大二的时候学了C语言后,利用easyX图形函数库写的一个简单版本的俄罗斯方块小游戏。游戏可使用方向键上下左右移动、变形,满行后自动消除,同时根据消行的数量进行延时的动态变化,计分等。
分享给大家,一起学习!
源码: #include <stdio.h> #include <stdlib.h> #include <time.h> #include "graphics.h" //图形函数库,可以网上百度下载 #include <conio.h> #include <string.h> #define BOUNDARY 10 #define BLOCKS_WIDTH 20 //小方块的长度 #define WINDOW_WIDTH BLOCKS_WIDTH*20 //横向可以放置五个块 #define WINDOW_HIGH BLOCKS_WIDTH*30 //竖向可以最多叠起来的个数 #define DATA_WIDTH 150 //数据显示的宽度 #define KEY_UP (0x6000+72) #define KEY_DOWN (0x6000+80) #define KEY_LEFT (0x6000+75) #define KEY_RIGHT (0x6000+77) #define KEY_SPACE 32 //空格用来暂停 #define KEY_ENTER 13 int CurBigBack1[4][20][2]={0}; int CurBigBack[30][20][2]={0}; int grade = 0; int level = 0; void setfont( int nHeight); ///定义当前方块结构体 struct BlocksAttr { int X; int Y; int Type; int Color; int Direct; }Blocks,Blocksprior; //复制 void copy(void) { Blocks.X = Blocksprior.X ; Blocks.Y = Blocksprior.Y ; Blocks.Type = Blocksprior.Type ; Blocks.Color = Blocksprior.Color ; Blocks.Direct = Blocksprior.Direct ; } //定义方块颜色种类 int BlocksColor[7]= { LIGHTCYAN, YELLOW, GREEN, RED, BLACK, BLUE, LIGHTGRAY }; //定义7中方块 int BlocksPoint[7][4][4][4]= { //正L 0,1,0,0, 0,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, 0,0,1,0, 1,1,1,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, 1,1,1,0, 1,0,0,0, 0,0,0,0, //反L 0,0,1,0, 0,0,1,0, 0,1,1,0, 0,0,0,0, 0,0,0,0, 1,1,1,0, 0,0,1,0, 0,0,0,0, 0,1,1,0, 0,1,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0, 1,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,0, 0,1,1,0, 0,0,0,0, //正N 0,0,0,0, 0,1,1,0, 1,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,0,0, 0,1,1,0, 1,1,0,0, 0,0,0,0, 0,1,0,0, 0,1,1,0, 0,0,1,0, 0,0,0,0, //| 0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0, 1,1,1,1, 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,0, 1,1,1,1, 0,0,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, 0,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0, 0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,1,0, 0,1,1,0, 0,0,1,0, 0,0,0,0, //反N 0,0,0,0, 1,1,0,0, 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, 1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,1,0, 0,1,1,0, 0,1,0,0, 0,0,0,0, }; //随机功能 void initBlocks(void) { Blocksprior.Color=BlocksColor[rand()%7]; Blocksprior.Direct=rand()%4; Blocksprior.Type=rand()%7; Blocksprior.X=8; Blocksprior.Y=-4; } //画方块 void dispBlocks(int flag = 0,BlocksAttr Block=Blocks,int preview = 0)//画当前方块 { int i,j; if (!preview) { setfillstyle(BLACK); bar(0,0,WINDOW_WIDTH+BOUNDARY,BOUNDARY); } if (flag) { setfillstyle(WHITE);//设置填充模式和颜色 setcolor(WHITE);//设置当前画线颜色 } else { setfillstyle(Block.Color);//设置填充模式和颜色 setcolor(WHITE);//设置当前画线颜色 } for(i=0;i<4;i++) { for (j=0;j<4;j++) { if(BlocksPoint[Block.Type][Block.Direct][i][j]) { if (preview) { bar3d(BOUNDARY+WINDOW_WIDTH+BOUNDARY*2+j*(DATA_WIDTH-BOUNDARY*3)/4,BOUNDARY*2+i*(DATA_WIDTH-BOUNDARY*3)/4,BOUNDARY+WINDOW_WIDTH+BOUNDARY*2+(j+1)*(DATA_WIDTH-BOUNDARY*3)/4 ,BOUNDARY*2+(i+1)*(DATA_WIDTH-BOUNDARY*3)/4,0,1); } else { bar3d(BOUNDARY+(Block.X+j)*BLOCKS_WIDTH,BOUNDARY+(Block.Y+i)*BLOCKS_WIDTH,BOUNDARY+(Block.X+j+1)*BLOCKS_WIDTH,BOUNDARY+(Block.Y+i+1)*BLOCKS_WIDTH,0,1);//画小格子 } } } } } //方块移动 bool judgePos(int x, int y, int z)//判断方块移动 { int i,j; for(i=0;i<4;i++) { for (j=0;j<4 j="" if="" blockspoint="" blocks="" type="" blocks="" direct="" z="">3?0:Blocks.Direct+z][i][j]) { if (Blocks.X+j+x<0 blocks="" x="" j="" x="">19||Blocks.Y+i+y>29) //Blocks.x : 方块当前的位置 j : 方块里填充的矩形数 {//x : 按键操作后的方块位置 return false; } if (CurBigBack[Blocks.Y+i+y][Blocks.X+j+x][0]) { return false; } } } } return true; } //获取键盘按值 int getKey(void) { int key; key=getch(); if (key==224) { key=getch(); if (key==72||key==80||key==75||key==77) { key=0x6000+key; } } return key; } //保存落定方块 void save() { for (int i = 0; i <4 ; i++) { for (int j = 0; j < 4 ; j++) { if (BlocksPoint[Blocks.Type][Blocks.Direct][i][j]) { CurBigBack[Blocks.Y+i][Blocks.X+j][0]=1; CurBigBack[Blocks.Y+i][Blocks.X+j][1]=Blocks.Color; } } } for (int a=0;a<30;a++) { for (int b=0;b<20 b="" printf="" d="" curbigback="" a="" b="" 0="" printf="" n="" void="" diamonddown="" int="" a="" int="" temp="0;" while="" 1="" for="" int="" i="a" i=""> 0 ; i--) { temp=0; for (int j = 0 ; j < 20 ; j++) { CurBigBack[i][j][0] = 0; CurBigBack[i][j][0] = CurBigBack[i-1][j][0]; CurBigBack[i][j][1] = CurBigBack[i-1][j][1]; if (CurBigBack[i-1][j][0]==0) { temp++; if (temp == 20) { return; } } } } } } //消除满行 void lineEliminate(void) { int temp=0; int count=0; setfillstyle(WHITE);//设置填充模式和颜色 setcolor(WHITE);//设置当前画线颜色 for (int a = 0 ; a < 30 ; a++) { temp = 0; for (int b = 0 ; b < 20 ; b++) { if (CurBigBack[a][b][0]) { temp++; if (temp == 20) { count++; diamondDown(a); } } } } switch(count) { case 1: grade+=10; break; case 2: grade+=30; break; case 3: grade+=50; break; case 4: grade+=80; break; } level = grade/100; bar(BOUNDARY,BOUNDARY,WINDOW_WIDTH+BOUNDARY,BOUNDARY+WINDOW_HIGH); for (int x = 0 ; x < 30 ; x++) { for (int y = 0 ; y < 20 ; y++) { if (CurBigBack[x][y][0]) { setfillstyle(CurBigBack[x][y][1]); bar3d(BOUNDARY+y*BLOCKS_WIDTH,BOUNDARY+x*BLOCKS_WIDTH,BOUNDARY+(y+1)*BLOCKS_WIDTH,BOUNDARY+(x+1)*BLOCKS_WIDTH,0,1); } } } } //游戏结束 bool gameOver(void) { LOGFONT font; for (int b = 0 ; b < 20 ; b++ ) { if(CurBigBack[0][b][0]) { return true; } } return false; } //主函数 void main(void) { int key; DWORD tim; LOGFONT font; int pass=1; char ch; char temp[10]; time_t t; srand((unsigned) time(&t)); /* while (1) { key=getch(); printf("%d\n",key); }*/ initgraph(BOUNDARY+WINDOW_WIDTH+BOUNDARY+DATA_WIDTH,BOUNDARY+WINDOW_HIGH+BOUNDARY,1);//初始化界面 setfillstyle(WHITE); bar(BOUNDARY,BOUNDARY,WINDOW_WIDTH+BOUNDARY,BOUNDARY+WINDOW_HIGH);//画出游戏区 bar(BOUNDARY+WINDOW_WIDTH+BOUNDARY*2,BOUNDARY*2,WINDOW_WIDTH+DATA_WIDTH,DATA_WIDTH-BOUNDARY); tim = GetTickCount(); initBlocks(); copy(); BeginBatchDraw(); while(1) { initBlocks();//随机生成一个BLOCKS dispBlocks(0,Blocksprior,1); setfillstyle(WHITE); setcolor(BLACK); setbkcolor(WHITE); bar(BOUNDARY+WINDOW_WIDTH+BOUNDARY*2,WINDOW_HIGH/2,WINDOW_WIDTH+DATA_WIDTH,WINDOW_HIGH/2+DATA_WIDTH); outtextxy(BOUNDARY+WINDOW_WIDTH+BOUNDARY*3,WINDOW_HIGH/2+BOUNDARY,"得分:"); outtextxy(BOUNDARY+WINDOW_WIDTH+BOUNDARY*5,WINDOW_HIGH/2+3*BOUNDARY,itoa(grade,temp,10)); outtextxy(BOUNDARY+WINDOW_WIDTH+BOUNDARY*3,WINDOW_HIGH/2+6*BOUNDARY,"等级:"); outtextxy(BOUNDARY+WINDOW_WIDTH+BOUNDARY*5,WINDOW_HIGH/2+8*BOUNDARY,itoa(level,temp,10)); while(1) { dispBlocks();//显示BLOCKS FlushBatchDraw(); if (kbhit())//检查当前按下的键 { key=getKey(); switch(key) { case KEY_DOWN: if (judgePos(0,1,0)) { dispBlocks(1); Blocks.Y++; } break; case KEY_UP://控制旋转,4->3,3->2,2->1,1->4 if (judgePos(0,0,1)) { dispBlocks(1); Blocks.Direct++; if (Blocks.Direct>3) { Blocks.Direct=0; } } break; case KEY_LEFT: if (judgePos(-1,0,0) ) { dispBlocks(1); Blocks.X--; } break; case KEY_RIGHT: if(judgePos(1,0,0)) { dispBlocks(1); Blocks.X++; } break; case KEY_SPACE: while (pass) { ch = getch();//空格暂停,按任意继续 switch(ch) { case KEY_SPACE: pass = 0; break; case 'q': return; } } pass = 1; break; } } if (GetTickCount() - tim > 500) { tim = GetTickCount(); if (judgePos(0,1,0)) { dispBlocks(1); Blocks.Y++; } else { save(); lineEliminate(); break; } } } if (gameOver()) { getfont(&font); setfont(40,40, "ss"); outtextxy(30,40,"GAME OVER"); setfont(20,20, "ss"); outtextxy(60,120,"按下ENTER键"); outtextxy(60,140,"重新开始游戏"); setfont(&font); FlushBatchDraw(); while (1) { ch = getKey(); if (ch == KEY_ENTER) { memset(CurBigBack,0,sizeof(CurBigBack)); memset(CurBigBack1,0,sizeof(CurBigBack1)); lineEliminate(); break; } if (ch == 'q') { return; } } } dispBlocks(1,Blocksprior,1); copy(); } closegraph(); }
