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*/}}***********************************************************。
先是效果图:主菜单:游戏:设置:错误处理: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));//移动上面的所有方块,覆盖这一行。