C++俄罗斯方块源码(完整功能版)
- 格式:doc
- 大小:435.00 KB
- 文档页数:18
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);}。
/********************************************** 游戏名称:俄罗斯方块**********************************************/#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代码声明:代码转⾃有兴趣的同学⼀起研习#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语言编写源代码实现其功能。
下面是俄罗斯方块游戏的C语言源代码:1. 创建窗口函数: // 创建窗口函数 void CreateWindow(int width, int height) { // 使用SDL库创建窗口 SDL_Init(SDL_INIT_EVERYTHING); SDL_Window *window = SDL_CreateWindow("Tetris",SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,width, height, 0); // 设置刷新时间SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); }2. 创建游戏函数: // 创建游戏函数 void CreateGame() { // 设置随机数种子srand((unsigned int)time(NULL)); // 加载游戏资源 LoadResources(); // 初始化游戏数据InitGameData(); // 初始化游戏界面InitGameUI(); // 开始游戏循环 GameLoop(); // 清理游戏资源 CleanupGame(); }3. 绘图函数: // 绘图函数 void Draw(int x, inty, Color color) { // 使用SDL库在指定位置绘制指定颜色的矩形 SDL_Rect rect; rect.x = x;rect.y = y; rect.w = BLOCK_SIZE; rect.h = BLOCK_SIZE; SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);SDL_RenderFillRect(renderer, &rect); }。
#define LEFT 0x4b#define RIGHT 0x4d#define DOWN 0x50#define CHANGE 0x20#define ESC 0x1b#define INTR 0x1C#define DefaultX 5#define DefaultY 1static unsigned counter=0;static unsigned shape[7][4][4][4]={{{{0,1,1,0},{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,1,1,0},{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,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}, {{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}}, {{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}, {{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}}, },{{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, },{{{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}}, {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}}, },{{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}}, },{{{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}}, {{0,0,0,0},{1,1,1,0},{1,0,0,0},{0,0,0,0}},{{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},{{0,0,0,0},{0,0,1,0},{1,1,1,0},{0,0,0,0}},},{{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},{{0,0,0,0},{1,0,0,0},{1,1,1,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,1,0},{0,0,1,0},{0,0,0,0}},},};unsigned back[22][14] ={{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,0,0,0,0,0,0,0,0,0,0,1,1},{1,1,1,1,1,1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,1,1,1,1,1,1}};char ShapeColor[7]={8,10,11,12,13,14,15};char DigitalShape[10]={128+119,3,62,31,128+75,128+93,128+125,19,128+127,128+95}; char ZodiacBack[11]={4,6,12,13,11,10,2,3,9,1,8};char ZodiacSoft[18][14]={{0,0,0,0,96,0,0,0,0,0,0,0,60,0},{255,248,0,0,96,0,0,0,0,248,0,0,124,0},{255,248,0,0,97,128,0,0,3,248,0,0,192,0},{0,112,0,0,97,128,0,0,7,0,0,1,128,48},{0,224,0,0,96,0,0,0,14,0,0,1,128,48},{1,192,0,0,96,0,0,0,12,0,0,1,128,48},{3,128,120,15,97,128,240,60,12,0,15,15,249,255},{7,0,252,31,225,131,248,127,14,0,31,143,249,255},{7,1,142,48,225,135,24,227,7,240,49,193,128,48},{14,3,134,96,97,142,24,192,3,252,112,193,128,48},{28,3,6,96,97,140,25,192,0,28,96,193,128,48},{56,3,6,96,97,140,25,128,0,6,96,193,128,48},{56,3,6,96,97,140,25,128,0,6,96,193,128,48},{120,3,6,96,97,140,25,128,0,6,96,193,128,48},{224,1,140,48,225,142,25,195,24,14,49,129,128,48},{255,249,252,63,225,135,252,255,28,28,63,129,128,48},{255,248,240,15,97,131,236,60,15,248,30,1,128,48},{0,0,0,0,0,0,0,0,7,224,0,1,128,0}};unsigned long TotalMark=0;unsigned int Erasered=0,ETimes=0;int Speed=0;int CEr=0;int NumOfLev[5]={0,0,0,0,0};int TimeDelay[10]={21,18,17,15,13,11,9,7,5,3};char NewShape[2];unsigned PerOnce[4];void interrupt ( *oldhandler)(__CPPARGS);void interrupt handler(__CPPARGS){++counter;oldhandler();}//******************************************************* void DrawBackground(){//setlinestyle}void DrawDigital(int x,int y,int a){int i=7;setcolor(((DigitalShape[a]>>i)&1)*7+4);//printf("%d",(DigitalShape[a]>>i)&1);i--;line(x,y+1,x,y+15);line(x+1,y+2,x+1,y+14);line(x+2,y+3,x+2,y+13);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x,y+17,x,y+31);line(x+1,y+18,x+1,y+30);line(x+2,y+19,x+2,y+29);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x,y+17,x,y+31);line(x+1,y+18,x+1,y+30);line(x+2,y+19,x+2,y+29);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x+1,y,x+16,y);line(x+2,y+1,x+15,y+1);line(x+3,y+2,x+14,y+2);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x+2,y+15,x+15,y+15);line(x+1,y+16,x+16,y+16);line(x+2,y+17,x+15,y+17);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x+3,y+30,x+14,y+30);line(x+2,y+31,x+15,y+31);line(x+1,y+32,x+16,y+32);setcolor(((DigitalShape[a]>>i)&1)*7+4);i--;line(x+15,y+3,x+15,y+13);line(x+16,y+2,x+16,y+14);line(x+17,y+1,x+17,y+15);setcolor(((DigitalShape[a]>>i)&1)*7+4);line(x+15,y+19,x+15,y+29);line(x+16,y+18,x+16,y+30);line(x+17,y+17,x+17,y+31);}//******************************************************* void ArtClear(){for(int i=480;i>=0;i-=2){setcolor(3);line(0,i-6,639,i-6);setcolor(9);line(0,i-4,639,i-4);setcolor(1);line(0,i-2,639,i-2);setcolor(getbkcolor());line(0,i,639,i);delay(1);}for(i=1;i<480;i+=2){setcolor(3);line(0,i+6,639,i+6);setcolor(9);line(0,i+4,639,i+4);setcolor(1);line(0,i+2,639,i+2);setcolor(getbkcolor());line(0,i,639,i);delay(1);}}//******************************************************* void end(){for(int j=0;j<4;j++){for(int i=j;i<480;i+=4){setcolor(3);line(0,i+8,639,i+8);setcolor(9);line(0,i+4,639,i+4);setcolor(1);line(0,i,639,i);setcolor(getbkcolor());line(0,i,639,i);delay(1);}delay(5);}setcolor(YELLOW);outtextxy(260,200,"[ Game Over ]");gotoxy(14,16);printf("This freeware is written by Daniel.Qu ZodiacSoft 2000"); gotoxy(12,17);printf("Please e-mail to swami@ or visit my homepage at"); gotoxy(12,18);printf(" if you have question.");gotoxy(14,20);printf("I will soon provide something new,please wait...");gotoxy(14,22);printf("We hold these truths to be self-evident,that all codes"); gotoxy(12,23);printf("are created FREE.");getch();clrscr();closegraph();exit(0);}//******************************************************* void ShowTitle(){int gdriver=DETECT,gmode,errorcode,i,j,k;initgraph(&gdriver,&gmode,"");errorcode=graphresult();if (errorcode!=grOk){printf("Graphics error: %s\n\007",grapherrormsg(errorcode));exit(1);}setbkcolor(9);//This line needs to be changedfor(i=0;i<11;i++){setcolor(ZodiacBack[i]);line(200,i*8+100,440,i*8+100);}delay(1000);for(j=0;j<17;j++)for(i=0;i<11;i++){setcolor(ZodiacBack[(i+j)%16]);line(200,i*8+100,440,i*8+100);delay(4);}for(j=0;j<18;j++){for(i=0;i<14;i++){for(k=7;k>=0;k--)if((ZodiacSoft[j][i]>>k)&1){putpixel(i*8-k+271,j+122,14);}}delay(10);}for(j=17;j>=0;j--){for(i=0;i<14;i++)for(k=7;k>=0;k--){if((ZodiacSoft[j][i]>>k)&1)putpixel(i*8-k+271,158-j,5);}delay(10);}setcolor(15);outtextxy(295,171,"Present");getch();ArtClear();}//******************************************************* void DrawShape(int x,int y,int color){//if(x<2||x>12||y>19)// return;setcolor(color);/*line(x<<4,y<<4,x<<4,(y<<4)+14);line(x<<4,(y<<4)+14,(x<<4)+14,(y<<4)+14);line((x<<4)+14,(y<<4)+14,(x<<4)+14,y*16);line((x<<4)+14,y<<4,x<<4,y*16);line((x<<4)+1,y<<4,(x<<4)+1,(y<<4)+14);line((x<<4)+1,(y<<4)+13,(x<<4)+14,(y<<4)+13);line((x<<4)+13,(y<<4)+13,(x<<4)+13,(y<<4)+1);line((x<<4)+13,(y<<4)+1,x<<4,(y<<4)+1); */for(int i=0;i<15;i++)line(x<<4,(y<<4)+i,(x<<4)+14,(y<<4)+i);setcolor(8);line((x<<4)+15, y<<4)+1,(x<<4)+15,(y<<4)+15);line((x<<4)+1,(y<<4)+15,(x<<4)+15,(y<<4)+15);setcolor(color-8);line((x<<4)+2,(y<<4)+2,(x<<4)+12,(y<<4)+2);line((x<<4)+2,(y<<4)+2,(x<<4)+2,(y<<4)+12);}//******************************************************* void DrawNull(int x,int y){setcolor(getbkcolor());for(int i=0;i<16;i++)line(x<<4,(y<<4)+i,(x<<4)+15,(y<<4)+i);}//******************************************************* void show(int x,int y,int CurrentShape,int Status){int temp;for(int i=0;i<20;i++)for(int j=2;j<12;j++){if(back[i][j]==1)DrawShape(6+j,4+i,8);elseDrawNull(6+j,4+i);} //no matter what the status be,I will draw the backgroundfor(int l=0;l<4;l++)for(int p=0;p<4;p++){if(l+x<2||x+l>11||p+y>19)continue;//if(shape[CurrentShape][Status][p][l]+back[y+p][x+l]==1)// DrawShape(3+l+x,3+p+y,8+CurrentShape);//else//cout<<''O'';// DrawNull(3+j,3+i);if(shape[CurrentShape][Status][p][l]==1)DrawShape(6+l+x,4+p+y,ShapeColor[CurrentShape]);if(back[y+p][x+l]==1)DrawShape(6+l+x,4+p+y,8);}}//******************************************************* void DrawScore(){int temp=TotalMark;for(int i=0;i<7;i++){DrawDigital(477-i*20,65,temp%10);temp/=10;}temp=Erasered;for(i=0;i<4;i++){DrawDigital(491-i*20,111,temp%10);temp/=10;}if(Erasered==0)return;for(i=1;i<5;i++){setfillstyle(1,8);bar(378,163+i*14,508,170+i*14);setfillstyle(1,5);bar(378,163+i*14,378+130*NumOfLev[i]/ETimes,170+i*14);}DrawDigital(466,293,Speed);return;}//******************************************************* int CreateNewShape(){NewShape[1]=NewShape[0];NewShape[0]=rand()%7;setfillstyle(1,0);bar(447,240,514,288);for(int l=0;l<4;l++)for(int p=0;p<4;p++)if(shape[NewShape[0]][0][p][l]==1)DrawShape(28+l,15+p,ShapeColor[7]);return NewShape[1];}//******************************************************* int Possible(int x,int y,int CurrentShape,int Status){for(int i=0;i<4;i++){for(int j=0;j<4;j++){if(shape[CurrentShape][Status][i][j]+back[y+i][x+j]==2)//this line can also write as the following type://if(shape[CurrentShape][Status][i][j]&&back[y+i][x+j])return 0;}}return 1;}//*******************************************************void GoLeft(int&x,int&y,int&CurrentShape,int&Status){if(Possible(x-1,y,CurrentShape,Status))x--;show(x,y,CurrentShape,Status);}//******************************************************* void GoRight(int&x,int&y,int&CurrentShape,int&Status){if(Possible(x+1,y,CurrentShape,Status))x++;show(x,y,CurrentShape,Status);}//******************************************************* void GoDown(int&x,int&y,int&CurrentShape,int&Status){int AllAreOne=1,temp=0;if(Possible(x,y+1,CurrentShape,Status)){y++;show(x,y,CurrentShape,Status);return;}TotalMark+=3*CurrentShape;for(int i=0;i<4;i++)for(int j=0;j<4;j++)back[i+y][j+x]+=shape[CurrentShape][Status][i][j];for(int r=1;r<20;r++){for(int l=2;l<13;l++){if(back[r][l]==0)AllAreOne=0;}if(AllAreOne==1){for(int rr=r;rr>0;rr--)for(int ll=2;ll<13;ll++)back[rr][ll]=back[rr-1][ll];Erasered++;CEr++;temp++;}AllAreOne=1;}CurrentShape=CreateNewShape();x=DefaultX;y=DefaultY;Status=0;NumOfLev[temp]++;TotalMark+=5*temp;show(x,y,CurrentShape,Status);counter=0;if(!Possible(x,y,CurrentShape,Status)){getch();end();}if(CEr>=30){Speed=(Speed+1)%10;CEr/=30;}if(temp)ETimes++;DrawScore();return;}void ChageShape(int&x,int&y,int&CurrentShape,int&Status){if(Possible(x,y,CurrentShape,(Status+1)%4))Status=(Status+1)%4;show(x,y,CurrentShape,Status);}//******************************************************* void DrawFace(){int temp;setcolor(15);line(351,59,519,59);line(351,60,518,60);line(351,59,351,156);line(352,59,352,155);setcolor(7);line(518,61,518,154);ine(519,60,519,154);line(353,155,519,155);line(352,156,519,156);setcolor(8);for(int i=61;i<155;i++)line(353,i,517,i);setcolor(7);line(427,106,512,106);line(428,107,511,107);line(427,106,427,147);line(428,106,428,146);setcolor(15);line(512,106,512,147);line(511,107,511,146);line(428,146,511,146);line(427,147,512,147);settextstyle(DEFAULT_FONT,HORIZ_DIR,1); setcolor(14);outtextxy(357,119,"Erasered");outtextxy(370,130,"Level:");setcolor(15);line(352,167,519,167);line(352,168,518,168);line(352,169,352,407);line(353,169,353,406);setcolor(7);line(519,167,519,407);line(518,168,518,406);line(352,407,519,407);line(353,406,519,406);line(524,55,89,55); //outter border 1stline(524,55,524,411);line(89,411,524,411);line(89,55,89,411);line(524,56,89,56); //outter border 2ndline(525,55,525,411);line(89,410,524,410);line(88,55,88,411);setfillstyle(8,7);bar(94,59,336,406);//setfillstyle(1,3);//bar(128,78,296,386);for(i=0;i<8;i++)DrawDigital(357+i*20,65,0);for(i=0;i<4;i++)DrawDigital(431+i*20,111,0);setfillstyle(1,8);setcolor(12);for(i=0;i<4;i++){temp=i+''1'';outtextxy(364,177+14*i,(char*)&temp);bar(378,177+i*14,508,184+i*14);}setcolor(14);outtextxy(366,250,"Next Shape");setcolor(10);outtextxy(366,294,"Current");outtextxy(382,309,"Level");setcolor(6);outtextxy(366,334,"Message:");bar(362,348,509,398);DrawDigital(466,293,Speed);}//******************************************************* void WannaQuit(){int choise=0,temp;setfillstyle(1,8);bar(362,348,509,398);setcolor(15);outtextxy(378,355,"Are you sure to");outtextxy(368,368,"quit game?");outtextxy(410,388,"Y es");outtextxy(470,388,"No");setcolor(14);circle(399,392,4);while((temp=bioskey(0))!=7181){if(temp==19200){setcolor(8);circle(459,392,4);choise=0;setcolor(14);circle(399,392,4);}if(temp==19712){setcolor(8);circle(399,392,4);choise=1;setcolor(14);circle(459,392,4);}}if(choise==0){end();}setfillstyle(1,8);bar(362,348,509,398);return;}//******************************************************* void main(){ShowTitle();unsigned c;int CurrentShape,x=6,y=0,Status=0;oldhandler=getvect(INTR);setvect(INTR,handler);randomize();NewShape[0]=rand()%7;DrawFace();CurrentShape=CreateNewShape();show(x,y,CurrentShape,Status);while(1){if(kbhit()){c=getch();if(c==0)c=getch();switch(c){case ''s'' :Speed=(Speed+1)%10;DrawDigital(466,293,Speed);break; case DOWN :GoDown(x,y,CurrentShape,Status);break;case LEFT :GoLeft(x,y,CurrentShape,Status);break;case RIGHT :GoRight(x,y,CurrentShape,Status);break;case CHANGE :ChageShape(x,y,CurrentShape,Status);break;case ESC :WannaQuit();}}if((counter%=TimeDelay[Speed])==(TimeDelay[Speed]-1)){GoDown(x,y,CurrentShape,Status);counter=0;}}}//*******************************************************。
C语言俄罗斯方块源代码Vc6.0编译通过#include<windows.h>#include<stdio.h>#include<time.h>#include<stdlib.h>#include<malloc.h>#include<conio.h>#define MAP_WIDTH10#define MAP_HEIGHT20#define BLOCKM"■"#define BKBLOCK"□"#define OUTSTD GetStdHandle(STD_OUTPUT_HANDLE)typedef int(*PFUN)(void *pData);void ShowMapArray(int map[MAP_HEIGHT][MAP_WIDTH]);//生成方块int xyIsInarrBlock(int arrBlock[4][2], int x, int y) //有返回1 没有返回0 {int i;for (i = 0;i<4;i++)if (arrBlock[i][0] == x && arrBlock[i][1] == y)return 1;return 0;}void GetTransBlocks(int arrBlock[4][2])//坐标模式4*4方块{int nTmp, x, y;int nCount = 1;int i;int nMinx = 0, nMiny = 0;memset(arrBlock, 0, 8 * sizeof(int));while (nCount < 4){nTmp = rand() % nCount;x = arrBlock[nTmp][0];y = arrBlock[nTmp][1];nTmp = rand() % 4;switch (nTmp){case 0:x--;break;case 1:y--;break;case 2:x++;break;case 3:y++;break;}if (xyIsInarrBlock(arrBlock, x, y))continue;arrBlock[nCount][0] = x;arrBlock[nCount][1] = y;if (nMinx > x)nMinx = x;if (nMiny > y)nMiny = y;nCount++;}for (i = 0;i<4;i++){if (nMinx < 0)arrBlock[i][0] -= nMinx;if (nMiny < 0)arrBlock[i][1] -= nMiny;}}//旋转void Ratat(int arrBlock[4][2], int Direct) // driect 1 顺时针方向旋转,-1 逆时针方向旋转{int i;int nMinx, nMiny;int nTmp;for (i = 0;i<4;i++){nTmp = arrBlock[i][0];arrBlock[i][0] = arrBlock[i][1] * (-1)*Direct;arrBlock[i][1] = nTmp*Direct;if (i == 0){nMinx = arrBlock[i][0];nMiny = arrBlock[i][1];}else{if (nMinx > arrBlock[i][0])nMinx = arrBlock[i][0];if (nMiny > arrBlock[i][1])nMiny = arrBlock[i][1];}}for (i = 0;i<4;i++){if (nMinx < 0)arrBlock[i][0] -= nMinx;if (nMiny < 0)arrBlock[i][1] -= nMiny;}}void gotoxy(int x, int y){COORD pos = { x,y };SetConsoleCursorPosition(OUTSTD, pos);}void showxy(int x, int y, int bShow){COORD pos = { x * 2 + 2,y + 2 };SetConsoleCursorPosition(OUTSTD, pos);if (bShow)printf(BLOCKM);elseprintf(BKBLOCK);}void DisShowCursor(){CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(OUTSTD, &cci);cci.bVisible = FALSE;SetConsoleCursorInfo(OUTSTD, &cci);}int CheckBlockPlace(int map[MAP_HEIGHT][MAP_WIDTH], int x, int y, int block[4][2], int bShow) //判断位置是否可用{int i;if (x < 0 || y < 0 || x >= MAP_WIDTH || y >= MAP_HEIGHT)return 0;for (i = 0;i<4;i++){if (map[y + block[i][1]][x + block[i][0]] == 1 && bShow)return 0;if (y + block[i][1] >= MAP_HEIGHT || x + block[i][0] >= MAP_WIDTH)return 0;}return 1;}int ShowBlock(int x, int y, int block[4][2], int bShow){int i;for (i = 0;i<4;i++)showxy(block[i][0] + x, block[i][1] + y, bShow);return 1;}void LoadMap(int map[MAP_HEIGHT][MAP_WIDTH]){int i, j;DisShowCursor();system("cls");printf("----------------俄罗斯方块v0.1--------------");printf("\n\n");for (i = 0;i<MAP_HEIGHT;i++){printf(" ");for (j = 0;j<MAP_WIDTH;j++){if (map[i][j])printf(BLOCKM);elseprintf(BKBLOCK);}printf("\n");}gotoxy(MAP_WIDTH * 2 + 6, 4);printf("按s开始\n");gotoxy(MAP_WIDTH * 2 + 6, 5);printf("Next:");gotoxy(MAP_WIDTH * 2 + 6, 12);printf("分数:");}int gameDown(int map[MAP_HEIGHT][MAP_WIDTH], int blockxy[4][2], int nSec, PFUN OnFun, void *pOnData){int i, j, k;int nSelect;int x = 3, y = 0;static int maxy = 20;int missrow = 0;int xsum = 0;while (1){nSelect = OnFun(pOnData);if (nSelect){switch (nSelect){case 75:{if (CheckBlockPlace(map, x - 1, y, blockxy, 1))x--;}break;case 72:{Ratat(blockxy, 1);if (!CheckBlockPlace(map, x, y, blockxy, 1)){Ratat(blockxy, -1);}}break;case 77:{if (CheckBlockPlace(map, x + 1, y, blockxy, 1))x++;}break;}}else{if (CheckBlockPlace(map, x, y, blockxy, 1)){ShowBlock(x, y, blockxy, 1);Sleep(nSec);if (CheckBlockPlace(map, x, y + 1, blockxy, 1)){ShowBlock(x, y, blockxy, 0);y++;}else{for (i = 0;i<4;i++){map[y + blockxy[i][1]][x + blockxy[i][0]] = 1;}if (y < maxy)maxy = y;break;}}elsereturn -1;}}for (i = maxy;i<MAP_HEIGHT;i++){xsum = 0;for (j = 0;j<MAP_WIDTH;j++){xsum += map[i][j];}if (xsum == MAP_WIDTH){for (k = i;k >= maxy;k--)for (j = 0;j<MAP_WIDTH;j++)map[k][j] = map[k - 1][j];missrow++;LoadMap(map);}}return missrow;}// help functionvoid ShowMapArray(int map[MAP_HEIGHT][MAP_WIDTH]){int i, j;for (i = 0;i<MAP_HEIGHT;i++){COORD pos = { MAP_WIDTH * 2,i };SetConsoleCursorPosition(OUTSTD, pos);for (j = 0;j<MAP_WIDTH;j++){printf("%d", map[i][j]);}}}int GetInfo(void *pData){while (kbhit()){char ch1 = getch();if (ch1 < 0){ch1 = getch();}return ch1;}while (kbhit())getch();return 0;}int main(){int map[MAP_HEIGHT][MAP_WIDTH] = { 0 };int blockarrnow[4][2] = { 0 }, blockarrnext[4][2] = { 0 };int ch, nRe, i, j, nScro = 0, nSpeed = 300;BOOL bRun = TRUE;LoadMap(map);srand((unsigned)time(NULL));while (bRun){if (kbhit()){ch = getch();}if (ch == 's' || ch == 'S'){GetTransBlocks(blockarrnow);while (bRun){GetTransBlocks(blockarrnext);ShowBlock(MAP_WIDTH + 2, 5, blockarrnext, 1);nRe = gameDown(map, blockarrnow, nSpeed, GetInfo, NULL);for (i = 0;i<4;i++){blockarrnow[i][0] = blockarrnext[i][0];blockarrnow[i][1] = blockarrnext[i][1];}for (i = 0;i <= 4;i++)for (j = 0;j <= 4;j++){gotoxy(MAP_WIDTH * 2 + 4 + j * 2, 7 + i);printf(" ");}if (nRe < 0){bRun = FALSE;break;}else{nScro += (nRe * 100);gotoxy(MAP_WIDTH * 2 + 11, 12);printf("%d", nScro);}}}}return 0;}Vs2015 编译运行配图。
//俄罗斯方块#include "stdio.h"#include "conio.h"#include "stdlib.h"#include "windows.h"#include "time.h"#define N 17#define M 13#define K 19int s[N][M]={{0,0,0},{0,0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, {1},{1,0,0,1},{1,1,1,1,1,1,0,1,1,0,0,1,1}};/*当前状态*/inta[K][3][3]={{0,2,0,2,2,2},{0,2,0,2,2,0,0,2},{0,2,0,0,2,2,0,2},{2,2,2,0,2},{2,2,2,0,0,2 ,0},{2,0,0,2,2,2},{2,0,0,2,0,0,2,2},{0,0,2,0,0,2,0,2,2},{0,0,2,2,2,2},{2,2,2,2,0,0}, {2,2,0,0,2,0,0,2,0},{0,2,2,0,2,0,0,2,0},{{2},{2},{2}},{2,2,2},{2,2,0,2,2,0},{2,0,0,2,2,0,0,2},{0,0,2,0,2,2,0,2},{2,2,0,0,2,2},{0,2,2,2,2,0}};void Disp(){int i,j;for(i=0;i<N;i++){for(j=0;j<M;j++)printf("%c",s[i][j]?48+s[i][j]:' ');printf("┃\n");}printf("━━━━━━━━");printf("\n\n操作说明:A-->左移,D-->右移,W-->变形,ESC-->退出\n");}void Down(){int i,j,k;for(j=0;j<M;j++)if(s[N-1][j]==2)break;/*判断是否在下边界*/if(j<M)/*若方块在下边界则将方块由2变1;因为用两种不同的符号,容易判断方块是否“着陆”及左右移动时,是否碰壁*/{for(i=0;i<N;i++)for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=1;for(i=N-1;i>=0;i--){for(j=0;j<M;j++)//判断第i行是否有空格if(s[i][j]==0)break;if(j==M)/*若第i行没空格消去第i行*/for(k=i++-1;k>=0;k--)//?for(j=0;j<M;j++)s[k+1][j]=s[k][j];}return;}for(i=0;i<N-1;i++){for(j=0;j<M;j++)if(s[i][j]==2)if(s[i+1][j]!=0&&s[i+1][j]!=2)break;/*方块下方不空说明触到1了退出内循环*/ if(j<M)break;/*方块下方不空退出外循环*/}if(i<N-1||j<M){for(i=0;i<N;i++)//若已触到1则将方块由 2变1*/for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=1;for(i=N-1;i>=0;i--){for(j=0;j<M;j++)if(s[i][j]==0)break;//判断第i行是否有空格if(j==M)/*若第i行没空格消去第i行*/for(k=i++-1;k>=0;k--)for(j=0;j<M;j++)s[k+1][j]=s[k][j];}return;}for(i=N-1;i>=0;i--)for(j=0;j<M;j++)if(s[i][j]==2)s[i+1][j]=s[i][j],s[i][j]=0;/*方块下移*/}void Right(){int i,j;for(i=0;i<N;i++)if(s[i][M-1]==2)return;/* 已经在右边界退出 */for(i=0;i<N;i++)for(j=0;j<M-1;j++)if(s[i][j]==2)if(s[i][j+1]!=0&&s[i][j+1]!=2)return;/* 方块右方不空,即方块右边有1 退出 */ for(j=M-2;j>=0;j--)for(i=0;i<N;i++)if(s[i][j]==2)s[i][j+1]=s[i][j],s[i][j]=0;/* 方块右移 */}void Left(){int i,j;for(i=0;i<N;i++)if(s[i][0]==2)return;/* 已经在左边界退出 */for(i=0;i<N;i++)for(j=1;j<M;j++)if(s[i][j]==2)if(s[i][j-1]!=0&&s[i][j-1]!=2)return;/* 方块左方不空退出 */ for(j=1;j<M;j++)for(i=0;i<N;i++)if(s[i][j]==2)s[i][j-1]=s[i][j],s[i][j]=0;/* 方块左移 */}int Have()/*判断是否有可移动方块,没有返回1,否则返回0*/{int i,j;for(i=0;i<N;i++)for(j=1;j<M;j++)if(s[i][j]==2)return 0;return 1;}int Add()/*随机生成方块*/{int t,x;/*生成两随机数t和x分别作为第t种方块和第x位置出现*/int i,j;srand((unsigned int)time(NULL));t=rand()%K;x=rand()%(M-3);if(x<0) x=-x%(M-3);//?for(i=0;i<3;i++)for(j=x;j<x+3;j++)//把生成的方块存到初状态中s[i][j]=a[t][i][j-x];}void bianxing(int t,int n){int i,j,k,m,x,y;for(i=0;i<N;i++)//首先扫描是否有移动方块;及方块变形前的位置“行、列”{m=-1;for(j=0;j<M;j++)if(s[i][j]==2){m=i,x=j,y=i;break;//y,x记录所在行、列;并退出内循环}if(m!=-1)//m!=-1证明有移动方块break;//退出外循环}if(m!=-1)//m!=-1证明有移动方块{if(x+3>M||y+3>N) return;//判断是否有可变形空间,没有就返回for(i=y;i<y+3;i++)//判断是否有3*3的变形空间,没有就返回for(j=x;j<x+3;j++)if(s[i][j]==1) return;/*擦除当前移动方块;因为上面判断3*3的移动空间,是从上面开始扫描,遇到第一个小格子时,依他为基点向右下方扫描是否有3*3的空间;显然只进行下面的变形--存储是不行的;如:002002022-->2220020时,显然前面的方格倒数第二个2,留在了3*3变形空间的外面,输出图形将多一个格子,所以要在变形-->存储操作前进行擦除操作*/for(i=y;i<y+3;i++)for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=0;//变形并把它存储到当前状态中if(t<=3&&t>=0){static int h1;if(h1>n)h1=0;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h1][i-y][j-x];h1++;}else if(t<=11&&t>=4){static int h2=4;if(h2>n)h2=4;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h2][i-y][j-x];h2++;}else if(t<=13&&t>=12){static int h3=12;if(h3>n)h3=12;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h3][i-y][j-x];h3++;}else if(t<=18&&t>=15){static int h4=15;if(h4>n)h4=0;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h4][i-y][j-x];h4++;}}void main(){char c;int i=0,t;char str[][50]={" ((`'-\"``\"\"-'`))"," ) - - ( "," / (o _ o) \ "," \ ( 0 ) /"," _'-.._'='_..-'_ "," /`;#'#'#.-.#'#'#;`\ "," \_)) '#' ((_/ "," #. ☆ Game ☆ # "," '#. Over! .#' "," / '#. .#' \ "," _\ \'#. .#'/ /_"," (((___) '#' (___) ",""};system("color 0a");while(1)/*判断是否有按键,没有循环输出i,否则停,conio.h*/{if(!kbhit())/*kbhit用来判断是否有按键输入,若有按键返回非零值,否则返回零;没有按键时c被赋予一个“非操作键值”,它将一直下移;有按键是调用getch函数,读取键值*/c='2';elsec=getch();if(c=='p')//停止键;按任意键可解除停止getch();system("CLS");/*清屏,TC用clrscr();,VC用system("CLS");*/if(Have())//Have()判断是否有可移动方块,没有返回1,否则返回0t=Add();switch(c){case 'a':Left();break; /*左移*/case 'd':Right();break; /*右移*/case 27: system("pause");return; /*按Esc(=27)另存后退出*/default:;}//变形if(c=='w')if(t>=0&&t<=3) bianxing(t,3);else if(t>=4&&t<=11) bianxing(t,11);else if(t==12||t==13) bianxing(t,13);else if(t>=15&&t<=18) bianxing(t,18);c='2';Down();//判断方块的停、走和消除//判断顶层是否有1 有:游戏结束for(i=0;i<M;i++)if(s[0][i]==1){system("CLS");i=0;while(1){if(strlen(str[i])==0)break;printf("%s\n",str[i++]);}system("pause");exit(0);}Disp();//刷屏Sleep(500);/*睡眠ms,windows.h*/}}***********************************************************。
#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语⾔源码实现俄罗斯⽅块介绍俄罗斯⽅块(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); // 放⼊当前⽅块。
一个c语言写的俄罗斯方块的代码#include <stdlib.h>#include <graphics.h>#include <bios.h>#define mDRAW 5#define mLINE 6#define mADOWN 7#define mGEN 8#define mLEFT 75#define mRIGHT 77#define mSPACE 57#define mESC 1#define TIMEINT 2#define MAXX 9#define MAXY 30#define BACKCOLOR BLACK#define WINX 50#define WINY 470#define GAP 6#define AREAX (WINX+GAP) #define AREAY (WINY-GAP)int oldarea[MAXY+1][MAXX];int area[MAXY+1][MAXX];int actW,actH,actX,actY;int curX,curY,curColor,curW,curH;int newX,newY,newColor,newW,newH; int active;int box[4][4];int FORCOLOR;int MESSAGE;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} },{{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,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}}};void init();void draw();int genBox();int getKey(); void lineFull(); int moveLeft(); int moveRight(); int moveDown();int rotate();int getW();int getH();void clearOldBox();void putNewBox();int collisionRotate(int box[][4]); void getMessage();void dispatchMessage();int timeCome();void fallDown();int gameOver();main(){int i;/*printf("This program is made by xiezhijian");*/ init();do{getMessage();dispatchMessage();}while(!gameOver());getch();closegraph();}void getMessage(){if(MESSAGE) return;if(timeCome()){MESSAGE=mADOWN; return;}if(bioskey(1)){MESSAGE=bioskey(0)>>8; return;}}void dispatchMessage(){switch(MESSAGE){case mLEFT: moveLeft();break; case mRIGHT: moveRight();break;case mADOWN: moveDown();break; case mSPACE: rotate();break;case mDOWN: fallDown(); break; case mDRAW: draw();break;case mLINE: lineFull();break;case mGEN: genBox();break; case mESC: closegraph(); exit(0); default: MESSAGE=0;}}void fallDown(){while(active){moveDown(); draw(); }MESSAGE=mLINE;}int timeCome(){static long tm, old;tm=biostime(0,tm);if(tm-old<TIMEINT) return 0; else{old=tm; return 1;}}void init(){int i,j,x1,y1,x2,y2;int driver=DETECT, mode=0; randomize();registerbgidriver(EGAVGA_driver); initgraph(&driver,&mode,""); cleardevice();setfillstyle(SOLID_FILL,BLUE);bar(0,0,639,479);x1=AREAX;y1=AREAY-BOXW*MAXY;x2=AREAX+MAXX*BOXW;y2=AREAY;rectangle(--x1,--y1,++x2,++y2); setfillstyle(SOLID_FILL,BLACK);bar(++x1,++y1,--x2,--y2);y1=AREAY-MAXY*BOXW; y2=AREAY; setcolor(DARKGRAY);for(i=0;i<MAXX;i++){x1=AREAX+i*BOXW;line(x1,y1,x1,y2);}x1=AREAX; x2=x1+MAXX*BOXW;for(j=0;j<MAXY;j++){y1=AREAY-j*BOXW;line(x1,y1,x2,y1);}for(j=0;j<MAXY;j++)for(i=0;i<MAXX;i++)area[j][i]=oldarea[j][i]=0;actX=0; actY=0; actW=MAXX-1; actH=MAXY-1; draw();MESSAGE=mGEN;}int genBox(){int i,j,boxidx;boxidx=random(7); FORCOLOR=random(7)+1; for(j=0;j<4;j++)for(i=0;i<4;i++)box[j][i]=BOX[boxidx][j][i];curW=getW(); curH=getH();curX=(MAXX+curW)/2;if(curX+curW>=MAXX)curX=MAXX-1-curW; curY=MAXY-1-curH;newX=curX; newY=curY; actX=curX;actY=curY;actW=newW=curW; actH=newH=curH; active=1;if(collision(box)) return 0;putNewBox();draw(); MESSAGE=0;return 1;}void lineFull(){int row,col, rowEnd,full,i,j;rowEnd=newY+newH;if(rowEnd>=MAXY-1) rowEnd=MAXY-2;for(row=newY; row<=rowEnd;){full=1;for(col=0;col<MAXX;col++)if(!area[row][col]){full=0; break;}if(!full){++row; continue;}for(j=row; j<MAXY-1;j++)for(i=0;i<MAXX;i++)area[j][i]=area[j+1][i];actX=0;actY=row; actW=MAXX-1; actH=MAXY-1-row;draw(); rowEnd--;}MESSAGE=mGEN;}void draw(){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,BACKCOLOR);elsesetfillstyle(SOLID_FILL,FORCOLOR);x1=AREAX+col*BOXW; x2=x1+BOXW;y1=AREAY-(row+1)*BOXW; y2=y1+BOXW;bar(++x1,++y1,--x2,--y2);oldarea[row][col]=area[row][col];}MESSAGE=0;}int moveLeft(){newX=curX-1; clearOldBox(); if(collision(box)){newX=curX;putNewBox(); MESSAGE=0;return 0;}putNewBox();actW=curW+1; actX=curX=newX; MESSAGE=mDRAW;return 1;}int moveRight(){newX=curX+1; clearOldBox();if(collision(box)){newX=curX;putNewBox();MESSAGE=0;return 0;}putNewBox();actW=curW+1; actX=curX; curX=newX; MESSAGE=mDRAW;return 1;}int moveDown(){int i,j;newY=curY-1; clearOldBox();if(collision(box)){newY=curY; putNewBox(); active=0; MESSAGE=mLINE; return 0;}putNewBox();actH=curH+1; actY=newY; curY=newY; MESSAGE=mDRAW;return 1;}int rotate(){int newBox[4][4];int i,j;clearOldBox();for(j=0;j<4;j++)for(i=0;i<4;i++)newBox[j][i]=0;for(i=0;i<4;i++)newBox[curW-i][j]=box[j][i];newW=curH; newH=curW;if(collisionRotate(newBox)){newW=curW; newH=curH; newX=curX; newY=curY; putNewBox();MESSAGE=0;return 0;}for(i=0;i<4;i++)box[j][i]=newBox[j][i];putNewBox();actH=newH>curH? newH:curH; actW=curX+actH-newX;actX=newX; actY=newY; curX=newX; curY=newY; curW=newW; curH=newH; MESSAGE=mDRAW;return 1;}int getW(){int i,j;for(i=3;i>0;i--)for(j=0;j<4;j++)if(box[j][i]) return i; return 0;}int getH(){int i,j;for(j=3;j>0;j--)for(i=0;i<4;i++)if(box[j][i]) return j; return 0;}void clearOldBox(){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 putNewBox(){int i,j;for(j=0;j<=newH;j++)for(i=0;i<=newW;i++)if(box[j][i])area[newY+j][newX+i]=FORCOLOR; }int collision(int cbox[][4]){if(newX<0) return 1;if(newX+newW>=MAXX) 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]&&cbox[j][i]) return 1; return 0;}int collisionRotate(int cbox[][4]){if(newX+newW>=MAXX) newX=MAXX-1-newW; if(newY+newH>=MAXY) newY=MAXY-1-newH; if(collision(cbox)) 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 collision(cbox);}int gameOver(){if(!active &&(curY+curH>MAXY-3)) return 1; else return 0;}。
/*学无止境*/ #include <stdlib.h>#include <stdio.h>#include <graphics.h>#define ESC 27#define UP 328#define DOWN 336#define LEFT 331#define RIGHT 333#define BLANK 32#define BOTTOM 2#define CANNOT 1#define CAN 0#define MAX 30#define F1 315#define ADD 43#define EQUAL 61#define DEC 45#define SOUNDs 115#define SOUNDS 83#define PAUSEP 80#define PAUSEp 112void Init();void Down();void GoOn();void ksdown();void Display(int color);void Give();int Touch(int x,int y,int dx,int dy);int GeyKey();void Select();void DetectFill();void GetScores();void Fail();void Help();void Quit();void DrawBox(int x,int y,int Color);void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch);void DrawNext(int Color);int Heng=12,Shu=20; /*横竖*/int Position[MAX][MAX];int middle[MAX][MAX];int ActH,ActS;int Act,Staus;int i,j,k;int Wid=10;int NoPass=CAN;float Delays=15000;int BeginH=250,BeginS=7;float Seconds=0;int Scores=0;int flag=1;int Sounds=CAN;int PreAct,NextAct;int a[8][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},{1,1,1,1,0,0,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},{1,1,0,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},{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,0},{0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{0,1,0,0,1,1,0,0,1,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,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,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}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}; int b[4][4];main(int argc,char *argv[]){if (argc!=1){if (argv[1]!="")Heng=atoi(argv[1]);if (argv[2]!="")Shu=atoi(argv[2]);}Init(); /*初始化界面*/PreAct=random(8); /*取得当前的方块*/for(;;) /*以下是游戏流程*/{NextAct=random(8); /*取得下一个方块*/ DrawNext(1); /*画出下一个方块*/Act=PreAct;if (Heng%2==0) ActH=Heng/2;else ActH=(Heng-1)/2;ActS=0; /*方块开始从游戏空间的中间下落*/ Staus=0; /*取开始的状态*/NoPass=CAN; /*物体可以下落*/Give(); /*取得当前的方块*/Display(Act+1); /*显示当前的方块,每种方块的颜色不同*/ GoOn(); /*游戏的算法精髓所在*/PreAct=NextAct; /*方块下落完毕,取得下一个方块*/ DrawNext(0);}}void Init(){int GraphDriver=DETECT,GraphMode;registerbgidriver(EGAVGA_driver);initgraph(&GraphDriver,&GraphMode,"");if (kbhit()) Sounds=CANNOT;setcolor(1);OutTextXY(10,10,"Tetris");OutTextXY(30,30,"Version 2.0");OutTextXY(10,120,"Help:");OutTextXY(20,140,"+ :Faster");OutTextXY(20,160,"- :Slower");OutTextXY(20,180,"Esc :Quit");OutTextXY(20,200,"F1 :Help");OutTextXY(10,310,"Copyright(c) 1998.2.22"); OutTextXY(10,320,"By Mr. Unique");outtextxy(10,250,"Score: 00000");rectangle(BeginH-3,BeginS-3,BeginH+Heng*(Wid+2)+2,BeginS+Sh u*(Wid+2)+2);rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Sh u*(Wid+2)+4);rectangle(BeginH+(Heng+4)*(Wid+2)-2,BeginS+10,BeginH+(Heng+ 8)*(Wid+2)+2,BeginS+12+4*(Wid+2));for (i=0;i<MAX;i++)for (j=0;j<MAX;j++){Position[i][j]=1;middle[i][j]=-1;}for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)Position[i][j]=0;for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)DrawBox(i,j,0);randomize();}void GoOn(){for(;;){Seconds+=0.2; /*控制方块的下落速度*/ if (Seconds>=Delays){Down();Seconds=0;if (NoPass==BOTTOM){DetectFill();middle[ActH][ActS]=Act;if (ActS==0)Fail();return;}}if (kbhit())Select();}}void Down() /*方块下降*/{Display(0);if (Touch(ActH,ActS,0,1)==CAN)ActS++;elsemiddle[ActH][ActS]=Act;Display(Staus+1);}int Touch(int x,int y,int dx,int dy) {NoPass=CAN;for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+dx+i][y+dy+j]+=b[i][j]; for (i=0;i<MAX;i++)for (j=0;j<MAX;j++)if (Position[i][j]>1)NoPass=CANNOT;for (i=0;i<4;i++)for (j=0;j<4;j++){Position[x+dx+i][y+dy+j]-=b[i][j]; middle[x+dx+i][y+dy+j]=Act;}if (NoPass==CANNOT && dx==0 && dy==1) {for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+i][y+j]+=b[i][j];NoPass=BOTTOM;}return NoPass;}int GetKey(void){int Ch,Low,Hig;Ch=bioskey(0);Low=Ch&0x00ff;Hig=(Ch&0xff00)>>8;return(Low==0?Hig+256:Low);}void Select(){int OldStaus,acts=ActS;switch(GetKey()){case ESC :Quit();break;case DOWN :Seconds+=14500;break;case LEFT :Display(0);if (ActH>0 && Touch(ActH,ActS,-1,0)==CAN) { ActH--;}Display(Act+1);break;case RIGHT :Display(0);if (ActH<Heng && Touch(ActH,ActS,1,0)==CAN) { ActH++;}Display(Act+1);break;case BLANK : Display(0);ksdown();Display(Act+1);break;case F1 :Help();break;case EQUAL :case ADD :if (Delays>300) Delays-=100;break; case DEC :if (Delays<3000) Delays+=100;break; case PAUSEP :case PAUSEp :getch();break;case SOUNDS :case SOUNDs :if (Sounds==CAN)Sounds=CANNOT;elseSounds=CAN;break;case UP :if(Act==7){while(acts<Shu-1&&Position[ActH][acts]!=1)acts++;Position[ActH][acts]=0;DrawBox(ActH,acts,0);acts=ActS;break;}else{Display(0);OldStaus=Staus;switch(Act){case 0:case 3:case 4:if (Staus==1) Staus=0;else Staus=1;break;case 1:break;case 2:case 5:case 6:if (Staus==3) Staus=0;else Staus++;break; }Give();if (Touch(ActH,ActS,0,0)==CANNOT){Staus=OldStaus;Give();}Display(Act+1);break;}}}void ksdown(){while(flag){if(Touch(ActH,ActS,0,0)==CAN){ActS++;}else {ActS--;flag=0;}}flag=1;}void Quit(){int ch,TopScore;FILE *fp;if ((fp=fopen("Russian.scr","r+"))!=NULL) {fscanf(fp,"%d",&TopScore);if (Scores>TopScore){setcolor(1);outtextxy(470,80,"Hello !");outtextxy(470,100,"In all the players,"); outtextxy(470,120,"You are the First !"); outtextxy(470,140,"And your score will"); outtextxy(470,160,"be the NEW RECORD !"); fseek(fp,0L,0);fprintf(fp,"%d",Scores);fclose(fp);}setcolor(1);OutTextXY(470,220,"Are You Sure (Yes/no)?"); ch=getch();if (ch=='y'||ch=='Y'){closegraph();delay(20);exit(0);}setcolor(0);outtextxy(470,220,"Are You Sure (Yes/no)?"); }void OutTextXY(int x,int y,char *String) {int i=0;char a[2];moveto(x,y);a[1]='\0';while (*(String+i)!='\0')a[0]=*(String+i);outtext(a);if (Sounds==CAN && a[0]!=' ') {sound(3000);delay(50);nosound();}i++;}}void Help(){unsigned Save;void *Buf;Save=imagesize(160,120,500,360); Buf=malloc(Save);getimage(160,120,500,360,Buf); setfillstyle(1,1);bar(160,120,500,280);setcolor(0);OutTextXY(170,130," About & Help");OutTextXY(170,150," # # # ########## # # # "); OutTextXY(170,160," # ## # # # # # # ###### ### "); OutTextXY(170,170," ########## ########## ## # # "); OutTextXY(170,180," # # # # # # # ## #### "); OutTextXY(170,190," # ## # #### ## # # # "); OutTextXY(170,200," # ## # # # # # ## # # # "); OutTextXY(170,210," # # # ## ## # ###### # # # "); OutTextXY(170,220," ## # ## # ## # # # # "); OutTextXY(170,230," # ## # #### # ## # "); OutTextXY(170,260," Good Luckly to You ");getch();putimage(160,120,Buf,0);free(Buf);}void GetScores(){int Sec10000,Sec1000,Sec100,Sec10,Sec1;setfillstyle(0,1);bar(60,250,109,260);Sec1=Scores%10;Sec10=(Scores%100-Scores%10)/10;Sec100=(Scores%1000-Scores%100)/100;Sec1000=(Scores%10000-Scores%1000)/1000; Sec10000=(Scores%100000-Scores%10000)/10000; DispScore(60,250,'0'+Sec10000);DispScore(70,250,'0'+Sec1000);DispScore(80,250,'0'+Sec100);DispScore(90,250,'0'+Sec10);DispScore(100,250,'0'+Sec1);DispScore(110,250,'0');DispScore(120,250,'0');}void DispScore(int x,int y,char Ch){char a[2];a[1]='\0';a[0]=Ch;outtextxy(x,y,a);}void Give(){for (i=0;i<4;i++)for (j=0;j<4;j++)b[i][j]=a[Act][Staus][i][j];}void Display(int color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (b[i][j]==1) DrawBox(ActH+i,ActS+j,color); }void DrawBox(int x,int y,int Color){x=BeginH+x*(Wid+2);y=BeginS+y*(Wid+2);setfillstyle(1,Color);bar(x+2,y+2,x+Wid-1,y+Wid-1);if (Color==0)setcolor(9);elsesetcolor(Act+1);rectangle(x+4,y+4,x+Wid-4,y+Wid-4);}void DrawNext(int Color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (a[NextAct][0][i][j]==1) DrawBox(Heng+4+i,1+j,Color); }void DetectFill(){int Number,Fall,FallTime=0;for (i=Shu-1;i>=0;i--){Number=0;for (j=0;j<Heng;j++)if (Position[j][i]==1) Number++;if (Number==Heng){FallTime++;if (Sounds==CAN){sound(500);delay(500);nosound();}for (Fall=i;Fall>0;Fall--)for (j=0;j<Heng;j++){Position[j][Fall]=Position[j][Fall-1]; middle[j][Fall]=middle[j][Fall-1];if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,middle[j][Fall]+1);}i++;}}switch(FallTime){case 0:break;case 1:Scores+=1;break;case 2:Scores+=3;break;case 3:Scores+=6;break;case 4:Scores+=10;break;}if (FallTime!=0){GetScores();if (Scores%100==0) Delays-=100;}}void Fail(){if (Sounds==CAN){for (k=0;k<3;k++){sound(300);delay(200);nosound();}}setcolor(1);OutTextXY(440,200,"Game over!"); Quit();closegraph();exit(0);}。
先是效果图:主菜单:游戏:设置:错误处理:627行,代码如下:#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(getc h()){case'1':system("cls");//play函数覆盖界面而不是清屏,所以需要先清屏play();break;case'2':sets();break;case'3':highscores();break;case'4':copyright();break;case'5':savehs();//保存数据saveset();return0;}}}catch(int errnum)//错误处理{system("cls");printf("o(>﹏<)o 出错啦!\n程序收到了一条错误信息,错误码是:%d(%s)\n您可以联系我们解决这个问题。
\n",errnum,errword[errnum]);printf("\n你可以选择以下操作:\n1.重启程序\n2.以默认设置重启程序\n3.向设置和数据文件写入默认设置然后重启\n4.退出\n");switch(getc h()){case'1':goto start1;case'2':gameset.xs=20;gameset.ys=20;gameset.speed=100;strcpy(gameset.sqr,"[]");//无法直接给数组复制数据strcpy(gameset.no," ");strcpy(gameset.frame,"::");int i;for(i=0;i<10;i++)strcpy(rating[i].name,"未命名"),rating[i].score=0;goto start2;case'3':{ofstream fout;fout.open("set.ini");fout<<"20\n20\n100[]\n \n::\n";fout.close();fout.clear();fout.open("highscore.dat");int j;for(j=0;j<10;j++)fout<<"未命名\n0\n";goto start1;}default:return-1;//返回异常退出}}return0;}void play(){mapsetup();//初始化/*for(int i=0;i<20;i++)set(i,19,SQR);*/while(newsqr())//不断新建方块,直到返回NO{while(move(DOWN)!=CANTMOVE)//每次向下移动方块,直到不能移动 {guide+=1;//向下移动一次加1分show();//显示while(kbhit())//不断处理键盘,直到没有按键{switch(getc h())//获取按键{case'w':move(UP);break;case's':move(DOWN);break;case'a':move(LEFT);break;case'd':move(RIGHT);break;}}Sleep(gameset.speed);//延时}movetomap();//退出循环时无法向下移动,把当前方块移动到地图上int line;while((line=wholeline())!=-1);//不断检查是否出现整行,直到没有deleteline(line);//删除整行}endup();//无法新建方块,游戏结束return;//结束}//函数定义void mapsetup(){map=new int[gameset.xs*gameset.ys];//申请内存if(!map)//如果申请到0throw no_enough_memory;//抛出异常//初始化地图int i,j;for(i=0;i<gameset.xs;i++){for(j=0;j<gameset.ys;j++){set(i,j,NO);}}guide=0;//分数清零return;}int get(int x,int y){if(y<0)//上方虚拟为空return NO;if(x>=0&&x<gameset.xs&&y>=0&&y<gameset.ys)//是否在地图范围内return*(map+y*gameset.xs+x);//提取数据elsereturn SQR;//虚拟地图侧面和底部有方块}void set(int x,int y,int date){if(x>=0&&x<gameset.xs&&y>=0&&y<gameset.ys)//if(x>0&&x<gameset.xs&&y>0&&y< gameset.ys)//是否在地图范围内*(map+y*gameset.xs+x)=date;//写入return;}bool newsqr(){int i,j;for(i=0;i<4;i++)//检查下一个方块要出现的地方是否有方块if(get(gameset.xs/2+i,0)==SQR)return false;//有方块,创建失败int which=rand()%7;//随机选择形状for(i=0;i<4;i++){for(j=0;j<4;j++){now[i][j]=shap[which][i][j];//复制形状}}for(i=rand()%4;i>0;i--)//旋转随机0-3次move(UP);xnow=gameset.xs/2;//设置坐标ynow=-4;return true;}int move(int direction){int x,y;//储存坐标偏移量int i,j;switch(direction){case UP://上键是旋转bool newshap[4][4];//储存旋转后的图形for(i=0;i<4;i++){for(j=0;j<4;j++){newshap[i][j]=now[j][3-i];//坐标变换}}for(i=0;i<4;i++){for(j=0;j<4;j++){if(newshap[i][j]==true&&get(xnow+i,ynow+j)==SQR)//对新图形碰撞检测return CANTMOVE;//不能旋转}}for(i=0;i<4;i++){for(j=0;j<4;j++){now[i][j]=newshap[i][j];//检测完毕,复制形状}}return OK;case DOWN://先记录坐标的偏移量,确定没有碰撞以后移动x=0,y=1;break;case LEFT:x=-1;y=0;break;case RIGHT:x=1,y=0;break;}for(i=0;i<4;i++){for(j=0;j<4;j++){if(now[i][j]==true&&get(i+x+xnow,j+y+ynow)==SQR)//如果和地图上的方块重合(边缘以外get函数也返回SQR,不必单独处理)//if(get(i+x,j+y)==SQR)//if(now[i+x][j+y]==SQR) {return CANTMOVE;//无法移动}}}xnow+=x;//检测完毕,更改坐标ynow+=y;return OK;}void movetomap(){guide+=10;//成功放置方块,加10分int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){if(now[i][j]==true)set(xnow+i,ynow+j,SQR);//复制方块到地图}}return;}int wholeline(){int i,j;bool whole;//储存是否是整行for(j=0;j<gameset.ys;j++)//for(i=0;i<gameset.ys;i++){whole=true;//假设是整行for(i=0;i<gameset.xs;i++)//for(j=0;j<gameset.xs;j++){if(get(i,j)==NO)whole=false;//有空,不是整行}if(whole)return j;//是整行,返回}return-1;//没找到整行,返回}void deleteline(int which){int i,j;guide+=1000;//消方块,奖励分数for(i=which;i>=0;i--){for(j=0;j<gameset.xs;j++){set(j,i,get(j,i-1));//移动上面的所有方块,覆盖这一行。