俄罗斯方块(Tetris)
源自: http://hi.baidu.com/misaka20001/blog/item/a854150a49b6b9d87bcbe1b6.html#0
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> char *gcText[] = {"■", "□", "□", "□", "□", "□", "□", "□"}; struct tetris { int x, y, s, st, t; int _pool[16][32], (*pool)[32], tmap[8][4][16]; } gt; void trsInit(){ // 方块形状定义 7种方块 4个方向, 采用4x4的方阵 二进制01存储 int sp[8][4] = {{15,4369},{23,785,116,547},{71,275,113,802}, {39,305,114,562},{54,561},{99,306},{51,51}, {-1/*结束标志*/}}; int *p, i, j, b; // 补满四个方向 for(p = sp[0]; *p >= 0; ++ p) if(!*p) *p = p[-2]; // 4x4图形, 值对应gcText中的符号, 索引从1-7, 0为游戏区域 for(j = 0; j < 7; ++j) for(i = 0; i < 4; ++i) for(b = 0; b < 16; ++b) gt.tmap[j+1][i][b] = (sp[j][i] & 1) * (j + 1), sp[j][i] >>= 1; // 游戏区域(10 x 21)/边界 gt.pool = >._pool[4]; memset(gt._pool, -1, sizeof(gt._pool)); // 边界填充为 -1 表示不绘制 for(i = 0; i < 10; ++i) memset(gt.pool[i], 0, sizeof(int[21])); // 游戏区域 填充为0对应gcText中的符号 } // 游戏区域符号操作, sp代表方块, c表示操作类型 0 简单的碰撞检测, 1 填充, 2 清空 int trsCopy(int sp[], int x, int y, int c){ int i, cx, cy; for(i = 0; i < 16; ++i) if(sp[i]){ cx = x + (i & 3), cy = y + (i >> 2); if(gt.pool[cx][cy]) // 已被占用 if(c == 2) // 清空 gt.pool[cx][cy] = 0; else // 返回 失败 return 0; if(c == 1) // 未被占用 并且填充 gt.pool[cx][cy] = sp[i]; } return 1; } int trsScene(){ int x, y = 0, k = 0; COORD pos = {0}; gt.s = rand() % 7 + 1, gt.st = gt.t = 0; gt.x = 3, gt.y = 0; // x, y为方块4x4第一元素的位置, 整个区域宽10, 高21 for(--gt.t; ;Sleep(1), --gt.t, k = 0){ while( kbhit() ){ //k = getche(); k = getch(); switch(k){ case 27: return 0; case 'A': case 'a': if(trsCopy(gt.tmap[gt.s][gt.st], gt.x - 1, gt.y, 0)) --gt.x; break; case 'D': case 'd': if(trsCopy(gt.tmap[gt.s][gt.st], gt.x + 1, gt.y, 0)) ++gt.x; break; case 'W': case 'w': if(trsCopy(gt.tmap[gt.s][(gt.st+1)%4], gt.x, gt.y, 0)) gt.st = (gt.st+1)%4; break; } } if(k == 's' || k == 'S' || gt.t < 0){ // 降落 if(trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y + 1, 0)) // 检测填充 ++gt.y, gt.t = 50; else { // 填充, 判断整行并清除 trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 1); if(y == 0) return 0; // game over, y == 0 or y == 21 for(--y; y > 0; --y){ for(x = 0; gt.pool[x][y] > 0; ++x) ; if(gt.pool[x][y] < 0) // 表明循环到边界了, 是整行可以清除 for(k = y++; k > 0; --k) for(x = 0; gt.pool[x][0] >= 0; ++x) gt.pool[x][k] = gt.pool[x][k - 1]; } return 1; } } // 填充-绘制-清空 trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 1); SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); for(y = 1; gt.pool[0][y] >= 0; ++y, putchar(10)) // 绘制从[0~9][1~20] for(x = 0; gt.pool[x][0] >= 0; ++x) printf(gcText[gt.pool[x][y]]); trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 2); } return 1; } int main(int argv, char** argc){ srand(time(NULL)); for(trsInit(); trsScene();); printf("Game Over\n"); system("pause"); return 0; }