俄罗斯方块(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;
}

浙公网安备 33010602011771号