俄罗斯方块C程序源代码

合集下载

俄罗斯方块C语言代码

俄罗斯方块C语言代码

【转载】88行代码实现俄罗斯方块游戏(含讲解)来源:/p/8在正式阅读本文之前,请你记得你应该用娱乐的心态来看,本代码所使用到的技巧,在工作了的人眼里会觉得很纠结,很蛋疼,很不可理喻,很丑,注意,是你蛋疼,不关我的事通常,写一个俄罗斯方块,往往动不动就几百行,甚至上千行,而这里只有88行正所谓头脑风暴,打破常规。

这里将使用很多不平常的手段来减少代码以下是Win-TC可以成功编译并执行的代码(代码保证单行长度不超过80字符,如果你是Win7系统,那请看后文):程序代码:#include"graphics.h"#include<conio.h>#include<stdlib.h>int gcW = 20, gcColor[] = {DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN,LIGHTRED, LIGHTMAGENTA,MAGENTA, YELLOW};struct tetris {int _pool[16][32], (*pool)[32], tmap[8][4][16];int x, y, s, st, t;}gt;void trsInit() {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 == 0 ) *p = p[-2];gt.pool = &gt._pool[4];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;memset(gt._pool, -1, sizeof(gt._pool));for (i = 0; i < 10; ++i)memset(&gt.pool[i], 0, sizeof(int[21]));return ;}int trsCopy(int sp[], int x, int y, int c) {int m[] = {0,32,64,96,1,33,65,97,2,34,66,98,3,35,67,99}, i, cx, cy;for (i = 0; i < 16; ++i) if (sp[i]) {cx = x + (m[i] >> 5), cy = y + (m[i] & 31);if (gt.pool[cx][cy]) if (c == 2) gt.pool[cx][cy] = 0; else return0;if (c==1) gt.pool[cx][cy] = sp[i];}return1;}int trsScene() {int x, y = 0;gt.s = random(7) + 1, gt.st = gt.t = 0;gt.x = 4, gt.y = 0;for (--gt.t ; ; delay(10), --gt.t) {int k = 0;while (kbhit()) {k = getch();if (k == 27) return0;if (k == 'A' || k == 'a') {if (trsCopy(gt.tmap[gt.s][gt.st], gt.x-1, gt.y, 0)) --gt.x;} else if (k == 'D' || k == 'd') {if (trsCopy(gt.tmap[gt.s][gt.st], gt.x+1, gt.y, 0)) ++gt.x;} else if (k == 'W' || k == 'w') {if (trsCopy(gt.tmap[gt.s][(gt.st+1) % 4], gt.x, gt.y, 0))gt.st = (gt.st+1) % 4;}}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);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];}return1;}}trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 1);for (x = 0; gt.pool[x][0] >= 0; ++x) {for (y = 1; gt.pool[x][y] >= 0; ++y) {setfillstyle(1, gcColor[gt.pool[x][y]]);bar(201 + x*gcW, 1 + y*gcW, 200 + gcW + x*gcW, gcW + y*gcW); }}trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 2);}}int main() {int g = DETECT, m = 0;initgraph(&g, &m, "");randomize();trsInit();while (trsScene());return0;}如果你没有Win-TC,或者你是Win7系统,可以用这个能用VC6编译的工程包:以上是图形界面版本,显示看起来好看一些但为了能更通用,还有一份控制台版本的代码,同样是88行,直接复制到VC即可编译:程序代码:#include<windows.h>#include<stdio.h>#include<time.h>#include<conio.h>#include<stdlib.h>char gcText[] = " 1LJTSZ#";struct tetris {int _pool[16][32], (*pool)[32], tmap[8][4][16];int x, y, s, st, t;}gt;void trsInit() {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 == 0 ) *p = p[-2];gt.pool = &gt._pool[4];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;memset(gt._pool, -1, sizeof(gt._pool));for (i = 0; i < 10; ++i)memset(&gt.pool[i], 0, sizeof(int[21]));return ;}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 return0;if (c==1) gt.pool[cx][cy] = sp[i];}return1;}int trsScene() {int x, y = 0;COORD pos = {0};gt.s = rand() % 7 + 1, gt.st = gt.t = 0;gt.x = 3, gt.y = 0;for (--gt.t; ; Sleep(1), --gt.t) {int k = 0;while (kbhit()) {k = getch();if (k == 27) return0;if (k == 'A' || k == 'a') {if (trsCopy(gt.tmap[gt.s][gt.st], gt.x-1, gt.y, 0)) --gt.x;} else if (k == 'D' || k == 'd') {if (trsCopy(gt.tmap[gt.s][gt.st], gt.x+1, gt.y, 0)) ++gt.x;} else if (k == 'W' || k == 'w') {if (trsCopy(gt.tmap[gt.s][(gt.st+1) % 4], gt.x, gt.y, 0))gt.st = (gt.st+1) % 4;}}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);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];}return1;}}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)) {for (x = 0; gt.pool[x][0] >= 0; ++x) {putchar(gcText[gt.pool[x][y]]);}}trsCopy(gt.tmap[gt.s][gt.st], gt.x, gt.y, 2);}}int main() {srand((unsigned)time(NULL));for (trsInit(); trsScene(); );return0;}区别仅仅是绘画用的函数不同而已,不过控制台版显示效果自然会差很多了当你玩下去,你如果堆放到最顶,输了的话,程序就会以最为华丽的方式:Crash(程序崩溃)谢幕======================================华丽的分割线========================================以下是对代码的压缩方法进行分析首先,通常我们需要准备7种方块,4个方向的形状表,相当多的俄罗斯方块程序就是在开头写了这样一个很长的数组定义,有的光这个定义就直接超100行了,这个程序是怎么实现的呢?其实这个程序,同样是使用一个7*4*16的数组来保存这个形状表,但是,它没有直接初始化,见这个数组的定义: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}};这个莫名其妙的数组的值是什么意思呢?其实很好猜的,我们尝试把这些数化为二进制:15 = 11114369 = 1000100010001合理地四位四位拆开,从低位到高位,从左到右,从上到下排列一下:11110000000000001000100010001000你终于发现,这就是长条方块的两个形状后面类似然后你会发现,这个数组并不完整,有的只定义了两个形状,有的是四个形状,没定义的数会默认置0的,这个怎么解释?看这个数组定义的下面第二行:for (p = sp[0]; *p >= 0; ++p) if ( *p == 0 ) *p = p[-2];意思是找出这个数组为0的元素,用它前面的元素值填上即*p = p[-2]而数组中最后一个元素值-1起监督头的作用,用于让这个循环跳出虽然可以把这些常数全直接写在数组里,但常数太多显得不太好,就这样写了之后你看到这行代码:gt.pool = &gt._pool[4];为什么定义两个pool呢?因为我们需要在原来的pool的界外用-1值填充,以便后面做碰撞检测减少不必要的代码但如果直接用原来的_pool,那每次访问都要加上一个偏移常数,不美观且显得代码长,就用另一个指针直接指向开始的位置然后,后面的三重循环就是解开那个位压缩数组以初始化gt.tmap数组,这个数组就是记录7*4种形状的数组再下面三行,就是初始化pool,游戏区为0,界外为-1而其中,i < 10决定了游戏池的宽度为10,sizeof(int[21])决定了游戏池的高度是20 (0我们不使用,这一行有特殊作用,后文会讲)用memset也是为了免写二重循环而已。

C语言编写控制台版俄罗斯方块源码

C语言编写控制台版俄罗斯方块源码

