[原创] 200 行代码,实现了一个功能基本完备的俄罗斯方块游戏
程序代码:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <conio.h> #include <time.h> #ifdef WIN32 #include <windows.h> #define usleep(t) Sleep((t)/1000) #define kbhit _kbhit #define getch _getch #endif static int g_all_bricks[7][4][18] = { { { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1 }, { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 4 }, { 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1 }, { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 4 }, }, { { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, }, { { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3 }, }, { { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 }, { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 }, { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 }, { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 }, }, { { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3 }, }, { { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3 }, { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3 }, }, { { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2 }, { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 3 }, }, }; static void draw_game(int board[20][10], int curbricks[16], int curx, int cury, int nextbricks[16], int level, int score, int lines, int history, int gameover) { int i, j, c; system("cls"); for (i=0; i<20; i++) { for (j=0; j<10; j++) { c = board[i][j] == 1 ? 'B' : board[i][j] == 2 ? 'x' : '.'; if (j>=curx && j<curx+4 && i>=cury && i<cury+4) { int tx = j - curx, ty = i - cury; if (curbricks[ty * 4 + tx]) { c = 'B'; } } printf("%c ", c); } switch (i) { case 0 : printf(" next:"); break; case 7 : printf(" level : %d", level ); break; case 9 : printf(" score : %d", score ); break; case 11: printf(" lines : %d", lines ); break; case 13: printf(" history: %d", history); break; case 15: printf("%s", gameover ? " game over !" : ""); break; case 16: printf("%s", gameover ? " press R to again." : ""); break; case 18: printf(" ffbricks v1.0.0"); break; case 19: printf(" writen by chenk"); break; } if (i >= 2 && i <= 5) { printf(" "); for (j=0; j<4; j++) { int tx = j, ty = i - 2; printf("%c ", nextbricks[ty * 4 + tx] ? 'B' : ' '); } } printf("\n"); } printf("-------------------"); } static int check_collision(int board[20][10], int bricks[16], int curx, int cury) { int i, j; for (i=0; i<20; i++) { for (j=0; j<10; j++) { if (j>=curx && j<curx+4 && i>=cury && i<cury+4) { int tx = j - curx, ty = i - cury; if (board[i][j] && bricks[ty * 4 + tx]) return 1; } } } return 0; } static void copy_bricks_to_board(int board[20][10], int bricks[16], int curx, int cury) { int i, j; for (i=0; i<20; i++) { for (j=0; j<10; j++) { if (j>=curx && j<curx+4 && i>=cury && i<cury+4) { int tx = j - curx, ty = i - cury; if (bricks[ty * 4 + tx]) { board[i][j] = 1; } } } } } static int mark_full_rows(int board[20][10]) { int i, j, l = 0; for (i=0; i<20; i++) { for (j=0; j<10; j++) { if (!board[i][j]) { break; } } if (j == 10) { l++; for (j=0; j<10; j++) board[i][j] = 2; } } return l; } static void remove_full_rows(int board[20][10]) { int i, j, f, m; for (i=19,m=19; i>=0 && m>=0; m--) { for (f=0,j=0; j<10; j++) { if ( board[m][j] == 1) { f = 1; break; } } if (f) { for (j=0; j<10; j++) board[i][j] = board[m][j]; i--; }; } for (; i>=0; i--) for (j=0; j<10; j++) board[i][j] = 0; } int main(void) { int board[20][10] = {0}; int type, rot, next, nrot, posx, posy, newx, newy, newr, collision, speed; int remove = 0, score = 0, lines = 0, level = 0, history = 0, gameover = 0; int quit = 0, key = 0, counter = 0, dirty = 1; srand((unsigned int)time(NULL)); type = rand()%7, rot = rand()%4, posx = rand()%6, posy = 0, next = rand()%7, nrot = rand()%4; while (!quit) { if (dirty) { draw_game(board, g_all_bricks[type][rot], posx, posy, g_all_bricks[next][nrot], level, score, lines, history, gameover); dirty = 0; } if (remove) { remove_full_rows(board); remove = 0; usleep(10*1000); } if (!kbhit()) { usleep(16*1000); if (gameover) continue; speed = 60 - 58 * level / 10; if (speed < 2) speed = 2; if (++counter % speed == 0) { key = 'd'; } else continue; } else key = getch(); if (gameover) { if (key == 'R' || key == 'r') { memset(board, 0, sizeof(board)); score= 0, lines = 0, level = 0, gameover = 0; } else continue; } newx = posx; newy = posy; newr = rot; dirty = 1; switch (key) { case 'Q': case 'q': quit = 1; break; case 'S': case 's': if (newx > 0) newx--; break; case 'F': case 'f': newx++; break; // case 'E': case 'e': if (newy > 0) newy--; break; case 'D': case 'd': newy++; break; case 'J': case 'j': newr++; newr %= 4; break; case 'K': case 'k': while (++newy + g_all_bricks[type][newr][17] <= 20 && !check_collision(board, g_all_bricks[type][newr], newx, newy)); posy = newy - 1; break; } collision = check_collision(board, g_all_bricks[type][newr], newx, newy); if ( newx + g_all_bricks[type][newr][16] <= 10 && newy + g_all_bricks[type][newr][17] <= 20 && !collision) { posx = newx; posy = newy; rot = newr; } else if (key == 'D' || key == 'd' || key == 'K' || key == 'k') { copy_bricks_to_board(board, g_all_bricks[type][rot], posx, posy); remove = mark_full_rows(board); lines += remove; score += remove * remove; level = score / 100; history = history > score ? history : score; type = next, rot = nrot, posx = rand()%6, posy = 0; next = rand()%7; nrot = rand()%4; gameover = check_collision(board, g_all_bricks[type][rot], posx, posy); } } return 0; }