C语言编写控制台版俄罗斯方块源码#include#include#include#include#include#includetypedef unsigned char uint8;typedef unsigned short uint16;typedef unsigned int uint32;typedef uint8 bool;#define APP_WIDTH 20#define APP_HEIGHT 20#define APP_MIN_X 8#define APP_MAX_X (APP_MIN_X + ((APP_WIDTH + 1) * 2)) #define APP_MIN_Y 3#define APP_MAX_Y (APP_MIN_Y + ((APP_HEIGHT + 1)))#define MAP_WIDTH 10#define MAP_HEIGHT 20#define MAP_MIN_X (APP_MIN_X + 2)#define MAP_MAX_X (MAP_MIN_X + (MAP_WIDTH *2))#define MAP_MIN_Y (APP_MIN_Y + 1)#define MAP_MAX_Y (MAP_MIN_Y + (MAP_HEIGHT))#define CTRL_WIDTH 8#define CTRL_HEIGHT 18#define CTRL_MIN_X (MAP_MAX_X + 2)#define CTRL_MAX_X (CTRL_MIN_X + (CTRL_WIDTH *2)) #define CTRL_MIN_Y (MAP_MIN_Y )#define CTRL_MAX_Y (MAP_MAX_Y - 1)#define BLOCK_WIDTH 4#define BLOCK_HEIGHT 4#define BLOCK_MIN_X (MAP_MIN_X + 6)#define BLOCK_MAX_X (MAP_MAX_X - 6)#define BLOCK_MIN_Y (MAP_MIN_Y )#define BLOCK_MAX_Y (MAP_MIN + 4)#define BLOCK_NUM 7#define BLOCK_DIR 4#define DIR_NONE 0#define DIR_UP 1#define DIR_DOWN 2#define DIR_LEFT 3#define DIR_RIGHT 4#define JK_FUNC_KEY 0x00#define JK_CTRL_KEY 0xE0#define JK_ESC 0x001B#define JK_ENTER 0x000D#define JK_SPACE 0x0020#define JK_BKSPACE 0x0008#define JK_TAB 0x0009#define JK_CTRL_Z 0x001A #define JK_CTRL_X 0x0018 #define JK_CTRL_C 0x0003 #define JK_CTRL_A 0x0001 #define JK_CTRL_S 0x0013 #define JK_CTRL_D 0x0004#define JK_LEFT 0xE04B #define JK_RIGHT 0xE04D #define JK_UP 0xE048#define JK_DOWN 0xE050 #define JK_INSERT 0xE052 #define JK_HOME 0xE047 #define JK_PGUP 0xE049 #define JK_DELETE 0xE053 #define JK_END 0xE04F#define JK_PGDW 0xE051#define JK_F1 0xFF3B#define JK_F2 0xFF3C#define JK_F3 0xFF3D#define JK_F4 0xFF3E#define JK_F5 0xFF3F#define JK_F6 0xFF40#define JK_F7 0xFF41#define JK_F8 0xFF42#define JK_F9 0xFF43#define JK_F10 0xFF44#define JK_F11 0xE085#define JK_F12 0xE086#define IS_BOX_IN_BLOCK(n,d,r,c) (BlockTable[(n)][(d)] & (0x00008000>> ((r) *BLOCK_WIDTH + (c))))// 各方块的码表,高16位为旋转掩码,低16位为方块的扫描码static uint32 BlockTable[BLOCK_NUM][BLOCK_DIR] ={{0xEE206C00, 0x66E04620, 0x8EE006C0, 0xECC08C40}, //S{0xE660C600, 0x2EE02640, 0xEE800C60, 0xCCE04C80}, //Z{0xECC088C0, 0xEE20E800, 0x66E06220, 0x8EE002E0}, //L{0x2EE02260, 0xCCE008E0, 0xEE80C880, 0xE660E200}, //J{0x7FCC4444, 0xEF330F00, 0x33FE2222, 0xCCF700F0}, //I{0xCC00CC00, 0xCC00CC00, 0xCC00CC00, 0xCC00CC00}, //O {0xE620E400, 0x26E02620, 0x8CE004E0, 0xEC808C80} //T};#define PRINT_BOX(bs) printf("%2s", BlockSharps[bs])#define IS_IN_MAP(x,y) (((x) >= MAP_MIN_X && (x) < MAP_MAX_X) && ( (y) >=MAP_MIN_Y && (y) < MAP_MAX_Y))#define IS_EMPTY_IN_MAP(x,y) ((MapTable[(y)][(x)]& 0x0F) == 0)char BlockSharps[2][4] = {" ", "■"};typedef struct POINTBLOCK{int x;int y;uint16 blocks;}PointBlock;static uint8 MapTable[30][30] = {{0}};void DrawMap (void);void gotoxy (int x, int y);void DrawBlock (PointBlock *block);uint16 CreateNewBlock (void);uint16 JkGetKey(void);bool JkHasKey(void);void FallDownBlock (PointBlock *nowpos, int *dir);void MoveBlock (PointBlock *nowpos, int * nowdir);void IniBlock (PointBlock *nowpos, PointBlock *nextpos);int CanRotate (int x, int y, uint16 block);int CanMove (int x, int y, uint16 block);void RedrawBlockInMap (int x, int y);int DropBlock (PointBlock *nowpos, PointBlock *nextpos, int *nowspeed, int *level, int *score, int *layer);void ErasePrevBlock(PointBlock *block);void KillLines (int col, int *nowspeed, int *level, int * score, int *layer);void RedrawALLBlock (int floor);void DrawBlockMenu (void);void printscore (int *score, int * layer, int *level);int setCursorVisible(int b);int Menu(void);int SetDifficulty(int *diff);int setCursorVisible(int b){HANDLE hd = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO ccInfo; GetConsoleCursorInfo(hd, &ccInfo);ccInfo.bVisible = !!b;return SetConsoleCursorInfo(hd, &ccInfo);}int main (void){int over = 0;int nowdir = DIR_NONE;int pause = 1;int speed = 900;int layer = 0;int score = 0;int level = 1;static PointBlock thisblock;static PointBlock nextblock;SetConsoleTitle ("仿写版俄罗斯方块"); setCursorVisible (0);level = Menu();if (level == 0){over = 0;ShowBye ();return 0;}speed = 1000 - level * 100;if (speed < 100)speed = 100;system ("cls");srand ((unsigned)time (NULL));DrawMap ();DrawBlockMenu();printscore(&score, &layer, &level);IniBlock(&thisblock, &nextblock);while (!over){if (!pause){MoveBlock (&thisblock, &nowdir);if (!DropBlock(&thisblock, &nextblock, &speed, &level, &score, &layer)){over = 1;break;}}if (JkHasKey ()){switch (JkGetKey()){case JK_UP:nowdir = DIR_UP;break;case JK_DOWN:nowdir = DIR_DOWN;break;case JK_LEFT:nowdir = DIR_LEFT;break;case JK_RIGHT:nowdir = DIR_RIGHT;break;case JK_ENTER:pause = !pause;break;case JK_ESC:over = 1;break;case JK_SPACE:if (!pause)FallDownBlock (&thisblock, &nowdir); break;default:break;}fflush(stdin);}}system ("cls");if ('y' == ShowOver(&score))return main();system ("cls");ShowBye();return 0;}void gotoxy (int x, int y){COORD pos;pos.X = x;pos.Y = y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HA NDLE),pos);}void DrawMap (void){int i, j;//draw APPgotoxy (APP_MIN_X, APP_MIN_Y);printf ("┏");for (i = 0; i < APP_WIDTH; i++)printf ("━");printf ("┓");for (i = 0; i < APP_HEIGHT; i++){gotoxy (APP_MIN_X, APP_MIN_Y + i + 1); printf ("┃");gotoxy (APP_MAX_X, APP_MIN_Y + i +1);printf ("┃");}gotoxy (APP_MIN_X, APP_MAX_Y);printf ("┗");for (i = 0; i < APP_WIDTH; i++)printf ("━");printf ("┛");//draw mapfor (i = 0; i < MAP_WIDTH; i++){for (j = 0; j < MAP_HEIGHT; j++){gotoxy ((MAP_MIN_X + (i * 2)), MAP_MIN_Y + j); printf (" ");}}// draw ctrlgotoxy (CTRL_MIN_X -2, CTRL_MIN_Y);p rintf ("┌");gotoxy (CTRL_MAX_X, CTRL_MIN_Y);printf ("┐");gotoxy (CTRL_MAX_X, CTRL_MAX_Y);printf ("┘");gotoxy (CTRL_MIN_X-2, CTRL_MAX_Y);printf ("└");for (i = 0; i < CTRL_WIDTH; i++){gotoxy (CTRL_MIN_X + (i * 2), CTRL_MIN_Y); printf ("─");gotoxy (CTRL_MIN_X + (i * 2), CTRL_MIN_Y + 5); printf ("─");gotoxy (CTRL_MIN_X + (i * 2), CTRL_MAX_Y); printf ("─");}for (i = 0; i < CTRL_HEIGHT; i++){gotoxy (CTRL_MIN_X - 2, CTRL_MIN_Y + 1 + i); printf ("│");gotoxy (CTRL_MAX_X, CTRL_MIN_Y +1 + i); printf ("│");}gotoxy(CTRL_MIN_X - 2, CTRL_MIN_Y + 5);printf ("├");gotoxy(CTRL_MAX_X, CTRL_MIN_Y + 5);printf ("┤");}uint16 CreateNewBlock (void){uint8 blocknum = (rand () + 255) % BLOCK_NUM; uint8 blockdir = 0;return ((blocknum << 4) | (blockdir));void DrawBlock (PointBlock *block){uint8 blocknum = (block->blocks & 0x00f0) >> 4; uint8 blockdir = (block->blocks & 0x000f);int i, j;for (i = 0; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){if(IS_BOX_IN_BLOCK(blocknum, blockdir, i, j)) {gotoxy (block->x + j *2, block->y + i);printf ("■");}}}}bool JkHasKey (void){bool k;if (kbhit ())k = 1;elsek = 0;return k;uint16 JkGetKey (){int rk = 0;int k = getch ();if (k == JK_FUNC_KEY){k = getch ();rk = 0xff00 | k;return rk;}if (k == JK_CTRL_KEY){k = getch ();rk = 0xe000 | k;return rk;}rk = 0x0000 |k;return rk;}void FallDownBlock(PointBlock * nowpos, int *dir ) {int hx = nowpos->x;int hy = nowpos->y;while (CanMove (hx, hy, nowpos->blocks))hy++;RedrawBlockInMap(nowpos->x, nowpos->y);nowpos->x = hx;nowpos->y = hy-1;DrawBlock(nowpos);*dir = DIR_NONE;}void MoveBlock (PointBlock *nowpos, int * nowdir) {int hx = nowpos->x;int hy = nowpos->y;uint16 theblock = nowpos->blocks;uint8 bd = theblock & 0x0f;if (*nowdir == DIR_NONE)return ;switch (*nowdir){case DIR_UP:if (CanRotate (hx, hy, theblock)){theblock &= 0xfff0;theblock |= (bd + 1) % BLOCK_DIR;}else{*nowdir = DIR_NONE;return;}break;case DIR_DOWN:hy++;break;case DIR_LEFT:hx -= 2;break;case DIR_RIGHT:hx += 2;break;default:break;}if (CanMove (hx, hy, theblock)){RedrawBlockInMap (nowpos->x, nowpos->y);nowpos->blocks = theblock;nowpos->x = hx;nowpos->y = hy;DrawBlock(nowpos);}*nowdir = DIR_NONE;}void IniBlock (PointBlock * nowpos, PointBlock * nextpos) {nextpos->x = 36;nextpos->y = 5;nextpos->blocks = CreateNewBlock ();DrawBlock (nextpos);nowpos->x = BLOCK_MIN_X;nowpos->y = BLOCK_MIN_Y;nowpos->blocks = CreateNewBlock ();DrawBlock (nowpos);}int CanRotate (int x, int y, uint16 block){int i, j;uint8 blocknum = (block & 0x00f0) >> 4;uint8 blockdir = block & 0x000f;int mx, my;for (i = 0; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){mx = x + j * 2;my = y + i;if (!IS_BOX_IN_BLOCK (blocknum, blockdir, i, j)) continue;if (!((IS_IN_MAP (mx, my)) && (IS_EMPTY_IN_MAP (mx, my)))) return 0;}}return 1;}int CanMove (int x, int y, uint16 block){int i, j;uint8 blocknum = (block & 0x00f0 ) >> 4;uint8 blockdir = block & 0x000f;int mx, my;for (i = 0; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){mx = x + j * 2;my = y + i;if (!IS_BOX_IN_BLOCK (blocknum, blockdir, i, j)) continue;if (!(IS_IN_MAP (mx, my) && IS_EMPTY_IN_MAP (mx, my))) return 0;}}return 1;}void RedrawBlockInMap (int x, int y){int i, j;int mx, my ;for (i = 0 ; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){mx = x + j * 2;my = y + i;if (IS_IN_MAP(mx, my) && IS_EMPTY_IN_MAP (mx, my)){gotoxy (mx, my);printf (" ");}}}}int DropBlock (PointBlock *nowpos, PointBlock *nextpos, int *nowspeed, int *level, int *score, int *layer){int hx = nowpos->x;int hy = nowpos->y;int i, j ;int mx, my;uint8 blocknum = (nowpos->blocks & 0x00f0) >> 4;uint8 blockdir = nowpos->blocks & 0x000f;static long lastclock = 0L;//Sleep (2000);if (clock() - lastclock > *nowspeed){lastclock = clock ();hy++;if (CanMove (hx, hy, nowpos->blocks)){RedrawBlockInMap(nowpos->x, nowpos->y);nowpos->x = hx;nowpos->y = hy;DrawBlock (nowpos);}else{for (i = 0; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){mx = nowpos->x + j * 2;my = nowpos->y + i;if (IS_BOX_IN_BLOCK (blocknum, blockdir, i, j) && IS_IN_MAP (mx, my)){MapTable[my][mx] = 1;}}}KillLines (nowpos->y, nowspeed, level, score, layer);for (j = 0; j < BLOCK_WIDTH; j++)if (MapTable[MAP_MIN_Y][j] != 0)return 0;nowpos->blocks = nextpos->blocks;ErasePrevBlock(nextpos);nextpos->blocks = CreateNewBlock ();nowpos->x = BLOCK_MIN_X;nowpos->y = BLOCK_MIN_Y;if (!CanMove (nowpos->x, nowpos->y, nowpos->blocks))return 0;DrawBlock (nowpos);DrawBlock (nextpos);}}return 1;}void ErasePrevBlock(PointBlock *block){int i, j;for (i = 0; i < BLOCK_HEIGHT; i++){for (j = 0; j < BLOCK_WIDTH; j++){gotoxy (block->x + j *2, block->y + i);printf (" ");}}}void KillLines(int col, int *nowspeed, int *level, int * score, int *layer){int i, j, k, line, flag, killblock = 0;for (i = 0; i < BLOCK_HEIGHT; i++){flag = 1;for (j = 0; j < MAP_WIDTH; j++){if (IS_EMPTY_IN_MAP (MAP_MIN_X + j*2, col + i)){flag = 0;break;}}if (flag){line = col + i;gotoxy (MAP_MIN_X, line);for (j = 0; j < MAP_WIDTH; j++){printf (" ");}for (k = line; k > 0; k--){for (j = 0; j < MAP_WIDTH ; j++){MapTable[k][MAP_MIN_X + j * 2] = MapTable[k-1][MAP_MIN_X + j * 2];}}killblock++;RedrawALLBlock (col + BLOCK_HEIGHT - 1);}}(*layer) += killblock;(*score) += (10 + killblock + (*level)) * killblock;if ((*layer) > (*level) * 10){(*score) += (*level) * 100;(*level)++;(*nowspeed) = 1000 - *level * 100;if ((*nowspeed) < 100)(*nowspeed) = 100;}printscore(score, layer, level);}void RedrawALLBlock (int floor){int i, j;if (floor >= MAP_HEIGHT +4)floor = MAP_HEIGHT + 3;for (i = floor; i >= 4; i--){for (j = 0; j < MAP_WIDTH; j++){gotoxy (MAP_MIN_X + j *2, i);PRINT_BOX(MapTable[i][MAP_MIN_X + j *2] & 0x0f); }}}void DrawBlockMenu (void){gotoxy (32, 11);printf ("LEVEL :");gotoxy (32, 13);printf ("SCORE :");gotoxy (32, 15);printf ("LAYER :");gotoxy (32, 17);printf ("PAUSE : ENTER");gotoxy (32, 19);printf ("EXIT : ESC");gotoxy (32, 21);printf (" By : MoYu");}void printscore (int *score, int * layer, int *level){gotoxy (38, 11);printf ("%d", *level);gotoxy (38, 13);printf ("%d", *score);gotoxy (38, 15);printf ("%d", *layer);}int Menu()//这里是菜单选择的界面{int choose = 5, ischoose = 1;int diff = 1, i;//display menu interfacesystem("cls");//clear screen首先清屏gotoxy (8,4);printf("************************************************\");gotoxy (8,5);printf(" Start game.\");gotoxy (8,6);printf(" Choose Difficulty.\");gotoxy (8,7);printf(" Quit.\");gotoxy (8,9);printf(" Warning:Please select English input method."); gotoxy (8,10);printf("\\");gotoxy (8,11);printf("************************************************\"); do{for(i = 5; i<= 7; i++){gotoxy(10, i);//光标移到(2,i)处if(i == choose)printf("%c",16);//这里显示的是选择的三角elseprintf(" ");}//get keydownswitch(JkGetKey()){//获取键盘按键,方向键只能通过扫描码获取case JK_UP:if (choose > 5)choose --;break;case JK_DOWN:if (choose < 7)choose++;break;case JK_ENTER:ischoose = 0;break;default:;}}while (ischoose);switch (choose){case 6:SetDifficulty(&diff);//选择难度的界面case 5:return diff;case 7:return 0;}return 0;}int SetDifficulty(int *diff)//显示选择难度的界面{assert (NULL != diff);system("cls");//to show set difficulty level interfacegotoxy(0, 6);printf("%c\\",30);//显示正三角printf(" %c\",31);//显示倒三角printf("\Please press UP or DOWN to choose difficulty level."); while (1){gotoxy(0, 7);printf("Difficulty level: %d",*diff);switch(JkGetKey()){//获取按键信息并选择难度case JK_UP:if (*diff > 1)(*diff) --;break;case JK_DOWN:if (*diff < 9)(*diff) ++;break;case JK_ENTER:return 0;default:;}}}int ShowOver (int *score){int key;gotoxy (16, 9);printf("================================"); gotoxy (16,10);printf(" GAME OVER");gotoxy (16,11);printf("================================"); gotoxy (16,13);printf(" YOU GOT SCORE: %u", *score);Sleep (2000);do{gotoxy (16, 10);printf(" Replay?(y/n) [ ]");do{gotoxy(41, 10);key = getche();}while('y'!=key && 'n'!=key);}while ('\' != getch());*score = 0;return key;}//显示再见void ShowBye (void){system ("cls");gotoxy (20, 9);printf("================================"); gotoxy (20,10);printf(" GOOD Bye!");gotoxy (20,11);printf("================================"); Sleep (2000);}。

俄罗斯方块c代码

俄罗斯方块c代码

/********************************************** 游戏名称:俄罗斯方块**********************************************/#ifndef BLOCK_H_H#define BLOCK_H_H#include<windows.h>#include<time.h>#include<iostream>using namespace std;#define WIDTH 10 //游戏区宽度#define HEIGHT 22 //游戏区高度#define SIZE 10 //方块大小#define KIND 8 //方块种类#define ID_LEFT 0#define ID_RIGHT 1#define ID_DOWN 2#define ID_UP 3#define ID_TIMER 4//八种方块struct BLOCK{WORD dir[4];COLORREF color;};//当前方块、下一方块struct BLOCKINFO{byte id:3;char x,y;byte dir:2;};enum DRAW{SHOW,//显示方块HIDE//隐藏方块};///////////定义函数////////////////void Init(HDC hdc); //初始化void NewGame(HDC hdc); //新游戏void GameOver(); //游戏结束void NewBlock(HDC hdc); //产生新方块bool CheckBlock(BLOCKINFO block); //检查是否可放下方块void DrawBlock(HDC hdc,BLOCKINFO block,DRAW draw); //画方块void OnRotate(HDC hdc); //旋转方块void Transform(HDC hdc); //变形方块void OnLeft(HDC hdc); //左移方块void OnRight(HDC hdc); //右移方块void OnDown(HDC hdc); //下移方块void OnSink(HDC hdc); //下沉方块#endif#include"BLOCK.h"//窗口句柄HWND Hwnd;bool start=true;int grade=0; //分数int level=1; //等级//文本TCHAR buf1[10],buf2[10];int len1=sprintf(buf1,"等级:%d",level);int len2=sprintf(buf2,"分数:%d",grade);//颜色COLORREFBLACK=RGB(0,0,0),RED=RGB(255,0,0),GREEN=RGB(0,255,0),BLUE=RGB(0,0,255),YELL OW=RGB(255,255,0),ORANGE=RGB(255,165,0),LA VENDER=RGB(230,230,250),GRAY=RG B(128,128,128),WHITE=RGB(255,255,255);//当前方块、下一方块BLOCKINFO g_curblock,g_nextblock;//八种方块BLOCK g_blocks[KIND]={{0x0F00,0x4444,0x0F00,0x4444,RED},{0x0660,0x0660,0x0660,0x0660,BLUE},{0x4460,0x02E0,0x0622,0x0740,GREEN},{0x2260,0x0E20,0x0644,0x0470,YELLOW},{0x0C60,0x2640,0x0C60,0x2640,ORANGE},{0x0360,0x4620,0x0360,0x4620,LA VENDER},{0x4E00,0x4C40,0xE40,0x4640,GRAY},{0x4E20,0x06C4,0x0472,0x2360,ORANGE}};//游戏区byte g_world[WIDTH][HEIGHT]={0};//游戏区颜色COLORREF color[WIDTH][HEIGHT]={0};//初始化游戏void Init(HDC hdc){grade=0; //分数level=1; //等级RECT rect;SetBkColor(hdc,BLACK);SetTextColor(hdc,WHITE);TextOut(hdc,(WIDTH+4)*SIZE,(HEIGHT-6)*SIZE,buf1,len1);TextOut(hdc,(WIDTH+4)*SIZE,(HEIGHT-8)*SIZE,buf2,len2);SetRect(&rect,-8.5*SIZE,(HEIGHT-2)*SIZE,-SIZE,(HEIGHT-3)*SIZE);SelectObject(hdc,GetStockObject(NULL_BRUSH));SelectObject(hdc,GetStockObject(WHITE_PEN));DrawText(hdc,TEXT("操作介绍"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("左移:左键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("右移:右键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("下移:下键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("下沉:空格键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("旋转:上键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("变形:Shift+上键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("暂停:回车键"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);OffsetRect(&rect,0,-2*SIZE);DrawText(hdc,TEXT("退出:Esc"),-1,&rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);Rectangle(hdc,0,0,WIDTH*SIZE,HEIGHT*SIZE);Rectangle(hdc,(WIDTH+4)*SIZE,HEIGHT*SIZE,(WIDTH+8)*SIZE,(HEIGHT-4)*SIZE);srand((unsigned)time(NULL));NewGame(hdc);}//游戏结束void GameOver(){KillTimer(Hwnd,ID_TIMER);if(IDYES==MessageBox(Hwnd,"是否重新开始","提示",MB_YESNO)){start=true;for(int i=0;i<WIDTH;i++){for(int j=0;j<HEIGHT;j++){color[i][j]=0;}}SetTimer(Hwnd,ID_TIMER,500,NULL);InvalidateRect(Hwnd,NULL,TRUE);}elseSendMessage(Hwnd,WM_DESTROY,0,0);}//新游戏void NewGame(HDC hdc){if(start){//清空游戏区ZeroMemory(g_world, WIDTH * HEIGHT);//生成下一方块g_nextblock.id=rand()%8;g_nextblock.dir=rand()%4;g_nextblock.x=WIDTH+4;g_nextblock.y=HEIGHT-1;}for(int i=0;i<WIDTH;i++){for(int j=0;j<HEIGHT;j++){if(color[i][j]){SelectObject(hdc,GetStockObject(WHITE_PEN));SelectObject(hdc,CreateSolidBrush(color[i][j]));}else{SelectObject(hdc,GetStockObject(BLACK_BRUSH));SelectObject(hdc,GetStockObject(BLACK_PEN));}RoundRect(hdc,i*SIZE,j*SIZE,(i+1)*SIZE,(j+1)*SIZE,0.25*SIZE,0.25*SIZE);}}NewBlock(hdc);}//产生新方块void NewBlock(HDC hdc){if(start){start=false;DrawBlock(hdc,g_nextblock,HIDE);g_curblock=g_nextblock;g_curblock.x=WIDTH/2-2;g_curblock.y=HEIGHT+2;g_nextblock.id=rand()%8;g_nextblock.dir=rand()%4;WORD c=g_blocks[g_curblock.id].dir[g_curblock.dir];while((c&0xF)==0){g_curblock.y--;c>>=4;}}DrawBlock(hdc,g_curblock,SHOW);DrawBlock(hdc,g_nextblock,SHOW);}//画方块void DrawBlock(HDC hdc,BLOCKINFO block,DRAW draw){WORD b=g_blocks[block.id].dir[block.dir];int x,y;COLORREF color;SelectObject(hdc,GetStockObject(NULL_BRUSH));SelectObject(hdc,GetStockObject(WHITE_PEN));Rectangle(hdc,0,0,WIDTH*SIZE,HEIGHT*SIZE);Rectangle(hdc,(WIDTH+4)*SIZE,HEIGHT*SIZE,(WIDTH+8)*SIZE,(HEIGHT-4)*SIZE); switch(draw){case SHOW:color=g_blocks[block.id].color;SelectObject(hdc,GetStockObject(WHITE_PEN));break;case HIDE:color=BLACK;SelectObject(hdc,GetStockObject(BLACK_PEN));break;}SelectObject(hdc,CreateSolidBrush(color));for(int i=0;i<16;i++){if(b&0x8000){x=block.x+i%4;y=block.y-i/4;if(y<HEIGHT){RoundRect(hdc,x*SIZE,y*SIZE,(x+1)*SIZE,(y+1)*SIZE,0.25*SIZE,0.25*SIZE); }}b<<=1;}SelectObject(hdc,GetStockObject(BLACK_BRUSH));SelectObject(hdc,GetStockObject(BLACK_PEN));}//检查是否可放下方块bool CheckBlock(BLOCKINFO block){WORD b=g_blocks[block.id].dir[block.dir];int x,y;for(int i=0;i<16;i++){if(b&0x8000){x=block.x+i%4;y=block.y-i/4;if((x<0)||(x>=WIDTH)||(y<0))return false;if((y<HEIGHT)&&(g_world[x][y]))return false;}b<<=1;}return true;}//左移方块void OnLeft(HDC hdc){BLOCKINFO tmp;tmp=g_curblock;tmp.x--;if(CheckBlock(tmp)){DrawBlock(hdc,g_curblock,HIDE);g_curblock.x--;DrawBlock(hdc,g_curblock,SHOW);}}//右移方块void OnRight(HDC hdc){BLOCKINFO tmp;tmp=g_curblock;tmp.x++;if(CheckBlock(tmp)){DrawBlock(hdc,g_curblock,HIDE);g_curblock.x++;DrawBlock(hdc,g_curblock,SHOW);}}//旋转方块void OnRotate(HDC hdc){int dx;BLOCKINFO tmp;tmp=g_curblock;tmp.dir++;if(CheckBlock(tmp)){dx=0;goto rotate;}tmp.x=g_curblock.x-1;if(CheckBlock(tmp)){dx=-1;goto rotate;}tmp.x=g_curblock.x+1;if(CheckBlock(tmp)){dx=1;goto rotate;}tmp.x=g_curblock.x-2;if(CheckBlock(tmp)){dx=-2;goto rotate;}tmp.x=g_curblock.x+2;if(CheckBlock(tmp)){dx=2;goto rotate;}return;rotate:DrawBlock(hdc,g_curblock,HIDE);g_curblock.dir++;g_curblock.x+=dx;DrawBlock(hdc,g_curblock,SHOW);}//变形方块void Transform(HDC hdc){int dx;BLOCKINFO tmp;tmp=g_curblock;tmp.id++;if(CheckBlock(tmp)){dx=0;goto transform;}tmp.x=g_curblock.x-1;if(CheckBlock(tmp)){dx=-1;goto transform;}tmp.x=g_curblock.x+1;if(CheckBlock(tmp)){dx=1;goto transform;}tmp.x=g_curblock.x-2;if(CheckBlock(tmp)){dx=-2;goto transform;}tmp.x=g_curblock.x+2;if(CheckBlock(tmp)){dx=2;goto transform;}return;transform:DrawBlock(hdc,g_curblock,HIDE);g_curblock.id++;g_curblock.x+=dx;DrawBlock(hdc,g_curblock,SHOW);}//下沉方块void OnSink(HDC hdc){int i,x,y;DrawBlock(hdc,g_curblock,HIDE);BLOCKINFO tmp=g_curblock;tmp.y--;while(CheckBlock(tmp)){g_curblock.y--;tmp.y--;}DrawBlock(hdc,g_curblock,SHOW);//判断是否结束游戏WORD b=g_blocks[g_curblock.id].dir[g_curblock.dir];for(i=0;i<16;i++){if(b&0x8000){if(g_curblock.y-i/4>=HEIGHT){GameOver();return;}else{g_world[g_curblock.x+i%4][g_curblock.y-i/4]=1;color[g_curblock.x+i%4][g_curblock.y-i/4]=g_blocks[g_curblock.id].color;}}b<<=1;}//判断是否消行int row[4]={0};bool brow=false;for(y=g_curblock.y;y>=(g_curblock.y>3?g_curblock.y-3:0);y--){i=0;for(x=0;x<WIDTH;x++){if(g_world[x][y]==1)i++;}if(i==WIDTH){brow=true;row[g_curblock.y-y]=1;grade+=10;}}//延时200毫秒Sleep(200);//消行if(brow){for(i=0;i<4;i++)if(row[i]){for(y=g_curblock.y-i+1;y<HEIGHT;y++)for(x=0;x<WIDTH;x++){g_world[x][y-1]=g_world[x][y];g_world[x][y]=0;color[x][y-1]=color[x][y];color[x][y]=0;}BitBlt(hdc,0,(g_curblock.y-i)*SIZE,WIDTH*SIZE,(HEIGHT-g_curblock.y+i-1)*SIZE-1,hdc ,0,(g_curblock.y-i+1)*SIZE,SRCCOPY);len2=sprintf(buf2,"分数:%d",grade);SetBkColor(hdc,BLACK);SetTextColor(hdc,WHITE);TextOut(hdc,(WIDTH+4)*SIZE,(HEIGHT-8)*SIZE,buf2,len2);}}if(grade/100&&(!(grade%100))){level+=1;len1=sprintf(buf1,"等级:%d",level);SetBkColor(hdc,BLACK);SetTextColor(hdc,WHITE);TextOut(hdc,(WIDTH+4)*SIZE,(HEIGHT-6)*SIZE,buf1,len1);KillTimer(Hwnd,ID_TIMER);SetTimer(Hwnd,ID_TIMER,500-30*level,NULL);}start=true;NewBlock(hdc);}//下移方块void OnDown(HDC hdc){BLOCKINFO tmp;tmp=g_curblock;tmp.y--;if(CheckBlock(tmp)){DrawBlock(hdc,g_curblock,HIDE);g_curblock.y--;DrawBlock(hdc,g_curblock,SHOW);}elseOnSink(hdc);}#include"BLOCK.h"HINSTANCE hinst;//窗口句柄extern HWND Hwnd;bool s=true;//窗口过程函数LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);/////////////////////////int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hpreInstance,LPSTR lpCmdLine,int nCmdShow){hinst=hInstance;WNDCLASS wndclass;wndclass.style=CS_HREDRAW|CS_VREDRAW;//类型wndclass.lpfnWndProc=WindowProc;//窗口过程函数wndclass.cbClsExtra=0;//存储附加信息wndclass.cbWndExtra=0;//wndclass.hInstance=hInstance;//程序的实例句柄wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);//图标(IDI_APPLICATION)wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);//光标wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);//获取系统画刷wndclass.lpszMenuName=NULL;//菜单名wndclass.lpszClassName="tetris";//窗口类名RegisterClass(&wndclass);//注册窗口//创建窗口HWND hwnd;hwnd=CreateWindow("tetris","俄罗斯方块",WS_OVERLAPPED|WS_SYSMENU|WS_MINIMIZEBOX,280,50,70*SIZE,60*SIZE,NULL,NULL,hInstance,NULL);//WS_OVERLAPPEDWINDOWHwnd=hwnd;//显示窗口ShowWindow(hwnd,nCmdShow);//更新窗口UpdateWindow(hwnd);MSG msg;BOOL bRet;while(bRet=GetMessage(&msg,NULL,0,0))//获取消息{if(bRet==-1)return -1;TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}//////////////////////////////////LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;LPDRAWITEMSTRUCT pdis;HDC hdc;static int cxClient,cyClient;static HWND hleft,hright,hup,hdown;POINT pt[3];switch (uMsg){case WM_SIZE:cxClient=LOWORD(lParam);cyClient=HIWORD(lParam);MoveWindow(hleft,53*SIZE,40*SIZE,3*SIZE,3*SIZE,TRUE);MoveWindow(hright,59*SIZE,40*SIZE,3*SIZE,3*SIZE,TRUE);MoveWindow(hup,56*SIZE,37*SIZE,3*SIZE,3*SIZE,TRUE);MoveWindow(hdown,56*SIZE,43*SIZE,3*SIZE,3*SIZE,TRUE);break;case WM_CREATE:SetTimer(hwnd,ID_TIMER,500,NULL);hleft=CreateWindow(TEXT("button"),TEXT(""),WS_CHILD|WS_VISIBLE|BS_OWNERD RAW,0,0,3*SIZE,3*SIZE,hwnd,(HMENU)ID_LEFT,hinst,NULL);hright=CreateWindow(TEXT("button"),TEXT(""),WS_CHILD|WS_VISIBLE|BS_OWNER DRAW,0,0,3*SIZE,3*SIZE,hwnd,(HMENU)ID_RIGHT,hinst,NULL);hdown=CreateWindow(TEXT("button"),TEXT(""),WS_CHILD|WS_VISIBLE|BS_OWNER DRAW,0,0,3*SIZE,3*SIZE,hwnd,(HMENU)ID_DOWN,hinst,NULL);hup=CreateWindow(TEXT("button"),TEXT(""),WS_CHILD|WS_VISIBLE|BS_OWNERD RAW,0,0,3*SIZE,3*SIZE,hwnd,(HMENU)ID_UP,hinst,NULL);break;case WM_PAINT:hdc=BeginPaint(hwnd,&ps);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);Init(hdc);EndPaint(hwnd,&ps);break;case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);switch (wmId){case 106:DestroyWindow(hwnd);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}break;case WM_TIMER:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);OnDown(hdc);ReleaseDC(hwnd,hdc);}break;case WM_KEYDOWN:switch(wParam){case VK_LEFT:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);OnLeft(hdc);ReleaseDC(hwnd,hdc);}SendMessage(hleft,BM_SETSTATE,1,0);break;case VK_RIGHT:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);OnRight(hdc);ReleaseDC(hwnd,hdc);}SendMessage(hright,BM_SETSTATE,1,0);break;case VK_UP:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);if(GetKeyState(VK_SHIFT)<0)Transform(hdc);elseOnRotate(hdc);ReleaseDC(hwnd,hdc);}SendMessage(hup,BM_SETSTATE,1,0);break;case VK_DOWN:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);OnDown(hdc);ReleaseDC(hwnd,hdc);}SendMessage(hdown,BM_SETSTA TE,1,0);break;case VK_SPACE:if(s){hdc=GetDC(hwnd);SetMapMode(hdc,MM_ISOTROPIC);SetWindowExtEx(hdc,250,250,NULL);SetViewportExtEx(hdc,cxClient,-cyClient,NULL);SetViewportOrgEx(hdc,20*SIZE,55*SIZE,NULL);OnSink(hdc);ReleaseDC(hwnd,hdc);}break;case VK_RETURN:if(s)s=false;elses=true;break;}break;case WM_KEYUP:switch(wParam){case VK_LEFT:SendMessage(hleft,BM_SETSTATE,0,0);break;case VK_RIGHT:SendMessage(hright,BM_SETSTATE,0,0);break;case VK_UP:SendMessage(hup,BM_SETSTA TE,0,0);break;case VK_DOWN:SendMessage(hdown,BM_SETSTA TE,0,0);break;}break;case WM_DRAWITEM:pdis=(LPDRAWITEMSTRUCT)lParam;FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)GetStockObject(BLACK_BRUSH));if(pdis->itemState&ODS_SELECTED)SelectObject(pdis->hDC,(HBRUSH)CreateSolidBrush(RGB(255,0,0)));elseSelectObject(pdis->hDC,(HBRUSH)CreateSolidBrush(RGB(255,255,255)));switch(pdis->CtlID){case ID_LEFT:pt[0].x=0;pt[0].y=1.5*SIZE;pt[1].x=3*SIZE;pt[1].y=0;pt[2].x=3*SIZE;pt[2].y=3*SIZE;break;case ID_RIGHT:pt[0].x=0;pt[0].y=0;pt[1].x=0;pt[1].y=3*SIZE;pt[2].x=3*SIZE;pt[2].y=1.5*SIZE;break;case ID_DOWN:pt[0].x=0;pt[0].y=0;pt[1].x=3*SIZE;pt[1].y=0;pt[2].x=1.5*SIZE;pt[2].y=3*SIZE;break;case ID_UP:pt[0].x=1.5*SIZE;pt[0].y=0;pt[1].x=0;pt[1].y=3*SIZE;pt[2].x=3*SIZE;pt[2].y=3*SIZE;break;}Polygon(pdis->hDC,pt,3);break;case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:KillTimer(hwnd,ID_TIMER);PostQuitMessage(0);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);}return 0;}。

俄罗斯方块-C代码

俄罗斯方块-C代码

俄罗斯⽅块-C代码声明:代码转⾃有兴趣的同学⼀起研习#include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#include<conio.h>#define SPACE 32#define LEFT 75#define RIGHT 77#define DOWN 80#define ESC 27#define Wall 2#define Box 1#define Kong 0#define FACE_X 29#define FACE_Y 20 //界⾯尺⼨void gotoxy(int x,int y); //移动光标int color(int c); //颜⾊void hidden_cursor(); //隐藏光标void inter_face(); //初始化界⾯void init_dia(); //初始化⽅块信息void draw_dia(int base,int space_c,int x,int y); //覆盖⽅块void draw_kong(int base,int space_c,int x,int y); //画⽅块int pd(int n,int space_c,int x,int y); //判断是否到底void start_game(); //开始游戏int xc();//消除void read_file(); //读写最⾼记录void write_file(); //写最⾼纪录int grade=0;//当前分数int max=0;//最⾼记录int nn=0;struct Face{int data[FACE_X][FACE_Y+10]; //数值,为1是⽅块,为0是空格int color[FACE_X][FACE_Y+10]; //对应⽅块的颜⾊}face;typedef struct Diamonds{ int space[4][4]; //4*4矩阵,为1为⽅块,为0 为空}Dia;Dia dia[7][4]; //⼀维基础7个⽅块,⼆维表⽰旋转次数int main(){system("cls");system("title 俄罗斯⽅块");color(7);system("mode con cols=60 lines=30"); //窗⼝宽度⾼度hidden_cursor();srand(time(NULL));read_file();grade=0;inter_face();init_dia();nn=rand()%7;while(1){start_game();}return 0;}/////////////////////////////////////////////////void start_game(){ int n,ch,t=0,x=0,y=FACE_Y/2-2,i,j;int space_c=0;//旋转次数draw_kong(nn,space_c,4,FACE_Y+3);n=nn;nn=rand()%7; //随机⽣成下⼀块color(nn);draw_dia(nn,space_c,4,FACE_Y+3);while(1){color(n);draw_dia(n,space_c,x,y);//画出图形if(t==0)t=15000;while(--t){ if(kbhit()!=0)//有输⼊就跳出break;}if(t==0){if(pd(n,space_c,x+1,y)==1){ draw_kong(n,space_c,x,y);x++; //向下降落}else{for(i=0;i<4;i++){for(j=0;j<4;j++){if(dia[n][space_c].space[i][j]==1){face.data[x+i][y+j]=Box;face.color[x+i][y+j]=n;while(xc());}}}return;}}else{ch=getch();switch(ch) //移动{case LEFT: if(pd(n,space_c,x,y-1)==1) //判断是否可以移动{ draw_kong(n,space_c,x,y);y--;}break;case RIGHT: if(pd(n,space_c,x,y+1)==1){ draw_kong(n,space_c,x,y);y++;}break;case DOWN: if(pd(n,space_c,x+1,y)==1){ draw_kong(n,space_c,x,y);x++;}break;case SPACE: if(pd(n,(space_c+1)%4,x+1,y)==1){ draw_kong(n,space_c,x,y);space_c=(space_c+1)%4;}break;case ESC : system("cls");gotoxy(FACE_X/2,FACE_Y);printf("---游戏结束!---\n\n");gotoxy(FACE_X/2+2,FACE_Y); printf("---按任意键退出!---\n");getch();exit(0);break;case 'R':case 'r': main();exit(0);case 'S':case 's': while(1){ if(kbhit()!=0)//有输⼊就跳出break;}break;}}}}int xc(){int i,j,k,sum;for(i=FACE_X-2;i>4;i--){sum=0;for(j=1;j<FACE_Y-1;j++){sum+=face.data[i][j];}if(sum==0)break;if(sum==FACE_Y-2) //满⼀⾏,减掉{grade+=100;color(7);gotoxy(FACE_X-4,2*FACE_Y+2); printf("分数:%d",grade);for(j=1;j<FACE_Y-1;j++){face.data[i][j]=Kong;gotoxy(i,2*j);printf(" ");}for(j=i;j>1;j--){ sum=0;for(k=1;k<FACE_Y-1;k++){sum+=face.data[j-1][k]+face.data[j][k]; face.data[j][k]=face.data[j-1][k];if(face.data[j][k]==Kong){gotoxy(j,2*k);printf(" ");}else{gotoxy(j,2*k);color(face.color[j][k]);printf("■");}}if(sum==0)return 1;}}}for(i=1;i<FACE_Y-1;i++)if(face.data[1][i]==Box){char n;Sleep(2000); //延时system("cls");color(7);gotoxy(FACE_X/2-2,2*(FACE_Y/3));if(grade>max){printf("恭喜您打破记录,⽬前最⾼纪录为:%d",grade); write_file();}else if(grade==max)printf("与纪录持平,请突破你的极限!");elseprintf("请继续努⼒,你与最⾼记录只差:%d",max-grade); gotoxy(FACE_X/2,2*(FACE_Y/3));printf("GAME OVER!\n");do{gotoxy(FACE_X/2+2,2*(FACE_Y/3));printf("是否重新开始游戏(y/n): ");scanf("%c",&n);gotoxy(FACE_X/2+4,2*(FACE_Y/3));if(n!='n' && n!='N' && n!='y' && n!='Y')printf("输⼊错误,请重新输⼊!");elsebreak;}while(1);if(n=='n' || n=='N'){gotoxy(FACE_X/2+4,2*(FACE_Y/3));printf("按任意键退出游戏!");exit(0);}else if(n=='y' || n=='Y')main();}}return 0;}//////////////////////////////////////////////void read_file() //读取最⾼记录{FILE *fp;fp=fopen("俄罗斯⽅块记录.txt","r+");if(fp==NULL){fp=fopen("俄罗斯⽅块记录.txt","w+");fwrite(&max,sizeof(int),1,fp);}fseek(fp,0,0);fread(&max,sizeof(int),1,fp);fclose(fp);}void write_file() //保存最⾼记录{FILE *fp;fp=fopen("俄罗斯⽅块记录.txt","r+");fwrite(&grade,sizeof(int),1,fp);fclose(fp);}///////////////////////////////////////////////int pd(int n,int space_c,int x,int y) //判断是否到底{int i,j;for(i=0;i<4;i++)for(j=0;j<4;j++){if(dia[n][space_c].space[i][j]==0)continue;else if(face.data[x+i][y+j]==Wall || face.data[x+i][y+j]==Box) return 0;}}return 1;}void draw_kong(int base,int space_c,int x,int y){int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){gotoxy(x+i,2*(y+j));if(dia[base][space_c].space[i][j]==1)printf(" ");}}}void draw_dia(int base,int space_c,int x,int y){int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){gotoxy(x+i,2*(y+j));if(dia[base][space_c].space[i][j]==1)printf("■");}}}void init_dia(){int i,j,k,z;int tmp[4][4];for(i=0;i<3;i++)dia[0][0].space[1][i]=1;dia[0][0].space[2][1]=1; //⼟形for(i=1;i<4;i++)dia[1][0].space[i][1]=1;dia[1][0].space[1][2]=1; //L形--1for(i=1;i<4;i++)dia[2][0].space[i][2]=1;dia[2][0].space[1][1]=1; //L形--2for(i=0;i<2;i++){ dia[3][0].space[1][i]=1;dia[3][0].space[2][i+1]=1; //Z形--1dia[4][0].space[1][i+1]=1;dia[4][0].space[2][i]=1;//Z形--2dia[5][0].space[1][i+1]=1;dia[5][0].space[2][i+1]=1;//⽥字形}for(i=0;i<4;i++)dia[6][0].space[i][2]=1;//1形//////////////////////////////////基础7个形状for(i=0;i<7;i++){for(z=0;z<3;z++){for(j=0;j<4;j++){for(k=0;k<4;k++){tmp[j][k]=dia[i][z].space[j][k];}}for(j=0;j<4;j++){for(k=0;k<4;k++){dia[i][z+1].space[j][k]=tmp[4-k-1][j];}}}}///////////////////////////////////旋转后的21个形状}//////////////////////////////////////void inter_face()//界⾯{ int i,j;for(i=0;i<FACE_X;i++){ for(j=0;j<FACE_Y+10;j++){ if(j==0 || j==FACE_Y-1 || j==FACE_Y+9) { face.data[i][j]=Wall;gotoxy(i,2*j);printf("■");}else if(i==FACE_X-1){ face.data[i][j]=Box;gotoxy(i,2*j);printf("■");}elseface.data[i][j]=Kong;}}gotoxy(FACE_X-18,2*FACE_Y+2); printf("左移:←");gotoxy(FACE_X-16,2*FACE_Y+2); printf("右移:→");gotoxy(FACE_X-14,2*FACE_Y+2); printf("旋转:space");gotoxy(FACE_X-12,2*FACE_Y+2); printf("暂停: S");gotoxy(FACE_X-10,2*FACE_Y+2); printf("退出: ESC");gotoxy(FACE_X-8,2*FACE_Y+2);printf("重新开始:R");gotoxy(FACE_X-6,2*FACE_Y+2);printf("最⾼纪录:%d",max);gotoxy(FACE_X-4,2*FACE_Y+2);printf("分数:%d",grade);}//////////////////////////////////////////////////void gotoxy(int x,int y) //移动坐标{COORD coord;coord.X=y;coord.Y=x;SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );}//////////////////////////////////////////////////void hidden_cursor()//隐藏光标{HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(hOut,&cci);cci.bVisible=0;//赋1为显⽰,赋0为隐藏SetConsoleCursorInfo(hOut,&cci);}int color(int c){switch(c){case 0: c=9;break;case 1:case 2: c=12;break;case 3:case 4: c=14;break;case 5: c=10;break;case 6: c=13;break;default: c=7;break;}SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改⽂字颜⾊return 0;}。

C语言程序设计-俄罗斯方块源程序

C语言程序设计-俄罗斯方块源程序

其中的主要逻辑有:(1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。

(2)得分越高,方块下降速度越快(每200分为单位)。

(3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。

初试分数为100分。

游戏控制:up-旋转;空格-下落到底;左右下方向键-控制方向。

P-开始或暂停游戏。

ESC-退出。

特点:(1)由于tc不支持中文,所以基本都是英文注释。

(2)函数命名尽可能规范的表达其内部处理目的和过程。

(3)代码加上注释仅有577行。

(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。

(4)除了消除空格时算法比较复杂,其他算法都比较简单易读。

(5)绘图效率和局部代码效率扔有待提高。

(6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。

俄罗斯方块源于大约9年前上大一时的一个梦,我们在学习c语言时,我的同寝室友邀请我合作一起完成俄罗斯方块(课外作业性质),但是当时限于我们的水平比较菜和学习状态比较懒散,我们没有完成。

大一的时候我在机房里无意发现别人留下的俄罗斯方块程序,运行,老师发现后激动的问我是我写的吗,我惭愧的摇摇头。

那时看到别人做c的大程序深感羡慕(自己只是写几十行的程序)。

数年后我仍然看到有不同样式的实现,但是我一直没有实现它,知道今天忽然有这个想法去做,算是弥补多年前的遗憾和心愿吧。

---------------------------------------------Q&A:----------------------------------------------Q:我编译时出现错误:fatal error C1083: Cannot open include file: 'bios.h': Nosuch file or directory,该如何解决?A:正文中的代码,是使用Borland公司的TC2.0编译的,编译结果运行在Windows的16位虚拟机上。

C51单片机12864液晶带按键制作俄罗斯方块C源码

C51单片机12864液晶带按键制作俄罗斯方块C源码

************说明******************************此程序包含一个俄罗斯方块.c 文件和一个12864.h 文件********************俄罗斯方块.c文件**************************#include "reg51.h"#include "12864.h"#define uchar unsigned char#define uint unsigned intstatic unsigned long Seed = 1;#define A 48271L#define M 2147483647L#define Q (M / A)#define R (M % A)sbit K1=P3^4;sbit K2=P3^5;sbit K3=P3^6;sbit K4=P3^7;unsigned int idata num[19+2]={0xfff,//第1行,最下面0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行0xfff//第21行,最上面};//定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列unsigned char code Block[28][2]={/** 口口口口口口* 口口口口* 口口口口口口*/{0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},/** 口口口口口口* 口口口口* 口口口口口口*/{0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},/** 口* 口口口口* 口口口*/{0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},/** 口口口* 口口口口* 口*/{0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},/** 口口* 口口口口口口口口* 口口口口口口*/{0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},/*口* 口* 口口口口口* 口*/{0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},/** 口口* 口口*/{0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}};#define PASSSCORE 20struct Jimu{unsigned int dat;char x;unsigned char y;unsigned char type;unsigned char change;}Sign[3];//积木结构体unsigned char SysFlag=0;#define NEWSIGNFLAG 0#define DEADFLAG 1#define PAUSEFLAG 2unsigned char Score=0;unsigned char Level=1;unsigned char DelayCnt=5;/*********************************************************/#define N 25/************************************伪随机数发生器*************************************/ double Random(void){long TmpSeed;TmpSeed=A*(Seed%Q)-R*(Seed/Q);if(TmpSeed>=0)Seed=TmpSeed;elseSeed=TmpSeed+M;return (double)Seed/M;}/************************************** 为伪随机数发生器播种***************************************/ void InitRandom(unsigned long InitVal){Seed=InitVal;}//延时子程序void Delay(unsigned int t){unsigned int i,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}/*********************************初始化MPU**********************************/void InitCpu(void){TMOD=0x0;TH0=0;TL0=0;TR0=1;ET0=1;EX1=1;EA=1;TCON|=0x04;}/**************************** welcome 游戏选择界面/**********************/void welcome(){Lcd_WriteStr(0,0,"欢迎来玩");Lcd_WriteStr(0,1,"俄罗斯方块");Lcd_WriteStr(0,2,"设置按K1");Lcd_WriteStr(0,2,"开玩按K2");}/*************俄罗斯方块部分/******************************画墙壁,初始化界面*******************************/void DrawBoard(void){unsigned char n;for(n=0;n<12;n++){Lcd_Rectangle(3*n,0,3*n+2,2,1);Lcd_Rectangle(3*n,60,3*n+2,62,1);}for(n=0;n<20;n++){Lcd_Rectangle(0,3*n,2,3*n+2,1);Lcd_Rectangle(33,3*n,35,3*n+2,1);}Lcd_WriteStr(4,0,"经典游戏");Lcd_WriteStr(3,2,"Score:");Lcd_WriteStr(3,3,"Level:");}/*********************************** 游戏结束处理************************************/ void GameOver(void){if((SysFlag&(1<<DEADFLAG))!=0)Lcd_WriteStr(3,1,"You Fail");elseLcd_WriteStr(3,1,"You Pass");}unsigned int code MaskTab[16]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};/**********************************根据积木图标左下坐标X,Y来画出积木图标***********************************/void DrawSign(struct Jimu Temp,unsigned char DrawMode){unsigned char m,n;for(m=0;m<4;m++)for(n=0;n<4;n++){if((Temp.dat&MaskTab[4*m+n])!=0)Lcd_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode);}}/********************************将积木图标值融入num数据中也即把积木图标固定,无法再下降*********************************/FixSign(void){unsigned char m,n;for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[4*m+n])!=0){num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n];}}}/********************************判断积木图标中方块是否与障碍方块重合*********************************/unsigned char CheckIf(void){unsigned char m,n;for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[1].dat&MaskTab[4*m+n])!=0){if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])!=0)return 0;}}return 1;}/********************************判断积木图标是否可以继续下降一格********************************/unsigned char CheckIfDown(void){Sign[1]=Sign[0];//Sign[1].y+=3;//假设下降一格return CheckIf();}/********************************判断积木图标是否可以向左移动*********************************/unsigned char CheckIfLeft(void){Sign[1]=Sign[0];Sign[1].x-=3;return CheckIf();}/********************************判断积木图标是否可以向右移动*********************************/unsigned char CheckIfRight(void){Sign[1]=Sign[0];Sign[1].x+=3;return CheckIf();}/********************************判断是否可以旋转*********************************/unsigned char CheckIfRoll(void){unsigned char i;unsigned int Temp;Sign[1]=Sign[0];if(++Sign[1].change>3)Sign[1].change=0;i=Sign[1].type*4+Sign[1].change;Temp=(unsigned int)Block[i][0]<<8;Temp=Temp|Block[i][1];Sign[1].dat=Temp;return CheckIf();}/********************************寻找满格的行并做消除处理最多寻找4个满行并做消除*********************************/void DelFull(void){unsigned char m,n;unsigned char Temp;unsigned char Flag=0;Temp=(Sign[0].y-2)/3;if(Temp>=20)//防止越过了下边界Temp=1;elseTemp=20-Temp;for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算{if(num[n]==0xfff){Flag=1;for(m=n+1;m<=19;m++){num[m-1]=num[m];}num[m]=0x801;Score++;//每找到一个满行,则分数加1}}if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面{for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画for(n=1;n<=10;n++){if((num[m]&MaskTab[n])==0){if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)!=0)//为加速而做的读象素操作{Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0);}}else{if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作{Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1);}}}}}/*******************************随机产生一个积木图标放到预产生区域并显示出来********************************/void CreatSign(void){unsigned char n;unsigned int Temp;DrawSign(Sign[2],0);//先清除n=Random()*28;Temp=(unsigned int)Block[n][0]<<8;Temp=Temp|Block[n][1];Sign[2].dat=Temp;Sign[2].x=45;Sign[2].y=4*3+2;Sign[2].type=n/4;Sign[2].change=n%4;DrawSign(Sign[2],1);//后画出}void PrintScore(void){unsigned char Str[3];Str[0]=(Score/10)|0x30;Str[1]=(Score%10)|0x30;Str[2]=0;Lcd_WriteStr(6,2,Str);}void PrintLevel(void){unsigned char Str[3];Str[0]=(Level/10)|0x30;Str[1]=(Level%10)|0x30;Str[2]=0;Lcd_WriteStr(6,3,Str);}/********************************游戏的具体过程,也是俄罗斯方块算法的关键部分*********************************/void GamePlay(void){unsigned char m,n;unsigned int Temp;SysFlag|=1<<NEWSIGNFLAG;//刚开始初始化为需要产生新的积木图标InitRandom(TL0);Lcd_WriteStr(3,1,"Playing");PrintScore();PrintLevel();CreatSign();while(1){if((SysFlag&(1<<NEWSIGNFLAG))==1)//判是否需要产生新的积木图标{SysFlag&=~(1<<NEWSIGNFLAG);Sign[0]=Sign[2];CreatSign();Sign[0].x=12;Sign[0].y=14;for(m=0;m<4;m++)//行循环{for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[15-m*4-n])==0)break;}if(n==4)Sign[0].y-=3;}//将积木图标出现置顶for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[4*m+n])!=0){if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])!=0)SysFlag|=1<<DEADFLAG;}}if((SysFlag&(1<<DEADFLAG))!=0)break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。

C++实现俄罗斯方块源码

C++实现俄罗斯⽅块源码本⽂实例为⼤家分享了C++实现俄罗斯⽅块的具体代码,供⼤家参考,具体内容如下先是效果图:主菜单:游戏:设置:错误处理:代码:#include <iostream.h>#include <conio.h>#include <stdio.h>#include <windows.h>#include <fstream.h>#include <time.h>#include <cstring>#pragma comment( lib,"winmm.lib" )//定义//⽅块#define NO 0#define SQR 1//碰撞检测#define OK 0#define CANTMOVE 1//⽅向#define UP 0#define DOWN 1#define LEFT 2#define RIGHT 3//错误码#define no_enough_memory 0#define set_no_found 1#define dat_no_found 2#define error_argument 3//函数声明//模块void play();//开始游戏void sets();//设置void highscores();//排⾏榜void copyright();//作者//功能void mapsetup();//准备地图bool newsqr();//放置⽅块,返回是否游戏结束int move(int direction);//移动⽅块,返回定义表void movetomap();//把当前⽅块移动到地图上int wholeline();//检查是否组成了⼀层,返回层数,-1表⽰没有void deleteline(int which);//删除⼀⾏void endup();//结束游戏,清理内存//显⽰void show();//刷新画⾯void showmenu(char* menu);//显⽰菜单//⽂件void loadset();//加载设置void saveset();//保存设置void loadhs();//加载排⾏榜bool addscores(int score,char name[50]);//增加⼀个分数,返回是否是⾼分void savehs();//保存排⾏榜//坐标变换int get(int x,int y);void set(int x,int y,int date);//结构//设置struct{int xs,ys;//屏幕⼤⼩int speed;//速度char sqr[3],no[3],frame[3];//⽅块、空⽩处、边框的样式}gameset;//排⾏榜struct{char name[50];int score;}rating[10];//全局变量//变量int* map=NULL;//地图bool now[4][4];//当前⽅块int xnow,ynow;//当前位置int guide;//分数//常量const bool shap[7][4][4]={//形状{\0,0,0,0,\0,0,0,0,\1,1,1,1,\0,0,0,0,\},\{\0,0,0,0,\0,1,1,0,\0,1,1,0,\0,0,0,0,\},\{\0,0,0,0,\0,1,1,1,\0,0,1,0,\0,0,0,0,\},\{\0,0,0,0,\1,0,0,0,\1,1,1,0,\0,0,0,0,\},\{\0,0,0,0,\0,0,0,1,\0,1,1,1,\0,0,0,0,\},\{\0,1,0,0,\0,1,1,0,\0,0,1,0,\0,0,0,0,\},\{\0,0,1,0,\0,1,1,0,\0,1,0,0,\0,0,0,0,\}\};const char errword[4][50]={"程序没能取得⾜够的内存","⽆法打开或找不到设置⽂件set.ini","⽆法打开或找不到排⾏榜数据highscore.dat","您设置的参数太⼤或者太⼩"}; //控制台HANDLE hout;//控制台句柄COORD curpos={0,0};//光标坐标//主函数int main(){start1:try{hout = GetStdHandle(STD_OUTPUT_HANDLE);//获取控制台句柄,以便移动光标srand(time(0));//⽤当前时间初始化随机数⽣成器loadset();//加载loadhs();start2:while(1){showmenu("俄罗斯⽅块\n请选择菜单:\n1.开始游戏\n2.设置\n3.排⾏榜\n4.帮助\n5.保存并退出\n");switch(getch()){case '1':system("cls");//play函数覆盖界⾯⽽不是清屏,所以需要先清屏play();break;case '2':sets();break;case '3':highscores();break;case '4':copyright();break;case '5':savehs();//保存数据saveset();return 0;}}}catch(int errnum)//错误处理{system("cls");printf("o(>﹏<)o 出错啦!\n程序收到了⼀条错误信息,错误码是:%d(%s)\n您可以联系我们解决这个问题。

c语言俄罗斯方块代码

#include<stdio.h>#include<stdlib.h>#include<graphics.h>#include<bios.h>/*下面定义了一些控制命令*//*重画界面命令*/#define CMDDRAW5/*消去一个满行的命令*/#define CMDDELLINE6/*自动下移一行的命令*/#define CMDAOTODOWN7/*生产新的方块*/#define CMDGEN8/*向左移动的命令,以左箭头<-控制,它的ASCII码值是75*/ #define CMDLEFTMOVE75/*向右移动的命令,以右箭头->控制,它的ASCII码值是77*/ #define CMDRINGHTMOVE 77/*旋转方块的命令,以空格来控制*/#define CMDROTATE57/*向下移动的命令,以向下的箭头控制,它的ASCII码值是80*/ #define CMDDOWNMOVE80/*退出游戏的控制命令,以esc键控制,它的ASCII码值是1*/#define CMDESC1/*定义了方块下降的时间间隔*/#define TIMEINTERVAL4/*下面定义了游戏区的大小*/#define MAXWIDTH15#define MAXHEIGHT30/*组成方块的小格子的宽度*/#define BOXWIDTH15/*用两个数组来表示新旧两个矩形游戏区*/int oldarea[MAXHEIGHT+1][MAXWIDTH];int area[MAXHEIGHT+1][MAXWIDTH];/*定义一个需要改变的屏幕区域,初次之外的区域不用进行重绘*/ int actW,actH,actX,actY;/*当前方块的一些属性(坐标,颜色,高,宽)*/int curX,curY,curColor,curW,curH;/*新的方块的一些属性(坐标,颜色,高,宽)*/int newX,newY,newColor,newW,newH;/*制定方块的状态*/int active;/*存储当前方块的数组*/int box[4][4];/*当前方块的颜色*/int BOXCOLOR;/*控制命令*/int CMD;/*定义七种基本的方块形状*/int BOX[7][4][4]={{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}};/*得到方块的宽度,即从右向左第一个不空的列*/ int GetWidth(){int i,j;for(i=3;i>0;i--)for(j=0;j<4;j++)if(box[j][i]) return i;return 0;}/*得到方块的高度,从上往下第一个不空的行*/ int GetHeight(){int i,j;for(j=3;j>0;j--)for(i=0;i<4;i++)if(box[j][i]) return j;return 0;}/*清除原有的方块占有的空间*/void ClearOldspace(){int i,j;for(j=0;j<=curH; j++)for(i=0;i<=curW; i++)if(box[j][i])area[curY+j][curX+i]=0;}/*置位新方块的位置*/void PutNewspace(){int i,j;for(j=0;j<=newH;j++)for(i=0;i<=newW;i++)if(box[j][i])area[newY+j][newX+i]=BOXCOLOR;}/*判断方块的移动是否造成区域冲突*/int MoveCollision(int box[][4]){int i,j;if(newX<0) return 1;if(newX+newW>=MAXWIDTH) return 1;if(newY<0) return 1;for(j=0;j<=newH;j++)for(i=0;i<=newW;i++)if(area[newY+j][newX+i]&&box[j][i]) return 1; return 0;}/*判断翻转方块是否造成区域的冲突*/int RotateBoxCollision(int box[][4]){int i,j;if(newX+newW>=MAXWIDTH) newX=MAXWIDTH-1-newW; if(newY+newH>=MAXHEIGHT) newY=MAXHEIGHT-1-newH; if(MoveCollision(box)) return 1;for(i=0;i<=newW;i++)for(j=0;j<=newH;j++)if(area[newY+j][newX+i]){newX-=newW-i+1; goto L;}L: return MoveCollision(box);}/*游戏结束*/int GameOver(){if(!active &&(curY+curH>MAXHEIGHT-3))return 1;elsereturn 0;}/*判断是否超时,即是否超过允许的时间间隔*/ int TimeOut(){static long tm,old;tm=biostime(0,tm);if(tm-old<TIMEINTERVAL)return 0;else{old=tm;return 1;}}/*重绘游戏区*/void DrawSpace(){int row,col,x1,y1,x2,y2;for(row=actY;row<=actY+actH;row++)for(col=actX;col<=actX+actW;col++)if(area[row][col]!=oldarea[row][col]) {if(area[row][col]==0)setfillstyle(SOLID_FILL,BLACK);elsesetfillstyle(SOLID_FILL,BOXCOLOR); x1=56+col*BOXWIDTH;x2=x1+BOXWIDTH;y1=464-(row+1)*BOXWIDTH;y2=y1+BOXWIDTH;bar(++x1,++y1,--x2,--y2);oldarea[row][col]=area[row][col]; }CMD=0;}/*消去满行*/void ClearFullline(){int row,col, rowEnd,full,i,j; rowEnd=newY+newH;if(rowEnd>=MAXHEIGHT-1)rowEnd=MAXHEIGHT-2;for(row=newY; row<=rowEnd;) {full=1;for(col=0;col<MAXWIDTH;col++) if(!area[row][col]){full=0; break;}if(!full){++row;continue;}for(j=row; j<MAXHEIGHT-1;j++) for(i=0;i<MAXWIDTH;i++)area[j][i]=area[j+1][i];actX=0;actY=row;actW=MAXWIDTH-1;actH=MAXHEIGHT-1-row; DrawSpace();rowEnd--;}CMD=CMDGEN;}/*向左移动方块*/ int MoveLeft(){newX=curX-1; ClearOldspace();if(MoveCollision(box)) {newX=curX; PutNewspace(); CMD=0;return 0;}PutNewspace(); actW=curW+1;actX=curX=newX; CMD=CMDDRAW; return 1;}/*向右移动方块*/int MoveRight(){newX=curX+1; ClearOldspace(); if(MoveCollision(box)){newX=curX;PutNewspace();CMD=0;return 0;}PutNewspace();actW=curW+1;actX=curX;curX=newX;CMD=CMDDRAW;return 1;}/*向下移动方块*/int MoveDown(){int i,j;newY=curY-1;ClearOldspace();if(MoveCollision(box)){newY=curY;PutNewspace();active=0;CMD=CMDDELLINE;return 0;}PutNewspace();actH=curH+1;actY=newY;curY=newY;CMD=CMDDRAW;return 1;}/*按加速键后方块迅速下落到底*/ void MoveBottom(){while(active){MoveDown();DrawSpace();}CMD=CMDDELLINE;}/*初始化*/void InitialGame(){int i,j,x1,y1,x2,y2;int driver=DETECT, mode=0; initgraph(&driver,&mode,"e:\\tc"); cleardevice();randomize();setfillstyle(SOLID_FILL,BLUE);bar(0,0,639,479);x1=56;y1=464-BOXWIDTH*MAXHEIGHT; x2=56+MAXWIDTH*BOXWIDTH;y2=464;rectangle(--x1,--y1,++x2,++y2);setfillstyle(SOLID_FILL,BLACK);bar(++x1,++y1,--x2,--y2);y1=464-MAXHEIGHT*BOXWIDTH; y2=464;setcolor(DARKGRAY);for(i=0;i<MAXWIDTH;i++){x1=56+i*BOXWIDTH;line(x1,y1,x1,y2);}x1=56; x2=x1+MAXWIDTH*BOXWIDTH;for(j=0;j<MAXHEIGHT;j++){y1=464-j*BOXWIDTH;line(x1,y1,x2,y1);}for(j=0;j<MAXHEIGHT;j++)for(i=0;i<MAXWIDTH;i++)area[j][i]=oldarea[j][i]=0;actX=0; actY=0; actW=MAXWIDTH-1; actH=MAXHEIGHT-1; DrawSpace();CMD=CMDGEN;}/*得到控制命令*/ void GetCMD(){if(CMD) return;if(TimeOut()){CMD=CMDAOTODOWN; return;}if(bioskey(1)){CMD=bioskey(0)>>8; return;}}/*生成一个新的方块*/ int GenerateNewbox() {int i,j,boxidx;boxidx=random(7); BOXCOLOR=random(7)+1;for(j=0;j<4;j++)for(i=0;i<4;i++)box[j][i]=BOX[boxidx][j][i];curW=GetWidth(); curH=GetHeight();curX=(MAXWIDTH+curW)/2;if(curX+curW>=MAXWIDTH)curX=MAXWIDTH-1-curW; curY=MAXHEIGHT-1-curH;newX=curX; newY=curY; actX=curX;actY=curY;actW=newW=curW; actH=newH=curH;active=1;if(MoveCollision(box)) return 0;PutNewspace();DrawSpace(); CMD=0;return 1;}/*翻转方块*/int RotateBox(){int newBox[4][4];int i,j;ClearOldspace();for(j=0;j<4;j++)for(i=0;i<4;i++)newBox[j][i]=0;for(j=0;j<4;j++)for(i=0;i<4;i++)newBox[curW-i][j]=box[j][i]; newW=curH;newH=curW;if(RotateBoxCollision(newBox)) {newW=curW;newH=curH;newX=curX;newY=curY;PutNewspace();CMD=0;return 0;}for(j=0;j<4;j++)for(i=0;i<4;i++)box[j][i]=newBox[j][i];PutNewspace();actH=newH>curH? newH:curH;actW=curX+actH-newX;actX=newX;actY=newY;curX=newX;curY=newY;curW=newW;curH=newH;CMD=CMDDRAW;return 1;}/*根据获得的命令来执行不同的操作*/ void ExecuteCMD(){switch(CMD){case CMDLEFTMOVE:MoveLeft();break;case CMDRINGHTMOVE: MoveRight();break;case CMDAOTODOWN: MoveDown();break;case CMDROTATE: RotateBox();break;case CMDDOWNMOVE: MoveBottom(); break;case CMDDRAW: DrawSpace();break;case CMDDELLINE: ClearFullline(); break;case CMDGEN: GenerateNewbox(); break;case CMDESC: closegraph(); return 0; default:CMD=0;}}/*主函数*/int main(){int i;InitialGame();do{GetCMD(); ExecuteCMD();}while(!GameOver()); getch(); closegraph(); return 0;}21/ 21。

C语言源码实现俄罗斯方块

C语⾔源码实现俄罗斯⽅块介绍俄罗斯⽅块(Tetris,俄⽂:Тетрис)是⼀款电视游戏机和掌上游戏机游戏,它由俄罗斯⼈阿列克谢·帕基特诺夫发明,故得此名。

俄罗斯⽅块的基本规则是移动、旋转和摆放游戏⾃动输出的各种⽅块,使之排列成完整的⼀⾏或多⾏并且消除得分。

由于上⼿简单、⽼少皆宜,从⽽家喻户晓,风靡世界。

源码#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <conio.h>#include <windows.h>#ifdef _MSC_VER // M$的编译器要给予特殊照顾#if _MSC_VER <= 1200 // VC6及以下版本#error 你是不是还在⽤VC6?!#else // VC6以上版本#if _MSC_VER >= 1600 // 据说VC10及以上版本有stdint.h了#include <stdint.h>#else // VC10以下版本,⾃⼰定义int8_t和uint16_ttypedef signed char int8_t;typedef unsigned short uint16_t;#endif#ifndef __cplusplus // 据说VC都没有stdbool.h,不⽤C++编译,⾃⼰定义booltypedef int bool;#define true 1#define false 0#endif#endif#else // 其他的编译器都好说#include <stdint.h>#ifndef __cplusplus // 不⽤C++编译,需要stdbool.h⾥的bool#include <stdbool.h>#endif#endif// =============================================================================// 7种⽅块的4旋转状态(4位为⼀⾏)static const uint16_t gs_uTetrisTable[7][4] ={{ 0x00F0U, 0x2222U, 0x00F0U, 0x2222U }, // I型{ 0x0072U, 0x0262U, 0x0270U, 0x0232U }, // T型{ 0x0223U, 0x0074U, 0x0622U, 0x0170U }, // L型{ 0x0226U, 0x0470U, 0x0322U, 0x0071U }, // J型{ 0x0063U, 0x0264U, 0x0063U, 0x0264U }, // Z型{ 0x006CU, 0x0462U, 0x006CU, 0x0462U }, // S型{ 0x0660U, 0x0660U, 0x0660U, 0x0660U } // O型};// =============================================================================// 初始状态的游戏池// 每个元素表⽰游戏池的⼀⾏,下标⼤的是游戏池底部// 两端各置2个1,底部2全置为1,便于进⾏碰撞检测// 这样⼀来游戏池的宽度为12列// 如果想要传统的10列,只需多填两个1即可(0xE007),当然显⽰相关部分也要随之改动// 当某个元素为0xFFFFU时,说明该⾏已被填满// 顶部4⾏⽤于给⽅块,不显⽰出来// 再除去底部2⾏,显⽰出来的游戏池⾼度为22⾏static const uint16_t gs_uInitialTetrisPool[28] ={0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xFFFFU, 0xFFFFU};#define COL_BEGIN 2#define COL_END 14// ============================================================================= typedef struct TetrisManager // 这个结构体存储游戏相关数据{uint16_t pool[28]; // 游戏池int8_t x; // 当前⽅块x坐标,此处坐标为⽅块左上⾓坐标int8_t y; // 当前⽅块y坐标int8_t type[3]; // 当前、下⼀个和下下⼀个⽅块类型int8_t orientation[3]; // 当前、下⼀个和下下⼀个⽅块旋转状态unsigned score; // 得分unsigned erasedCount[4]; // 消⾏数unsigned erasedTotal; // 消⾏总数unsigned tetrisCount[7]; // 各⽅块数unsigned tetrisTotal; // ⽅块总数bool dead; // 挂} TetrisManager;// ============================================================================= typedef struct TetrisControl // 这个结构体存储控制相关数据{bool pause; // 暂停bool clockwise; // 旋转⽅向:顺时针为trueint8_t direction; // 移动⽅向:0向左移动 1向右移动// 游戏池内每格的颜⾊// 由于此版本是彩⾊的,仅⽤游戏池数据⽆法存储颜⾊信息// 当然,如果只实现单⾊版的,就没必要⽤这个数组了int8_t color[28][16];} TetrisControl;HANDLE g_hConsoleOutput; // 控制台输出句柄// ============================================================================= // 函数声明// 如果使⽤全局变量⽅式实现,就没必要传参了void initGame(TetrisManager *manager, TetrisControl *control); // 初始化游戏void restartGame(TetrisManager *manager, TetrisControl *control); // 重新开始游戏void giveTetris(TetrisManager *manager); // 给⼀个⽅块bool checkCollision(const TetrisManager *manager); // 碰撞检测void insertTetris(TetrisManager *manager); // 插⼊⽅块void removeTetris(TetrisManager *manager); // 移除⽅块void horzMoveTetris(TetrisManager *manager, TetrisControl *control); // ⽔平移动⽅块void moveDownTetris(TetrisManager *manager, TetrisControl *control); // 向下移动⽅块void rotateTetris(TetrisManager *manager, TetrisControl *control); // 旋转⽅块void dropDownTetris(TetrisManager *manager, TetrisControl *control); // ⽅块直接落地bool checkErasing(TetrisManager *manager, TetrisControl *control); // 消⾏检测void keydownControl(TetrisManager *manager, TetrisControl *control, int key); // 键按下void setPoolColor(const TetrisManager *manager, TetrisControl *control); // 设置颜⾊void gotoxyWithFullwidth(short x, short y); // 以全⾓定位void printPoolBorder(); // 显⽰游戏池边界void printTetrisPool(const TetrisManager *manager, const TetrisControl *control); // 显⽰游戏池void printCurrentTetris(const TetrisManager *manager, const TetrisControl *control); // 显⽰当前⽅块void printNextTetris(const TetrisManager *manager); // 显⽰下⼀个和下下⼀个⽅块void printScore(const TetrisManager *manager); // 显⽰得分信息void runGame(TetrisManager *manager, TetrisControl *control); // 运⾏游戏void printPrompting(); // 显⽰提⽰信息bool ifPlayAgain(); // 再来⼀次// ============================================================================= // 主函数int main(){TetrisManager tetrisManager;TetrisControl tetrisControl;initGame(&tetrisManager, &tetrisControl); // 初始化游戏do{printPrompting(); // 显⽰提⽰信息printPoolBorder(); // 显⽰游戏池边界runGame(&tetrisManager, &tetrisControl); // 运⾏游戏if (ifPlayAgain()) // 再来⼀次{SetConsoleTextAttribute(g_hConsoleOutput, 0x7);system("cls"); // 清屏restartGame(&tetrisManager, &tetrisControl); // 重新开始游戏else{break;}} while (1);gotoxyWithFullwidth(0, 0);CloseHandle(g_hConsoleOutput);return 0;}// ============================================================================= // 初始化游戏void initGame(TetrisManager *manager, TetrisControl *control){CONSOLE_CURSOR_INFO cursorInfo = { 1, FALSE }; // 光标信息g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台输出句柄SetConsoleCursorInfo(g_hConsoleOutput, &cursorInfo); // 设置光标隐藏SetConsoleTitleA("俄罗斯⽅块控制台版——By: NEWPLAN");restartGame(manager, control);}// ============================================================================= // 重新开始游戏void restartGame(TetrisManager *manager, TetrisControl *control){memset(manager, 0, sizeof(TetrisManager)); // 全部置0// 初始化游戏池memcpy(manager->pool, gs_uInitialTetrisPool, sizeof(uint16_t [28]));srand((unsigned)time(NULL)); // 设置随机种⼦manager->type[1] = rand() % 7; // 下⼀个manager->orientation[1] = rand() & 3;manager->type[2] = rand() % 7; // 下下⼀个manager->orientation[2] = rand() & 3;memset(control, 0, sizeof(TetrisControl)); // 全部置0giveTetris(manager); // 给下⼀个⽅块setPoolColor(manager, control); // 设置颜⾊}// ============================================================================= // 给⼀个⽅块void giveTetris(TetrisManager *manager){uint16_t tetris;manager->type[0] = manager->type[1]; // 下⼀个⽅块置为当前manager->orientation[0] = manager->orientation[1];manager->type[1] = manager->type[2];// 下下⼀个置⽅块为下⼀个manager->orientation[1] = manager->orientation[2];manager->type[2] = rand() % 7;// 随机⽣成下下⼀个⽅块manager->orientation[2] = rand() & 3;tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]]; // 当前⽅块// 设置当前⽅块y坐标,保证刚给出时只显⽰⽅块最下⾯⼀⾏// 这种实现使得玩家可以以很快的速度将⽅块落在不显⽰出来的顶部4⾏内if (tetris & 0xF000){manager->y = 0;}else{manager->y = (tetris & 0xFF00) ? 1 : 2;}manager->x = 6; // 设置当前⽅块x坐标if (checkCollision(manager)) // 检测到碰撞manager->dead = true; // 标记游戏结束}else // 未检测到碰撞{insertTetris(manager); // 将当前⽅块加⼊游戏池}++manager->tetrisTotal; // ⽅块总数++manager->tetrisCount[manager->type[0]]; // 相应⽅块数printNextTetris(manager); // 显⽰下⼀个⽅块printScore(manager); // 显⽰得分信息}// ============================================================================= // 碰撞检测bool checkCollision(const TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];uint16_t dest = 0;// 获取当前⽅块在游戏池中的区域:// 游戏池坐标x y处⼩⽅格信息,按低到⾼存放在16位⽆符号数中dest |= (((manager->pool[manager->y + 0] >> manager->x) << 0x0) & 0x000F);dest |= (((manager->pool[manager->y + 1] >> manager->x) << 0x4) & 0x00F0);dest |= (((manager->pool[manager->y + 2] >> manager->x) << 0x8) & 0x0F00);dest |= (((manager->pool[manager->y + 3] >> manager->x) << 0xC) & 0xF000);// 若当前⽅块与⽬标区域存在重叠(碰撞),则位与的结果不为0return ((dest & tetris) != 0);}// ============================================================================= // 插⼊⽅块void insertTetris(TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];// 当前⽅块每4位取出,位或到游戏池相应位置,即完成插⼊⽅块manager->pool[manager->y + 0] |= (((tetris >> 0x0) & 0x000F) << manager->x);manager->pool[manager->y + 1] |= (((tetris >> 0x4) & 0x000F) << manager->x);manager->pool[manager->y + 2] |= (((tetris >> 0x8) & 0x000F) << manager->x);manager->pool[manager->y + 3] |= (((tetris >> 0xC) & 0x000F) << manager->x);}// ============================================================================= // 移除⽅块void removeTetris(TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];// 当前⽅块每4位取出,按位取反后位与到游戏池相应位置,即完成移除⽅块manager->pool[manager->y + 0] &= ~(((tetris >> 0x0) & 0x000F) << manager->x);manager->pool[manager->y + 1] &= ~(((tetris >> 0x4) & 0x000F) << manager->x);manager->pool[manager->y + 2] &= ~(((tetris >> 0x8) & 0x000F) << manager->x);manager->pool[manager->y + 3] &= ~(((tetris >> 0xC) & 0x000F) << manager->x);}// ============================================================================= // 设置颜⾊void setPoolColor(const TetrisManager *manager, TetrisControl *control){// 由于显⽰游戏池时,先要在游戏池⾥判断某⼀⽅格有⽅块才显⽰相应⽅格的颜⾊// 这⾥只作设置即可,没必要清除// 当移动⽅块或给⼀个⽅块时调⽤int8_t i, x, y;// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];for (i = 0; i < 16; ++i)y = (i >> 2) + manager->y; // 待设置的列if (y > ROW_END) // 超过底部限制{break;}x = (i & 3) + manager->x; // 待设置的⾏if ((tetris >> i) & 1) // 检测的到⼩⽅格属于当前⽅块区域{control->color[y][x] = (manager->type[0] | 8); // 设置颜⾊}}}// ============================================================================= // 旋转⽅块void rotateTetris(TetrisManager *manager, TetrisControl *control){int8_t ori = manager->orientation[0]; // 记录原旋转状态removeTetris(manager); // 移⾛当前⽅块// 顺/逆时针旋转manager->orientation[0] = (control->clockwise) ? ((ori + 1) & 3) : ((ori + 3) & 3);if (checkCollision(manager)) // 检测到碰撞{manager->orientation[0] = ori; // 恢复为原旋转状态insertTetris(manager); // 放⼊当前⽅块。

VC++ 6.0 MFC 俄罗斯方块 自动求解 代码 源程序

#include <windows.h>#include <time.h>#include <stdlib.h>#include <stdio.h>#define tDown 1 //方块下落定时器的标识(编号)#define tPaint 2 //重绘定时器的标识(编号)#define tDownTime 500 //方块下落一行位置的时间间隔#define tPaintTime 50 //窗口重绘的时间间隔#define ROW 24 //地图的行数目(第23行不用)#define COL 14 //地图的列数目(第0列和第13列不用)#define MAX_CLASS 7 //方块形状数目#define LEN 20 //每个方格大小为20×20像素#define StartY -1 * LEN + 5 //-15,绘制俄罗斯方块地图时的边界起始位置#define StartX -1 * LEN + 5 //-15int iDeleteRows = 0; //总共清除的行int iTotalNum = 0; //总得分char WindowTxt[100] = "俄罗斯方块游戏自动求解已关闭"; //窗口标题char s1[] = "关闭", s2[] = "启动"; //用于启动/关闭自动求解功能时显示不同的标题bool bAuto; //是否自动求解的标志bool Pause; //是否暂停的标志int Map[ROW][COL]; //俄罗斯方块的地图(被占据的方格为1,否则为0) int CurrentBox[4][4]; //当前落下的方块int CurrentY, CurrentX; //当前落下方块的当前位置(指左上角位置)int NextBox[4][4]; //下一个将落下的方块int Box[MAX_CLASS][4][4] = //7种方块形状{{{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}},{{0,0,0,0},{0,1,0,0},{1,1,1,0},{0,0,0,0}},{{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}},{{0,1,1,0},{0,0,1,0},{0,0,1,0},{0,0,0,0}},{{0,1,1,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}}};void InitMap( ); //初始化地图int NewFall( ); //新的方块落下void BuildNextBox( ); //产生下一个随机的方块int Test( int y, int x, int box[4][4] ); //测试在(y,x)位置是否能放置方块box,能放置返回1,否则返回0int Drop( ); //定时时间到,当前方块下降一行位置void PutBox( ); //放置当前方块int Move( int Right ); //(通过方向键)移动方块,参数right为1表示向右移动,为0表示向左移动void Clear( ); //清除满足条件的行int Rotate( ); //测试旋转是否可行,如果可行则旋转当前方块int RotateTest( int Box1[4][4], int Box2[4][4] ); //旋转当前方块int count1( int y, int x, int box[4][4] ); //新增函数int BestStartX( ); //新增函数LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); //窗口处理函数声明int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow ) //入口函数{static TCHAR szAppName[ ] = TEXT ("Russion");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if( !RegisterClass( &wndclass ) ){MessageBox( NULL, TEXT ("Program requires Windows NT!" ),szAppName, MB_ICONERROR );return 0;}hwnd = CreateWindow( szAppName, WindowTxt,WS_OVERLAPPED | WS_SYSMENU | WS_BORDER,CW_USEDEFAULT, CW_USEDEFAULT,(COL + 4) * LEN, //窗口宽度:(14+4)×20=360像素ROW * LEN, //窗口高度:24×20=480像素(包括标题栏部分)NULL, NULL, hInstance, NULL );ShowWindow( hwnd, iCmdShow );UpdateWindow( hwnd );while( GetMessage( &msg, NULL, 0, 0 ) ){TranslateMessage( &msg );DispatchMessage( &msg );}return msg.wParam;}//初始化地图(将第0列和第13列、第23行设置为1(被占据),其他位置设置为0) void InitMap( ){int y, x;for( y = 0; y < ROW; y++ ){for( x = 0; x < COL; x++ ){//第0列、第13列、第23行设置为1(被占据)if( x < 1 || x > COL - 2 || y > ROW - 2 )Map[y][x] = 1;else Map[y][x] = 0;}}}//计算在(y,x)位置(左上角位置)上放置方块box后空出的方格数int count1( int y, int x, int box[4][4] ){if( !Test(y,x,box) ) return 100; //不能在(y,x)位置放置box,返回∞if( Test(y+1,x,box) ) return 100; //如果box还能下降,也返回∞int tmpy, tmpx;int c = 0; //空出的方格数for( tmpx = 0; tmpx < 4; tmpx++ ) //考虑第0~3列{for( tmpy = 3; tmpy >= 0; tmpy-- ){if( box[tmpy][tmpx] ) break;}tmpy++;if( tmpy>0 ){for( ; tmpy<4; tmpy++ ){if( tmpy+y<0 || tmpy+y>=ROW || tmpx+x<0 || tmpx+x>=COL ) continue;if(!Map[tmpy+y][tmpx+x]) c++; //空出的方格}}}return c;}//当启动自动求解功能时,求下一个方块的最佳下降位置//策略1为:放置后,空出的方格数最少,为MinC1,此时能达到最高位置为MaxY1,该位置为BestX1;//策略2为:放置后,能下降的位置最高,为MaxY2,此时空出的方格数为MinC2,该位置为BestX2;//必有MaxY1<=MaxY2, MinC1>=MinC2//取二者的折衷,策略为:优先采取策略1,但如果MinC2==MinC1或MaxY2>=MaxY1+2,则取策略2int BestStartX( ){int X, Y, tmpx, tmpy; //循环变量int BestX = 0, MaxY = 0, MinC = 100;//最终所求的最佳下降位置int BestX1, MaxY1, MinC1; //策略1:MinC:最佳位置处放置方块时,空出的空格最少,BestX:最佳下降位置,MaxY:能下降到的位置int BestX2, MaxY2, MinC2; //策略2:最佳位置为能下降的位置最高int c; //以上策略求最值时用到的辅助变量int tBox1[4][4], tBox2[4][4]; //tBox2为实现旋转时用到的临时变量int Rotates = 0, Rotates1 = 0, Rotates2 = 0;//找到最佳位置后,当前方块需要旋转的次数int Last1, Last2; //Last1为下一个方块未旋转时最下一个方格所在的行,Last2为旋转后最下一个方格所在的行memcpy(tBox1, NextBox, sizeof(tBox1)); memcpy(tBox2, NextBox, sizeof(tBox1)); for( tmpy=3; tmpy>=0; tmpy-- ) //统计tBox1中最下一个方格所在的行{for( tmpx=0; tmpx<4; tmpx++ ) if(tBox1[tmpy][tmpx]) break;if(tmpx<4) break;}Last1 = tmpy;BestX1 = 0, MaxY1 = 0, MinC1 = 100; BestX2 = 0, MaxY2 = 0, MinC2 = 100;//枚举从第0~COL-4列下落for( X=0; X<=COL-4; X++ ){for( Y=0; Y<=ROW-1; Y++ )if( !Test( Y, X, tBox1 ) ) break;Y--;c = count1(Y,X,tBox1);if( c<MinC1 || c==MinC1 && Y+Last1>MaxY1 )MinC1 = c, BestX1 = X, MaxY1 = Y+Last1;if( Y+Last1>MaxY2 || Y+Last1==MaxY2 && c<MinC2 )MinC2 = c, BestX2 = X, MaxY2 = Y+Last1;}//第1次旋转,旋转后为tBox1Last2 = RotateTest(tBox1, tBox2); memcpy(tBox1, tBox2, sizeof(tBox1));for( X=0; X<=COL-4; X++ ){for( Y=0; Y<=ROW-1; Y++ )if( !Test( Y, X, tBox1 ) ) break;Y--;c = count1(Y,X,tBox1);if( c<MinC1 || c==MinC1 && Y+Last2>MaxY1 )MinC1 = c, BestX1 = X, MaxY1 = Y+Last2, Rotates1 = 1;if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && c<MinC2 )MinC2 = c, BestX2 = X, MaxY2 = Y+Last2, Rotates2 = 1;}//第2次旋转,旋转后为tBox1Last2 = RotateTest(tBox1, tBox2); memcpy(tBox1, tBox2, sizeof(tBox1));for( X=0; X<=COL-4; X++ ){for( Y=0; Y<=ROW-1; Y++ )if( !Test( Y, X, tBox1 ) ) break;Y--;c = count1(Y,X,tBox1);if( c<MinC1 || c==MinC1 && Y+Last2>MaxY1 )MinC1 = c, BestX1 = X, MaxY1 = Y+Last2, Rotates1 = 2;if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && c<MinC2 )MinC2 = c, BestX2 = X, MaxY2 = Y+Last2, Rotates2 = 2;}//第3次旋转,旋转后为tBox1Last2 = RotateTest(tBox1, tBox2); memcpy(tBox1, tBox2, sizeof(tBox1));for( X=0; X<=COL-4; X++ ){for( Y=0; Y<=ROW-1; Y++ )if( !Test( Y, X, tBox1 ) ) break;Y--;c = count1(Y,X,tBox1);if( c<MinC1 || c==MinC1 && Y+Last2>MaxY1 )MinC1 = c, BestX1 = X, MaxY1 = Y+Last2, Rotates1 = 3;if( Y+Last2>MaxY2 || Y+Last2==MaxY2 && c<MinC2 )MinC2 = c, BestX2 = X, MaxY2 = Y+Last2, Rotates2 = 3;}MinC = MinC1, BestX = BestX1, MaxY = MaxY1, Rotates = Rotates1;if( MinC2==MinC1 || MaxY2>=MaxY1+2 )MinC = MinC2, BestX = BestX2, MaxY = MaxY2, Rotates = Rotates2;if( Rotates>0 ){for( int i=0; i<Rotates; i++ ){RotateTest(NextBox, tBox1);memcpy(NextBox, tBox1, sizeof(tBox1));}}return BestX;}int NewFall( ) //新的方块落下(如果能落下返回1,否则不能落下返回0(程序就该结束了)) {int y, x;CurrentY = 0; //当前方块的当前位置是指该方块(4×4大小)的左上角所在位置if(bAuto) CurrentX = BestStartX( );else CurrentX = COL / 2 - 2; //初始为(0,5)for( y = 0; y < 4; y++ ){for( x = 0; x < 4; x++ )CurrentBox[y][x] = NextBox[y][x];}BuildNextBox( ); //产生下一个随机的方块return Test( CurrentY, CurrentX, CurrentBox );}int no[400] = {3,3,5,1};void BuildNextBox( ) //产生下一个随机的方块{static int j=0;int i, y, x;i = rand()%MAX_CLASS; //随机生成0~6的整数for( y = 0; y < 4; y++ ){for( x = 0; x < 4; x++ )NextBox[y][x] = Box[i][y][x];}}//测试在(y,x)位置(左上角位置)是否能放置方块box,能放置返回1,否则返回0int Test( int y, int x, int box[4][4] ){int tmpy, tmpx;for( tmpy = 0; tmpy < 4; tmpy++ ){for( tmpx = 0; tmpx < 4; tmpx++ ){if( Map[tmpy + y][tmpx + x] && box[tmpy][tmpx] )return 0;}}return 1;}int Drop( ) //定时时间到,当前方块下降一行位置(如果能下降返回1,否则返回0){int NewY;NewY = CurrentY + 1;if( Test( NewY, CurrentX, CurrentBox ) ){CurrentY = NewY;return 1;}return 0;}void PutBox( ) //在当前位置(CurrentY,CurrentX)放置当前方块(此时当前方块已经不能下降了){int y, x;for( y = 0; y < 4; y++ ){for( x = 0; x < 4; x++ ){if( CurrentBox[y][x] )Map[CurrentY + y][CurrentX + x] = CurrentBox[y][x];}}}int Move( int Right ) //(通过方向键)移动方块,参数right为1表示向右移动,为0表示向左移动{int x;if( Right ) x = CurrentX + 1; //向右移动一列位置else x = CurrentX - 1; //向左移动一列位置if( Test( CurrentY, x, CurrentBox ) ){CurrentX = x;return 1;}return 0;}void Clear( ) //清除满足条件的行{int y, x; //循环变量int DelY, DelX; //循环变量int Full; //一行是否满的标志for( y = 0; y < ROW - 1; y++ ) //检查第0~22行{Full = 1;for( x = 1; x < COL - 1; x++ ) //检查每行的第1~12列{if( !Map[y][x] ){Full = 0; break;}}if( Full ) //第y行满了,删除该行,该行以上的其他行下移一行{iDeleteRows++; iTotalNum = iDeleteRows*100; //更新得分for( DelY = y; DelY > 0; DelY-- ){for( DelX = 1; DelX < COL - 1; DelX++ )Map[DelY][DelX] = Map[DelY-1][DelX];}for( DelX = 1; DelX < COL - 1; DelX++ ) //第0行置为0Map[0][DelX] = 0;}}}int Rotate( ) //测试旋转是否可行,如果可行则旋转当前方块{int y, x;int TmpBox[4][4];RotateTest( CurrentBox, TmpBox );if( Test( CurrentY, CurrentX, TmpBox ) ){for( y = 0; y < 4; y++ ){for( x = 0; x < 4; x++ )CurrentBox[y][x] = TmpBox[y][x];}return 1;}else return 0;}/*0000 0000 0000 //旋转规律是:Box3[y][x] = Box1[y][3-x] -> 方块绕竖直方向对称变换0100-> 0010-> 0010 //Box2[x][y] = Box3[y][x] -> 沿着主对角线对称变换(相当于矩阵转置)1110 0111 01100000 0000 0010 */int RotateTest( int Box1[4][4], int Box2[4][4] ) //旋转当前方块{ //新增返回值为:旋转后的Box2中最下一个方格所在的行int y, x;for( y = 0; y < 4; y++ ){for( x = 3; x >=0; x-- )Box2[x][y] = Box1[y][3 - x];}for( y=3; y>=0; y-- ) //统计Box2中最下一个方格所在的行{for( x=0; x<4; x++ ){if(Box2[y][x]) break;}if(x<4) break;}return y;}LRESULT CALLBACK WndProc( HWND hwnd, UINT message, //窗口处理函数WPARAM wParam, LPARAM lParam ){HDC hdc, hdcMem;int y, x;PAINTSTRUCT ps;HBITMAP hBitMap;HPEN hPen;HBRUSH hBrush;static int cxClient, cyClient; //窗口客户区宽度和高度char str[20]; //用于显示得分的变量switch( message ){case WM_CREATE:SetTimer( hwnd, tDown, tDownTime, NULL ); //开启两个定时器SetTimer( hwnd, tPaint, tPaintTime, NULL );srand( (unsigned)time( NULL ) );bAuto = false;Pause = false;InitMap( );BuildNextBox( ); //先随机产生一个方块NewFall( ); //方块落下并随机产生下一个方块sprintf( str, " 得分:%d", iTotalNum ); strcat( WindowTxt, str );SetWindowText(hwnd,WindowTxt);return 0;case WM_SIZE:cxClient = LOWORD( lParam ); //取得窗口客户区宽度和高度cyClient = HIWORD( lParam );return 0;case WM_TIMER:switch( wParam ){case tDown: //下降定时器if( !Drop( ) ) //如果不能下降则放置当前方块{PutBox( );MessageBeep( -1 );Clear( ); //清除//刷新得分sprintf( str, "%d", iTotalNum ); WindowTxt[36] = 0;strcat( WindowTxt, str ); SetWindowText(hwnd,WindowTxt);if( !NewFall( ) ) //如果新的方块不能落下,则程序结束{KillTimer(hwnd, tDown );KillTimer(hwnd, tPaint );//PostMessage( hwnd, WM_CLOSE, NULL, NULL );}}break;case tPaint: //重绘定时器InvalidateRect(hwnd, NULL, FALSE); //强制重绘窗口工作区break;}case WM_KEYDOWN:switch( wParam ){case VK_LEFT: //"向左"方向键if(bAuto) break;Move(0); break;case VK_RIGHT: //"向右"方向键if(bAuto) break;Move(1); break;case VK_UP: //"向上"方向键:旋转if(bAuto) break;Rotate( ); break;case VK_DOWN: //"向下"方向键:当前方块下移一行位置if(bAuto) break;MessageBeep( -1 ); Drop( ); break;case VK_RETURN: //回车键:暂停Pause = !Pause;if( Pause ) //暂停、自动求解时也可以暂停KillTimer( hwnd, tDown );else //启动{if(bAuto) SetTimer( hwnd, tDown, tDownTime/5, NULL );else SetTimer( hwnd, tDown, tDownTime, NULL );}break;case VK_SPACE:if(bAuto) break;while( 1 ) //使用永真循环,使得当前方块一直下降到不能下降为止{if( !Drop( ) ){PutBox( ); Clear( );sprintf( str, "%d", iTotalNum ); WindowTxt[36] = 0;strcat( WindowTxt, str ); SetWindowText(hwnd,WindowTxt);if( !NewFall( ) ) //如果新的方块不能落下,则程序结束{KillTimer(hwnd, tDown );KillTimer(hwnd, tPaint );//PostMessage( hwnd, WM_CLOSE, NULL, NULL );}break;}}break;case VK_F1:bAuto = !bAuto;if(bAuto) //自动求解{KillTimer(hwnd, tDown );SetTimer( hwnd, tDown, tDownTime/5, NULL );memcpy( WindowTxt+25, s2, strlen(s2) ); //修改标题}else{KillTimer(hwnd, tDown );SetTimer( hwnd, tDown, tDownTime, NULL );memcpy( WindowTxt+25, s1, strlen(s1) ); //修改标题}SetWindowText(hwnd,WindowTxt);break;}case WM_PAINT: //重绘窗口工作区hdc = BeginPaint( hwnd, &ps );hdcMem = CreateCompatibleDC( hdc );hBitMap = CreateCompatibleBitmap( hdc, cxClient, cyClient );SelectObject( hdcMem, hBitMap );//画地图最外面的矩形(4, 4, 246, 446)Rectangle( hdcMem, StartX + LEN * 1 - 1,StartY + LEN * 1 - 1,StartX + LEN * (COL - 1) + 1, StartY + LEN * (ROW - 1) + 1 );hPen = CreatePen( PS_SOLID, 1, RGB(180, 180, 180) );SelectObject( hdcMem, hPen );hBrush = CreateSolidBrush( RGB(250, 250, 250) );SelectObject( hdcMem, hBrush );for( y = 1; y < ROW - 1; y++ ) //画地图中的每一格{for( x = 1; x < COL - 1; x++ ){Rectangle( hdcMem, StartX + LEN * x, StartY + LEN * y,StartX + LEN * (x + 1), StartY + LEN * (y + 1) );}}DeleteObject( hPen );DeleteObject( hBrush );hPen = CreatePen( PS_SOLID, 1, RGB(180, 180, 180) ); SelectObject( hdcMem, hPen );hBrush = CreateSolidBrush( RGB(255, 100, 100) );SelectObject(hdcMem, hBrush);for( y = 1; y < ROW - 1; y++ ) //画出地图中每个被占据的方格{for( x = 1; x < COL - 1; x++ ){if( Map[y][x] ){Rectangle( hdcMem, StartX + LEN * x, StartY + LEN * y,StartX +LEN * (x + 1), StartY + LEN * (y + 1) );}}}for( y = 0; y < 4; y++ ) //画当前方块{for( x = 0; x < 4; x++ ){if( CurrentBox[y][x] ){if( y + CurrentY > 0 ){Rectangle( hdcMem, (x + CurrentX) * LEN + StartX,(y + CurrentY) * LEN +StartY,(x + CurrentX + 1) * LEN + StartX,(y + CurrentY + 1) * LEN + StartY );}}}}for( y = 0; y < 4; y++ )//在窗口右边区域画下一个方块{for( x = 0; x < 4; x++ ){if( NextBox[y][x] ){Rectangle( hdcMem, (x + COL) * LEN + StartX,(y + 2) * LEN + StartY,(x+ COL + 1) * LEN + StartX, (y + 3) * LEN + StartY );}}}DeleteObject( hPen );DeleteObject( hBrush );DeleteObject( hBitMap );BitBlt( hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY );DeleteDC( hdcMem );EndPaint( hwnd, &ps );return 0;case WM_DESTROY:KillTimer(hwnd, tDown );KillTimer(hwnd, tPaint );PostQuitMessage( 0 );return 0;}//end of switch( message )return DefWindowProc( hwnd, message, wParam, lParam );}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

俄罗斯方块C程序源代码(好像有问题) typedef enum tetris_shape{ ZShape=0, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape }shape;

int maxX(); int minX(); void turn_left(); void turn_right(); int out_of_table(); void transform(); int leftable(); int rightable(); int downable(); void move_left(); void move_right();

int add_to_table(); void remove_full();

void new_game(); void run_game(); void next_shape(); int random(int seed);

void paint(); void draw_table();

void key_down(WPARAM wParam); void resize(); void initialize(); void finalize();

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

#include #include #include #include "tetris.h"

#define APP_NAME "TETRIS" #define APP_TITLE "Tetris Game" #define GAMEOVER "GAME OVER"

#define SHAPE_COUNT 7 #define BLOCK_COUNT 4 #define MAX_SPEED 5

#define COLUMS 10 #define ROWS 20

#define RED RGB(255,0,0) #define YELLOW RGB(255,255,0) #define GRAY RGB(128,128,128) #define BLACK RGB(0,0,0) #define WHITE RGB(255,255,255) #define STONE RGB(192,192,192)

#define CHARS_IN_LINE 14 #define SCORE "SCORE %4d"

char score_char[CHARS_IN_LINE]={0}; char* press_enter="Press Enter key..."; char* help[]= { "Press space or up key to transform shape.", "Press left or right key to move shape.", "Press down key to speed up.", "Press enter key to pause game.", "Enjoy it. O_o made by C.X.", 0 };

enum game_state { game_start, game_run, game_pause, game_over }state = game_start; COLORREF shape_color[] = { RGB(255,0,0), RGB(0,255,0), RGB(0,0,255), RGB(255,255,0), RGB(0,255,255), RGB(255,0,255), RGB(255,255,255), };

int shape_coordinate[SHAPE_COUNT][BLOCK_COUNT][2] = { {{0,-1},{0,0},{-1,0},{-1,1}}, {{0,-1},{0,0},{1,0},{1,1}}, {{0,-1},{0,0},{0,1},{0,2}}, {{-1,0},{0,0},{1,0},{0,1}}, {{0,0},{1,0},{0,1},{1,1}}, {{-1,-1},{0,-1},{0,0},{0,1}}, {{1,-1},{0,-1},{0,0},{0,1}} };

int score=0; shape next=0; shape current=0; int current_coordinate[4][2]={0}; int table[ROWS][COLUMS]={0}; int shapex=0; int shapey=0; int speed=0; clock_t start=0; clock_t finish=0;

HWND gameWND; HBITMAP memBM; HBITMAP memBMOld; HDC memDC; RECT clientRC; HBRUSH blackBrush; HBRUSH stoneBrush; HBRUSH shapeBrush[SHAPE_COUNT]; HPEN grayPen; HFONT bigFont; HFONT smallFont;

int maxX() { int i=0; int x=current_coordinate[i][0]; int m=x; for (i=1;i { x=current_coordinate[i][0]; if (m { m=x; } } return m; }

int minX() { int i=0; int x=current_coordinate[i][0]; int m=x; for (i=1;i { x=current_coordinate[i][0]; if(m>x) { m=x; } } return m; }

void turn_left() { int i=0; int x,y; for (i=0;i<4;i++) { x=current_coordinate[i][0]; y=current_coordinate[i][1]; current_coordinate[i][0]=y; current_coordinate[i][1]=-x; } }

void turn_right() { int i=0; int x,y; for(i=0;i<4;i++) { x=current_coordinate[i][0]; y=current_coordinate[i][1]; current_coordinate[i][0]=-y; current_coordinate[i][1]=x; } }

int out_of_table() { int i=0; int x,y; for(i=0;i<4;i++) { x=shapex+current_coordinate[i][0]; y=shapey+current_coordinate[i][1]; if(x<0||x>(COLUMS-1)||y>(ROWS-1)) { return 1; } if(table[y][x]) { return 1; } } return 0; }

void transform() { if(current==SquareShape) { return; } turn_right(); if(out_of_table()) { turn_left(); } }

int leftable() { int i=0; int x,y; for(i=0;i<4;i++) { x=shapex+current_coordinate[i][0]; y=shapey+current_coordinate[i][1]; if(x<=0||table[y][x-1]==1) { return 0; } } return 1; }

int rightable() { int i=0; int x,y; for(i=0;i<4;i++) { x=shapex+current_coordinate[i][0]; y=shapey+current_coordinate[i][1]; if(x>=(COLUMS-1)||table[y][x+1]==1) { return 0; } } return 1; }

int downable() {

相关文档
最新文档