C语言_俄罗斯方块_VS2010

合集下载

C语言实现俄罗斯方块(转)

C语言实现俄罗斯方块(转)

C语⾔实现俄罗斯⽅块(转)原⽂地址如下:在图书馆看到⼀本书有俄罗斯⽅块的源程序⾃⼰当年也是俄罗斯⽅块的爱好者便想分析分析这个⼩游戏的源代码这⼏天有空就看了看发现读源码对编程领悟很有帮助读完深深的感觉到程序的确是好的数据结构加上好的算法这段程序定义了两个数据结构分别是//游戏底板结构,表⽰每个⼩⽅块所具有的属性struct BOARD{//当前状态,只有0或1,1表⽰次⼩⽅块已被占⽤int var;//⼩⽅块的颜⾊int color;}Table_board[Vertical_boxs][Horizontal_boxs];//游戏跳出的⽅块结构struct SHAPE{//⼀个字节等于8位,每四位来表⽰⼀个游戏⽅块的⼀⾏//如box[0]="0x88",box[1]="oxc0"表⽰的是://1000//1000//1100//0000//以此来表⽰游戏⽅块的各种形状char box[2];//游戏⽅块的颜⾊int color;//下⼀个游戏⽅块的编号int next;//这个next设计的也是相当妙啊};该源码的算法更确切的说是游戏的逻辑读完也是很有体会把握好⼤的系统强⼤的逻辑能⼒是必要的平时⾃⼰还是要再数据结构和算法这些⽅⾯加强学习、锻炼这段程序还有就是中断不是很理解还需要时间领悟⼀下下⾯贴⼀下我的程序注释这个游戏的层次描述:1预览功能2控制功能俄罗斯⽅块 3显⽰更新功能4分数更新功能5游戏帮助功能下⾯是源码:(该程序⽤到了TC的图形库,所以VC下是运⾏不了的,不过VC做代码编辑阅读⽐较⽅便,所以代码注释采⽤了VC下的//)//加载头⽂件#include <stdio.h>#include <stdlib.h>#include <dos.h>#include <graphics.h>//加载tc图形库//定义按键码#define VK_LEFT 0x4b00#define VK_RIGHT 0x4d00#define VK_DOWN 0x5000#define VK_UP 0x4800#define VK_ESC 0x011b//设置中断号 1c:时钟中断时得到控制权,若要固定时间发⽣事件,可以通过修改1c中断来得到#define TIMER 0x1c//共有19种形态的游戏⽅块#define MAX_BOX 19//⽅块的边长为20#define BSIZE 20//显⽰游戏界⾯的左上⾓x坐标#define Sys_x 160//显⽰游戏界⾯的左上⾓y坐标#define Sys_y 25//⽔平⽅向的⽅块数量#define Horizontal_boxs 10//垂直⽅向的⽅块数量#define Vertical_boxs 15//第⼀个游戏⽅块的产⽣起始位置#define Begin_boxs_x Horizontal_boxs/2//前景⾊#define FgColor 3//背景⾊#define BgColor 0//右边状态栏的x坐标#define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+46#define false 0#define true 1//移动的⽅向#define MoveLeft 1#define MoveRight 2#define MoveDown 3#define MoveRoll 4//保存当前游戏⽅块编号int current_box_numb;//保存游戏⽅块的当前坐标int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;//是否要产⽣新游戏⽅块int flag_newbox=false;//下落速度int speed=1;//游戏得分int score=0;//每等级所需要分数int speed_step=30;//指向原来时钟中断处理过程⼊⼝的中断处理函数指针关键字interrupt指定⼀个函数应该被看成⼀个中断函数void interrupt(*oldtimer)(void);//游戏底板结构,表⽰每个⼩⽅块所具有的属性struct BOARD{//当前状态,只有0或1,1表⽰次⼩⽅块已被占⽤int var;//⼩⽅块的颜⾊int color;}Table_board[Vertical_boxs][Horizontal_boxs];//游戏跳出的⽅块结构struct SHAPE{//⼀个字节等于8位,每四位来表⽰⼀个游戏⽅块的⼀⾏//如box[0]="0x88",box[1]="oxc0"表⽰的是://1000//1000//1100//0000//以此来表⽰游戏⽅块的各种形状char box[2];//游戏⽅块的颜⾊int color;//下⼀个游戏⽅块的编号int next;};//初始化游戏⽅块的内容,包括形状颜⾊和下⼀个游戏⽅块编号struct SHAPE shapes[MAX_BOX]={{0x88,0xc0,CYAN,1},{0xe8,0x0,CYAN,2},{0xc4,0x40,CYAN,3},{0x2e,0x0,CYAN,0},{0x44,0xc0,MAGENTA,5},{0x8e,0x0,MAGENTA,6},{0xc8,0x80,MAGENTA,7},{0xe2,0x0,MAGENTA,4},{0x8c,0x40,YELLOW,9},{0x6c,0x0,YELLOW,8},{0x4c,0x80,BROWN,11},{0xc6,0x0,BROWN,10},{0x4e,0x0,WHITE,13},{0x8c,0x80,WHITE,14},{0xe4,0x0,WHITE,15},{0x4c,0x40,WHITE,12},{0x88,0x88,RED,17},{0xf0,0x0,RED,16},{0xcc,0x0,BLUE,18},};//定时计数器变量unsigned int TimerCounter=0;//以下为函数声明void initialize(int,int,int,int);void interrupt newtimer(void);void SetTimer(void interrupt(*IntProc)(void));void KillTimer(void);void ShowScore(int);void ShowSpeed(int);void show_help(int,int);void setFullRow(int);int DelFullRow(int);void show_box(int,int,int,int);void EraseBox(int,int,int);void ErasePreBox(int,int,int);int MkNextBox(int);int MoveAble(int,int,int,int);//主函数void main(){int GameOver=0;int key,nextbox;int Currentaction=0;int gd=VGA,gm=VGAHI,errorcode;initgraph(&gd,&gm,"");errorcode=graphresult();if(errorcode!=grOk){printf("\nNotice:Graphics error: %s\n",grapherrormsg(errorcode));printf("Press any key to quit!");getch();exit(1);}setbkcolor(BgColor);setcolor(FgColor);randomize();SetTimer(newtimer);initialize(Sys_x,Sys_y,Horizontal_boxs,Vertical_boxs);//初始化nextbox=MkNextBox(-1);show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color); show_box(LeftWin_x,Curbox_y+320,nextbox,shapes[nextbox].color);show_help(Sys_x,Curbox_y+320);getch();while (1){Currentaction=0;flag_newbox=false;//int bioskey(int cmd)//完成直接键盘操作,cmd的值决定执⾏什么操作//cmd=0,返回下⼀个键盘键⼊的值//cmd=1,查询是否按下⼀个键,若按下⼀个键返回⾮零值,否则返回0if(bioskey(1)){key=bioskey(0);}else{key=0;}switch(key){case VK_LEFT:if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveLeft)){EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x-=BSIZE;Currentaction=MoveLeft;}break;case VK_RIGHT:if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveRight)){EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x+=BSIZE;Currentaction=MoveRight;}break;case VK_DOWN:if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown)){EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;Currentaction=MoveDown;}elseflag_newbox=true;break;case VK_UP:if(MoveAble(Curbox_x,Curbox_y,shapes[current_box_numb].next,MoveRoll)){EraseBox(Curbox_x,Curbox_y,current_box_numb);current_box_numb=shapes[current_box_numb].next;Currentaction=MoveLeft;}break;case VK_ESC:GameOver=1;break;default:break;}if (Currentaction)//当前有动作就执⾏{show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color); Currentaction=0;}if(flag_newbox)//按了向下键,但不能下移就产⽣新的游戏⽅块{ErasePreBox(LeftWin_x,Sys_y+200,nextbox);nextbox=MkNextBox(nextbox);show_box(LeftWin_x,Curbox_y+200,nextbox,shapes[nextbox].color);if(!MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown)){show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color); GameOver=1;}else{flag_newbox=false;}Currentaction=0;}else//⾃由下落{if(Currentaction==MoveDown||TimerCounter>(20-speed*2)){if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown)){EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color); }TimerCounter=0;}}if(GameOver){printf("game over,thank you! your score is %d",score);getch();break;}}getch();KillTimer();closegraph();}//******************************************************************** //显⽰帮助,提⽰⽤户如何进⾏游戏的相关操作//void show_help(int xs,int ys){char stemp[50];setcolor(15);//void far rectangle(int x0,int y0,int x1,int y1)//以(x0,y0)为左上⾓,(x1,x2)为右下⾓画⼀个矩形框rectangle(xs,ys,xs+239,ys+100);//sprintf()//将字串格式化到字符串sprintf(stemp," -Roll -Downwards");stemp[0]=24;stemp[8]=25;setcolor(14);//void far outtextxy(int x,int y,char far *text)//将⽂本输出到指定位置outtextxy(xs+40,ys+30,stemp);sprintf(stemp," -Turn Left -Turn Right");stemp[0]=27;stemp[13]=26;outtextxy(xs+40,ys+45,stemp);outtextxy(xs+40,ys+60,"Esc-Exit");setcolor(FgColor);}//******************************************************************* //对游戏界⾯的初始化void initialize(int x,int y,int m,int n){int i,j,oldx;oldx=x;for(j=0;j<n;j++){for(i=0;i<m;i++){Table_board[j][i].var=0;Table_board[j][i].color=BgColor;line(x,y,x+BSIZE,y);line(x,y,x,y+BSIZE);line(x,y+BSIZE,x+BSIZE,y+BSIZE);line(x+BSIZE,y,x+BSIZE,y+BSIZE);x+=BSIZE;}y+=BSIZE;x=oldx;}Curbox_x=x;Curbox_y=y;flag_newbox=false;speed=1;score=0;ShowScore(score);ShowSpeed(speed);}//*************************************************************//显⽰当前⽤户的成绩void ShowScore(int score){int x,y;char score_str[5];setfillstyle(SOLID_FILL,BgColor);y=100;//确定⼀个以(x0,y0)为左上⾓,(x1,x2)为右下⾓的矩形窗⼝,再按规定图形和颜⾊填充bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);sprintf(score_str,"%3d",score);outtextxy(x,y,"SCORE");outtextxy(x,y+10,score_str);}//**********************************************************//显⽰当前下落速度void ShowSpeed(int speed){int x,y;char speed_str[5];setfillstyle(SOLID_FILL,BgColor);x=LeftWin_x;y=150;bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);sprintf(speed_str,"%3d",speed);outtextxy(x,y,"Level");outtextxy(x,y+10,speed_str);outtextxy(x,y+50,"Nextbox");}//**********************************************************//定义新的时钟中断处理函数void interrupt newtimer(void){//调⽤原来的例程(*oldtimer)();//全局计数器变量加1TimerCounter++;}//********************************************************//设置新的时钟中断处理void SetTimer(void interrupt (*IntProc)(void)){//获取中断号为TIMER的中断处理函数的⼊⼝地址oldtimer=getvect(TIMER);//设置新的时钟中断处理过程时,禁⽌所有中断disable();//将中断号为TIMER的中断处理函数⼊⼝地址改为IntProc()函数的⼊⼝地址setvect(TIMER,IntProc);//开启中断enable();}//*********************************************************//恢复原有的时钟中断处理过程void KillTimer(){disable();setvect(TIMER,oldtimer);enable();}//********************************************************//在(x,y)位置开始,⽤指定的颜⾊显⽰编号为box_num的游戏⽅块void show_box(int x,int y,int box_num,int color){int i,ii,ls_x=x;//指定的游戏⽅块不存在if(box_num<0||box_num>=MAX_BOX)box_num=MAX_BOX/2;//void far setfillstyle(int pattern,int color)//以pattern为填充模式以color为填充颜⾊对指定图形进⾏填充setfillstyle(SOLID_FILL,color);{int mask=128;//掩码,⽤于位运算//单个⽅块填充for(i=0;i<8;i++){if(i%4==0&&i!=0)//表⽰转到游戏⽅块的下⼀⾏了{y+=BSIZE;x=ls_x;}if((shapes[box_num].box[ii])&mask){bar(x,y,x+BSIZE,y+BSIZE);line(x,y,x+BSIZE,y);line(x,y,x,y+BSIZE);line(x,y+BSIZE,x+BSIZE,y+BSIZE);line(x+BSIZE,y,x+BSIZE,y+BSIZE);}x+=BSIZE;mask/=2;}y+=BSIZE;x=ls_x;}}//***************************************************************//清除(x,y)位置开始的编号为box_num的boxvoid EraseBox(int x,int y,int box_num){int mask=128,t_boardx,t_boardy,n,m;setfillstyle(SOLID_FILL,BgColor);for(n=0;n<4;n++){for (m=0;m<4;m++){if(((shapes[box_num].box[n/2])&mask)){bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE);line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE,y+n*BSIZE+BSIZE);line(x+m*BSIZE,y+n*BSIZE+BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); line(x+m*BSIZE+BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); }mask/=2;if(mask==0)mask=128;}}}//*******************************************************//同EraseBox()void ErasePreBox(int x,int y,int box_numb){int mask=128,t_boardx,t_boardy,n,m;setfillstyle(SOLID_FILL,BgColor);for(n=0;n<4;n++){for(m=0;m<4;m++){if(((shapes[box_numb].box[n/2])&mask)){bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);}mask/=2;if(mask==0)mask=128;}}}//***************************************************************//将新图形的游戏⽅块放置在游戏板上,并返回此游戏⽅块号int MkNextBox(int box_numb){int mask=128,t_boardx,t_boardy,n,m;t_boardx=(Curbox_x-Sys_x)/BSIZE;t_boardy=(Curbox_y-Sys_y)/BSIZE;for(n=0;n<4;n++){for(m=0;m<4;m++){if(((shapes[current_box_numb].box[n/2])&mask)){//设置游戏⽅块Table_board[t_boardy+n][t_boardx+m].var=1;Table_board[t_boardy+n][t_boardx+m].color=shapes[current_box_numb].color;}mask=mask/2;if(mask==0)mask=128;}}setFullRow(t_boardy);//初始化坐标Curbox_x=Sys_x+Begin_boxs_x*BSIZE;Curbox_y=Sys_y;if(box_numb==-1)box_numb=rand()%MAX_BOX;//随机产⽣游戏⽅块current_box_numb=box_numb;flag_newbox=false;return (rand()%MAX_BOX);}//***********************************************************//⽤于找到满⾏,参数t_boardy表⽰当前的游戏⽅块号void setFullRow(int t_boardy){int n,full_numb=0,top=0;//top保存当前游戏主板在消除满⾏后的最⾼点,⽤于游戏主板的重绘register m;//寄存器类型,存取速度快for(n=t_boardy+3;n>=t_boardy;n--){if(n<0||n>=Vertical_boxs)continue;for(m=0;m<Horizontal_boxs;m++){if(!Table_board[n+full_numb][m].var)//发现有⼀个是空的就跳过break;}if(m==Horizontal_boxs)//找到满⾏{if(n==t_boardy+3)top=DelFullRow(n+full_numb);//清除该⾏,并保存最⾼点elseDelFullRow(n+full_numb);full_numb++;//保存满⾏的⾏数}}if(full_numb)//存在满⾏{int oldx,x=Sys_x,y=BSIZE*top+Sys_y;oldx=x;score=score+full_numb*10;for(n=top;n<t_boardy+4;n++){if(n>=Vertical_boxs)continue;//重绘游戏主板for(m=0;m<Horizontal_boxs;m++){if(Table_board[n][m].var){setfillstyle(SOLID_FILL,Table_board[n][m].color);}elsesetfillstyle(SOLID_FILL,BgColor);bar(x,y,x+BSIZE,y+BSIZE);line(x,y,x+BSIZE,y);line(x,y,x,y+BSIZE);line(x,y+BSIZE,x+BSIZE,y+BSIZE);line(x+BSIZE,y,x+BSIZE,y+BSIZE);x+=BSIZE;}y+=BSIZE;x=oldx;}ShowScore(score);if(speed!=score/speed_step){speed=score/speed_step;ShowSpeed(speed);}elseShowSpeed(speed);}}//************************************************************//处理删除⾏,参数y指明具体哪⼀⾏为满⾏int DelFullRow(int y){int n,top=0;register m,totoal;for (n=y;n>=0;n--){totoal=0;for(m=0;m<Horizontal_boxs;m++){if(!Table_board[n][m].var)totoal++;//没有⽅格,对计数器加1//上⾏不等于下⾏就把上⾏传给下⾏,此处为程序优化部分,也可不优化 if(Table_board[n][m].var!=Table_board[n-1][m].var){Table_board[n][m].var=Table_board[n-1][m].var;Table_board[n][m].color=Table_board[n-1][m].color;}}//发现上⾯有连续的空⾏,提前结束if (totoal==Horizontal_boxs){top=n;break;}}return top;//返回最⾼点}//********************************************************8//判断⽅块是否可以移动,(x,y)为当前游戏⽅块位置,box_numb为游戏⽅块号,direction为动作标识int MoveAble(int x,int y,int box_numb,int direction){int n,m,t_boardx,t_boardy;int mask;if(direction==MoveLeft)//如果向左移动{mask=128;x-=BSIZE;t_boardx=(x-Sys_x)/BSIZE;t_boardy=(y-Sys_y)/BSIZE;for(n=0;n<4;n++){for(m=0;m<4;m++){if((shapes[box_numb].box[n/2])&mask){if((x+BSIZE*m)<Sys_x)//碰到最左边return false;else if(Table_board[t_boardy+n][t_boardx+m].var)//左移⼀个单位后,与游戏主板冲突return false;}mask/=2;if(mask==0)mask=128;}}return true;}else if(direction==MoveRight)//右移动{x+=BSIZE;t_boardx=(x-Sys_x)/BSIZE;t_boardy=(y-Sys_y)/BSIZE;mask=128;for(n=0;n<4;n++){for(m=0;m<4;m++){if((shapes[box_numb].box[n/2])&mask){if((x+BSIZE*m)>=(Sys_x+BSIZE*Horizontal_boxs))//碰到最右边return false;else if(Table_board[t_boardy+n][t_boardx+m].var)//与游戏主板冲突return false;}mask/=2;if(mask==0)mask=128;}}return true;}else if(direction==MoveDown)//下移动{mask=128;y+=BSIZE;t_boardx=(x-Sys_x)/BSIZE;t_boardy=(y-Sys_y)/BSIZE;for(n=0;n<4;n++){for(m=0;m<4;m++){if((shapes[box_numb].box[n/2])&mask){if((y+BSIZE*n)>=(Sys_y+BSIZE*Vertical_boxs)||Table_board[t_boardy+n][t_boardx+m].var)//碰到最下边或向下有冲突 {flag_newbox=true;break;}}mask/=2;if(mask==0)mask=128;}}if(flag_newbox)return false;elsereturn true;}else if(direction==MoveRoll)//旋转{mask=128;t_boardx=(x-Sys_x)/BSIZE;t_boardy=(y-Sys_y)/BSIZE;for(n=0;n<4;n++){for(m=0;m<4;m++){if((shapes[box_numb].box[n/2])&mask){if((y+BSIZE*n)>=(Sys_y+BSIZE*Vertical_boxs))//碰到最下边return false;if((x+BSIZE*n)>=(Sys_x+BSIZE*Horizontal_boxs))//碰到最左边return false;if((x+BSIZE*m)>=(Sys_x+BSIZE*Horizontal_boxs))//碰到最右边return false;else if (Table_board[t_boardy+n][t_boardx+m].var)//向下有冲突{return false;}}mask/=2;if(mask==0)mask=128;}}return true;}elsereturn false;}。

俄罗斯方块c语言源代码

俄罗斯方块c语言源代码

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

俄罗斯方块C语言代码

俄罗斯方块C语言代码

#include <stdio.h>#include <dos.h>#include <conio.h>#include <graphics.h>#include <stdlib.h>#ifdef__cplusplus#define __CPPARGS ...#else#define __CPPARGS#endif#define MINBOXSIZE 15 /* 最小方块的尺寸*/#define BGCOLOR 7 /* 背景着色*/#define GX 200#define GY 10#define SJNUM 10000 /* 每当玩家打到一万分等级加一级*/ /* 按键码*/#define VK_LEFT 0x4b00#define VK_RIGHT 0x4d00#define VK_DOWN 0x5000#define VK_UP 0x4800#define VK_HOME 0x4700#define VK_END 0x4f00#define VK_SPACE 0x3920#define VK_ESC 0x011b#define VK_ENTER 0x1c0d/* 定义俄罗斯方块的方向(我定义他为4种)*/#define F_DONG 0#define F_NAN 1#define F_XI 2#define F_BEI 3#define NEXTCOL 20 /* 要出的下一个方块的纵坐标*/#define NEXTROW 12 /* 要出的下一个方块的横从标*/#define MAXROW 14 /* 游戏屏幕大小*/#define MAXCOL 20#define SCCOL 100 /*游戏屏幕大显示器上的相对位置*/#define SCROW 60int gril[22][16]; /* 游戏屏幕坐标*/int col=1,row=7; /* 当前方块的横纵坐标*/int boxfx=0,boxgs=0; /* 当前寺块的形壮和方向*/int nextboxfx=0,nextboxgs=0,maxcol=22;/*下一个方块的形壮和方向*/ int minboxcolor=6,nextminboxcolor=6;int num=0; /*游戏分*/int dj=0,gamedj[10]={18,16,14,12,10,8,6,4,2,1};/* 游戏等级*//* 以下我用了一个3维数组来纪录方块的最初形状和方向*/int boxstr[7][4][16]={{{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},{0,1,0,0,1,1,0,0,1,0,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},{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}},{{1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0},{1,1,1,0,1,0,0,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},{0,0,1,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,0,0,0,1,1,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},{1,1,1,0,0,0,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,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}},{{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,0,1,1,1,0,0,1,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0},{0,1,0,0,1,1,1,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}}};/* 随机得到当前方块和下一个方块的形状和方向*/void boxrad(){minboxcolor=nextminboxcolor;boxgs=nextboxgs;boxfx=nextboxfx;nextminboxcolor=random(14)+1;if(nextminboxcolor==4||nextminboxcolor==7||nextminboxcolor==8) nextminboxcolor=9;nextboxfx=F_DONG;nextboxgs=random(7);}/*初始化图形模试*/void init(int gdrive,int gmode){int errorcode;initgraph(&gdrive,&gmode,"e:\\tc");errorcode=graphresult();if(errorcode!=grOk){printf("error of: %s",grapherrormsg(errorcode));exit(1);}}/* 在图形模式下的清屏*/void cls(){setfillstyle(SOLID_FILL,0);setcolor(0);bar(0,0,640,480);}/*在图形模式下的高级清屏*/void clscr(int a,int b,int c,int d,int color){setfillstyle(SOLID_FILL,color);setcolor(color);bar(a,b,c,d);}/*最小方块的绘制*/void minbox(int asc,int bsc,int color,int bdcolor){int a=0,b=0;a=SCCOL+asc;b=SCROW+bsc;clscr(a+1,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE,color);if(color!=BGCOLOR){setcolor(bdcolor);line(a+1,b+1,a-1+MINBOXSIZE,b+1);line(a+1,b+1,a+1,b-1+MINBOXSIZE);line(a-1+MINBOXSIZE,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE); line(a+1,b-1+MINBOXSIZE,a-1+MINBOXSIZE,b-1+MINBOXSIZE); }}/*游戏中出现的文字*/void txt(int a,int b,char *txt,int font,int color){setcolor(color);settextstyle(0,0,font);outtextxy(a,b,txt);}/*windows 绘制*/void win(int a,int b,int c,int d,int bgcolor,int bordercolor){clscr(a,b,c,d,bgcolor);setcolor(bordercolor);line(a,b,c,b);line(a,b,a,d);line(a,d,c,d);line(c,b,c,d);}/* 当前方块的绘制*/void funbox(int a,int b,int color,int bdcolor){int i,j;int boxz[4][4];for(i=0;i<16;i++)boxz[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(boxz[i][j]==1)minbox((j+row+a)*MINBOXSIZE,(i+col+b)*MINBOXSIZE,color,bdcolor); }/*下一个方块的绘制*/void nextfunbox(int a,int b,int color,int bdcolor){int i,j;int boxz[4][4];for(i=0;i<16;i++)boxz[i/4][i%4]=boxstr[nextboxgs][nextboxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(boxz[i][j]==1)minbox((j+a)*MINBOXSIZE,(i+b)*MINBOXSIZE,color,bdcolor);}/*时间中断定义*/#define TIMER 0x1cint TimerCounter=0;void interrupt ( *oldhandler)(__CPPARGS);void interrupt newhandler(__CPPARGS){TimerCounter++;oldhandler();}void SetTimer(void interrupt (*IntProc)(__CPPARGS)){oldhandler=getvect(TIMER);disable();setvect(TIMER,IntProc);enable();}/*由于游戏的规则,消掉都有最小方块的一行*/void delcol(int a){int i,j;for(i=a;i>1;i--)for(j=1;j<15;j++){minbox(j*MINBOXSIZE,i*MINBOXSIZE,BGCOLOR,BGCOLOR);gril[i][j]=gril[i-1][j];if(gril[i][j]==1)minbox(j*MINBOXSIZE,i*MINBOXSIZE,minboxcolor,0);}/*消掉所有都有最小方块的行*/ void delete(){int i,j,zero,delgx=0;char *nm="00000";for(i=1;i<21;i++){zero=0;for(j=1;j<15;j++)if(gril[j]==0)zero=1;if(zero==0){delcol(i);delgx++;}}num=num+delgx*delgx*10;dj=num/10000;sprintf(nm,"%d",num);clscr(456,173,500,200,4);txt(456,173,"Number:",1,15);txt(456,193,nm,1,15);}/*时间中断结束*/void KillTimer(){disable();setvect(TIMER,oldhandler); enable();}/* 测试当前方块是否可以向下落*/ int downok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i+1][row+j])k=0;return(k);/* 测试当前方块是否可以向左行*/int leftok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i][row+j-1])k=0;return(k);}/* 测试当前方块是否可以向右行*/int rightok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i][row+j+1])k=0;return(k);}/* 测试当前方块是否可以变形*/int upok(){int i,j,k=1,a[4][4];for(i=0;i<4;i++)for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx+1][i];for(i=3;i>=0;i--)for(j=3;j>=0;j--)if(a[j] && gril[col+i][row+j])k=0;return(k);}/*当前方块落下之后,给屏幕坐标作标记*/ void setgril(){int i,j,a[4][4];funbox(0,0,minboxcolor,0);for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j])gril[col+i][row+j]=1;col=1;row=7;}/*游戏结束*/void gameover(){int i,j;for(i=20;i>0;i--)for(j=1;j<15;j++)minbox(j*MINBOXSIZE,i*MINBOXSIZE,2,0);txt(103,203,"Game Over",3,10);}/*按键的设置*/void call_key(int keyx){switch(keyx){case VK_DOWN: { /*下方向键,横坐标加一。

c语言怎样编写俄罗斯方块

c语言怎样编写俄罗斯方块

linesCleared++; for (int k = i; k > 0; k--) {
for (int j = 0; j < WIDTH; j++) { board[k][j] = board[k - 1][j];
} } for (int j = 0; j < WIDTH; j++) {
board[0][j] = 0; } } } printf("Lines cleared: %d\n", linesCleared); }
if (kbhit()) { char key = getch(); switch (key) { case 'a': if (!checkCollision(shapeX - 1, shapeY, shape)) { shapeX--; } break; case 'd': if (!checkCollision(shapeX + 1, shapeY, shape)) { shapeX++; } break; case 's': if (!checkCollision(shapeX, shapeY + 1, shape)) { shapeY++; } break; case 'w': int tempShape[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { tempShape[i][j] = shape[i][j]; } } rotateShape(tempShape); if (!checkCollision(shapeX, shapeY, tempShape)) { rotateShape(shape); } break; case 'q': exit(0); }

俄罗斯方块C语言代码(计算机类)

俄罗斯方块C语言代码(计算机类)

#include <stdio.h>#include <dos.h>#include <conio.h>#include <graphics.h>#include <stdlib.h>#ifdef__cplusplus#define __CPPARGS ...#else#define __CPPARGS#endif#define MINBOXSIZE 15 /* 最小方块的尺寸*/#define BGCOLOR 7 /* 背景着色*/#define GX 200#define GY 10#define SJNUM 10000 /* 每当玩家打到一万分等级加一级*/ /* 按键码*/#define VK_LEFT 0x4b00#define VK_RIGHT 0x4d00#define VK_DOWN 0x5000#define VK_UP 0x4800#define VK_HOME 0x4700#define VK_END 0x4f00#define VK_SPACE 0x3920#define VK_ESC 0x011b#define VK_ENTER 0x1c0d/* 定义俄罗斯方块的方向(我定义他为4种)*/#define F_DONG 0#define F_NAN 1#define F_XI 2#define F_BEI 3#define NEXTCOL 20 /* 要出的下一个方块的纵坐标*/#define NEXTROW 12 /* 要出的下一个方块的横从标*/#define MAXROW 14 /* 游戏屏幕大小*/#define MAXCOL 20#define SCCOL 100 /*游戏屏幕大显示器上的相对位置*/#define SCROW 60int gril[22][16]; /* 游戏屏幕坐标*/int col=1,row=7; /* 当前方块的横纵坐标*/int boxfx=0,boxgs=0; /* 当前寺块的形壮和方向*/int nextboxfx=0,nextboxgs=0,maxcol=22;/*下一个方块的形壮和方向*/ int minboxcolor=6,nextminboxcolor=6;int num=0; /*游戏分*/int dj=0,gamedj[10]={18,16,14,12,10,8,6,4,2,1};/* 游戏等级*//* 以下我用了一个3维数组来纪录方块的最初形状和方向*/int boxstr[7][4][16]={{{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},{0,1,0,0,1,1,0,0,1,0,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},{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}},{{1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0},{1,1,1,0,1,0,0,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},{0,0,1,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,0,0,0,1,1,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},{1,1,1,0,0,0,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,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}},{{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,0,1,1,1,0,0,1,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0},{0,1,0,0,1,1,1,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}}};/* 随机得到当前方块和下一个方块的形状和方向*/void boxrad(){minboxcolor=nextminboxcolor;boxgs=nextboxgs;boxfx=nextboxfx;nextminboxcolor=random(14)+1;if(nextminboxcolor==4||nextminboxcolor==7||nextminboxcolor==8) nextminboxcolor=9;nextboxfx=F_DONG;nextboxgs=random(7);}/*初始化图形模试*/void init(int gdrive,int gmode){int errorcode;initgraph(&gdrive,&gmode,"e:\\tc");errorcode=graphresult();if(errorcode!=grOk){printf("error of: %s",grapherrormsg(errorcode));exit(1);}}/* 在图形模式下的清屏*/void cls(){setfillstyle(SOLID_FILL,0);setcolor(0);bar(0,0,640,480);}/*在图形模式下的高级清屏*/void clscr(int a,int b,int c,int d,int color){setfillstyle(SOLID_FILL,color);setcolor(color);bar(a,b,c,d);}/*最小方块的绘制*/void minbox(int asc,int bsc,int color,int bdcolor){int a=0,b=0;a=SCCOL+asc;b=SCROW+bsc;clscr(a+1,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE,color);if(color!=BGCOLOR){setcolor(bdcolor);line(a+1,b+1,a-1+MINBOXSIZE,b+1);line(a+1,b+1,a+1,b-1+MINBOXSIZE);line(a-1+MINBOXSIZE,b+1,a-1+MINBOXSIZE,b-1+MINBOXSIZE); line(a+1,b-1+MINBOXSIZE,a-1+MINBOXSIZE,b-1+MINBOXSIZE); }}/*游戏中出现的文字*/void txt(int a,int b,char *txt,int font,int color){setcolor(color);settextstyle(0,0,font);outtextxy(a,b,txt);}/*windows 绘制*/void win(int a,int b,int c,int d,int bgcolor,int bordercolor){clscr(a,b,c,d,bgcolor);setcolor(bordercolor);line(a,b,c,b);line(a,b,a,d);line(a,d,c,d);line(c,b,c,d);}/* 当前方块的绘制*/void funbox(int a,int b,int color,int bdcolor){int i,j;int boxz[4][4];for(i=0;i<16;i++)boxz[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(boxz[i][j]==1)minbox((j+row+a)*MINBOXSIZE,(i+col+b)*MINBOXSIZE,color,bdcolor); }/*下一个方块的绘制*/void nextfunbox(int a,int b,int color,int bdcolor){int i,j;int boxz[4][4];for(i=0;i<16;i++)boxz[i/4][i%4]=boxstr[nextboxgs][nextboxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(boxz[i][j]==1)minbox((j+a)*MINBOXSIZE,(i+b)*MINBOXSIZE,color,bdcolor);}/*时间中断定义*/#define TIMER 0x1cint TimerCounter=0;void interrupt ( *oldhandler)(__CPPARGS);void interrupt newhandler(__CPPARGS){TimerCounter++;oldhandler();}void SetTimer(void interrupt (*IntProc)(__CPPARGS)){oldhandler=getvect(TIMER);disable();setvect(TIMER,IntProc);enable();}/*由于游戏的规则,消掉都有最小方块的一行*/void delcol(int a){int i,j;for(i=a;i>1;i--)for(j=1;j<15;j++){minbox(j*MINBOXSIZE,i*MINBOXSIZE,BGCOLOR,BGCOLOR); gril[i][j]=gril[i-1][j];if(gril[i][j]==1)minbox(j*MINBOXSIZE,i*MINBOXSIZE,minboxcolor,0);}}/*消掉所有都有最小方块的行*/void delete(){int i,j,zero,delgx=0;char *nm="00000";for(i=1;i<21;i++){zero=0;for(j=1;j<15;j++)if(gril[j]==0)zero=1;if(zero==0){delcol(i);delgx++;}}num=num+delgx*delgx*10;dj=num/10000;sprintf(nm,"%d",num);clscr(456,173,500,200,4);txt(456,173,"Number:",1,15);txt(456,193,nm,1,15);}/*时间中断结束*/void KillTimer(){disable();setvect(TIMER,oldhandler);enable();}/* 测试当前方块是否可以向下落*/int downok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i+1][row+j])k=0;return(k);}/* 测试当前方块是否可以向左行*/ int leftok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i][row+j-1])k=0;return(k);}/* 测试当前方块是否可以向右行*/ int rightok(){int i,j,k=1,a[4][4];for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i]; for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j] && gril[col+i][row+j+1])k=0;return(k);}/* 测试当前方块是否可以变形*/int upok(){int i,j,k=1,a[4][4];for(i=0;i<4;i++)for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx+1][i]; for(i=3;i>=0;i--)for(j=3;j>=0;j--)if(a[j] && gril[col+i][row+j])k=0;return(k);}/*当前方块落下之后,给屏幕坐标作标记*/void setgril(){int i,j,a[4][4];funbox(0,0,minboxcolor,0);for(i=0;i<16;i++)a[i/4][i%4]=boxstr[boxgs][boxfx][i];for(i=0;i<4;i++)for(j=0;j<4;j++)if(a[j])gril[col+i][row+j]=1;col=1;row=7;}/*游戏结束*/void gameover(){int i,j;for(i=20;i>0;i--)for(j=1;j<15;j++)minbox(j*MINBOXSIZE,i*MINBOXSIZE,2,0);txt(103,203,"Game Over",3,10);}/*按键的设置*/void call_key(int keyx){switch(keyx){case VK_DOWN: { /*下方向键,横坐标加一。

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

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

C语⾔实现俄罗斯⽅块源代码本⽂实例为⼤家分享了C语⾔实现俄罗斯⽅块的具体代码,供⼤家参考,具体内容如下GitHub:Head.h#ifndef _HEAD_H_#define _HEAD_H_#include<graphics.h>#include<stdio.h>#include<conio.h>#include<stdlib.h>#include<time.h>#include<string.h>#define _CRT_SECURE_NO_WARNINGS 1//界⾯的相关的参数#define WALL_SQUARE_WIDTH 10 //围墙⽅块的宽度#define xWALL_SQUARE_NUM 30 //x轴⽅向的⽅块的数⽬#define yWALL_SQUARE_WIDTH 46 //y轴⽅向的⽅块的数⽬#define GAME_WALL_WIDTH (WALL_SQUARE_WIDTH*xWALL_SQUARE_NUM) //游戏区域的宽度 300#define GAME_WALL_HTGH (WALL_SQUARE_WIDTH*yWALL_SQUARE_WIDTH) //游戏区域的⾼度 460#define WINDOW_WIDTH 480 // 游戏总窗⼝宽度 480#define WINDOW_HIGH 460 // 游戏总窗⼝⾼度 460//定义俄罗斯⽅块的相关参数#define ROCK_SQUARE_WIDTH (2*WALL_SQUARE_WIDTH) //俄罗斯⽅块的⼤⼩是围墙的两倍 20#define xROCK_SQUARE_NUM ((GAME_WALL_WIDTH -20)/ROCK_SQUARE_WIDTH) // 游戏区x轴放的⽅块数⽬:14 #define yROCK_SQUARE_NUM ((GAME_WALL_HTGH -20)/ROCK_SQUARE_WIDTH) // 游戏区y轴放的⽅块数⽬:22 //定义移动⽅块的相关操作#define DIRECT_UP 3#define DIRECT_DOWN 2#define DIRECT_LEFT -1#define DIRECT_RIGHT 1/*数据结构-线性表(结构体数组)*/typedef struct ROCK{//⽤来表⽰⽅块的形状(每⼀个字节是8位,⽤每4位表⽰⽅块中的⼀⾏)unsigned short rockShapeBits;int nextRockIndex; //下⼀个⽅块,在数组中的下标} RockType;//⽅块在图形窗⼝中的位置(即定位4*4⼤块的左上⾓坐标)typedef struct LOCATE{int left;int top;} RockLocation_t;//全局变量-游戏板的状态描述(即表⽰当前界⾯哪些位置有⽅块)//0表⽰没有,1表⽰有(多加了两⾏和两列,形成⼀个围墙,便于判断⽅块是否能够移动)int game_board[yROCK_SQUARE_NUM + 2][xROCK_SQUARE_NUM + 2] = { 0 };int game_socres = 0; //全局分数// 把俄罗斯⽅块的19种类放到数组中int rockTypeNum = 19;RockType RockArray[19] = { (0, 0) };//预览区的⽅块的位置RockLocation_t preRockLocation = {GAME_WALL_WIDTH+70,70};//每次⽣成初始化⽅块的位置RockLocation_t initRockLocation = { (WALL_SQUARE_WIDTH + 100), WALL_SQUARE_WIDTH };//分数显⽰的位置//各个⽂件中的函数void DisplayRock(int rockIdx, RockLocation_t* LocatePtr, bool displayed);//初始化Init源⽂件void InitGame();//game.hvoid PlayGame();bool IsGameOver();#endifDraw.h#include"Head.h"//画出游戏界⾯void DrawGameWindow(){//先画出围墙setcolor(BLUE);setlinestyle(PS_SOLID,NULL,0);setfillcolor(BLUE);//画出上下围墙for (int x = WALL_SQUARE_WIDTH; x <= GAME_WALL_WIDTH; x += WALL_SQUARE_WIDTH){fillrectangle(x - WALL_SQUARE_WIDTH, 0, x, WALL_SQUARE_WIDTH); //上fillrectangle(x - WALL_SQUARE_WIDTH, GAME_WALL_HTGH - WALL_SQUARE_WIDTH, x, GAME_WALL_HTGH);//下 }//画出左右围墙for (int y = WALL_SQUARE_WIDTH; y <= GAME_WALL_HTGH; y += WALL_SQUARE_WIDTH){fillrectangle(0, y, WALL_SQUARE_WIDTH, y + WALL_SQUARE_WIDTH);//左fillrectangle(GAME_WALL_WIDTH - WALL_SQUARE_WIDTH, y, GAME_WALL_WIDTH, y + WALL_SQUARE_WIDTH);//右 }//画出右边统计分数及相关东西//画出分割线setcolor(WHITE);setlinestyle(PS_DASH,2);line(GAME_WALL_WIDTH + 20, 0, GAME_WALL_WIDTH + 20, GAME_WALL_HTGH);//设置字体LOGFONT font;gettextstyle(&font);settextstyle(18, 0, _T("宋体"));font.lfQuality = ANTIALIASED_QUALITY;//设置输出效果为抗锯齿//1显⽰预览形状outtextxy(GAME_WALL_WIDTH + 80, 30, _T("预览"));outtextxy(GAME_WALL_WIDTH + 80, 170, _T("分数"));outtextxy(GAME_WALL_WIDTH + 65, 250, _T("操作说明"));outtextxy(GAME_WALL_WIDTH + 40, 290, _T("w a s d控制⽅向"));outtextxy(GAME_WALL_WIDTH + 40, 335, _T("空格暂停"));//显⽰分数setcolor(RED);outtextxy(GAME_WALL_WIDTH + 90, 200, '0');}//在游戏区显⽰编号为rockIdx的⽅块void DisplayRock(int rockIdx, RockLocation_t* LocatePtr, bool displayed){int color;//⽅块的填充颜⾊int lineColor = WHITE;//线的颜⾊int boardFalg = 0;int xRock = 0;int yRock = 0;unsigned short rockCode = RockArray[rockIdx].rockShapeBits;//如果displayed为true的话,将⽅块块颜⾊设置为white,game_board对应的位置设置为1;//如果displayed为false的话,将⽅块块颜⾊设置为black,game_board对应的位置设置为0;displayed ? (color = RED, boardFalg = 1) : (color = BLACK,lineColor = BLACK, boardFalg = 0);setcolor(lineColor);setlinestyle(PS_SOLID);//设置为实线,xRock = LocatePtr->left;yRock = LocatePtr->top;int count = 0;//每4个换⾏,记录坐标偏移量unsigned short mask = 1;for (int i = 1; i <= 16; ++i){mask = 1 << (16 - i);if ((rockCode & mask) != 0) //如果不为0的话,就画出⼩⽅块{fillrectangle(xRock , yRock, xRock + ROCK_SQUARE_WIDTH, yRock + ROCK_SQUARE_WIDTH); }if (i % 4 == 0) //换⾏{yRock = yRock + ROCK_SQUARE_WIDTH;xRock = xRock = LocatePtr->left;}else{xRock += ROCK_SQUARE_WIDTH;}}}Init.h#include"Head.h"static void ShapeStrToBit(unsigned char *rockShapeStr, unsigned short& rockShapeBit);static void ReadRcok();void InitGame(){//把全局游戏游戏版初始化,边界初始化为1for (int i = 0; i < xROCK_SQUARE_NUM + 2; i++){game_board[0][i] = 1; //上边界game_board[yROCK_SQUARE_NUM + 1][i] = 1; //下边界}for (int i = 0; i < yROCK_SQUARE_NUM + 2; i++){game_board[i][0] = 1 ; //左边界game_board[i][xROCK_SQUARE_NUM + 1] = 1; //右边界}//读取俄罗斯⽅块ReadRcok();}//从⽂件中读取⽅块的形状存储到rockArray中void ReadRcok(){FILE* fp = fopen("RockShape.ini","r");if (NULL == fp){printf("打开⽂件失败\n");return;}unsigned char readBuf[1024]; //fp读取到字符串readbuf中unsigned short rockShapeBit = 0;//存放⽅块形状,占16⽐特位unsigned char rockShapeStr[16];//存放⽅块字符串int ShapeStrIdx = 0;int rockNum = 0;//统计⽅块的个数以及存放⽅块数组RockArray的下标int rocknext = 0;//⽅块数组中下⼀个形状int rockShapeStart = 0;//同⼀类型的形状while (true){size_t readSize = fread(readBuf, 1, 1024, fp);if (readSize == 0)break;//处理readbuffor (size_t idx = 0; idx < readSize; ++idx){//将字符存放到rockShapeStr中if (readBuf[idx] == '@' || readBuf[idx] == '#'){rockShapeStr[ShapeStrIdx] = (unsigned char)readBuf[idx];++ShapeStrIdx;}++idx; //可能idx == readSize了if (readBuf[idx] == '*')//修改上⼀次⽅块的next值{idx += 5;RockArray[--rockNum].nextRockIndex = rockShapeStart;rockNum++;rockShapeStart = rockNum;rocknext = rockShapeStart ;}}//可能没有填满if (ShapeStrIdx < 16){break;}else //填满shapestr{ShapeStrIdx = 0;//置0//将rockShapeStr 转为rockShapeBitShapeStrToBit(rockShapeStr, rockShapeBit);rocknext++;RockArray[rockNum].rockShapeBits = rockShapeBit;RockArray[rockNum].nextRockIndex = rocknext;rockNum++;}}}fclose(fp);}//将从⽂件中读取的字符串(长度默认为16)转换成 unsigned shortvoid ShapeStrToBit(unsigned char *rockShapeStr, unsigned short& rockShapeBit){rockShapeBit = 0;for (size_t idx = 0; idx < 16; ++idx){if (rockShapeStr[idx] == '@') //1{rockShapeBit |= (1 << (16 - idx - 1));}// #为0 不需要处理}}game.h#include"Head.h"#define _CRT_SECURE_NO_WARNINGS 1bool MoveAble(int rockIndex, RockLocation_t* currentLocatePtr, int f_direction);void SetGameBoardFlag(int rockIdx, RockLocation_t* curRockLocation);void UserHitKeyBoard(char userHit, int* RockIndex, RockLocation_t* curRockLocation); void FullLine();void UpdateSocres(int scores);void DelCurLine(int rowIdx);bool IsGameOver();void PlayGame(){char userHit = 0;//⽤户敲击键盘int curRockIndex = 0;//当前⽅块的rockArray下标int nextRockIndex = 0;//下次RockLocation_t curRockLocation;curRockLocation.left = initRockLocation.left;curRockLocation.top = initRockLocation.top;DWORD oldtime = 0;srand((unsigned int)time(NULL));curRockIndex = rand() % rockTypeNum;nextRockIndex = rand() % rockTypeNum;//画出预览区初始化⽅块//在初始位置和预览区显⽰⽅块形状bool moveAbled = false;while (true){//判断当前⽅块是否落地(判断能否再下移):如果落地,判断是否满⾏,再判断是否结束游戏,改变game_board ,画出下次初始化的⽅块,以及⽣成新的预览⽅块 //moveAbled = MoveAble(curRockIndex, &curRockLocation, DIRECT_DOWN);if (!moveAbled) //判断是否落地,不能下移表⽰落地{//修改game_board的值SetGameBoardFlag(curRockIndex, &curRockLocation);FullLine();if (IsGameOver()){MessageBox(NULL, _T("游戏结束"), _T("GAME OVER"), MB_OK);exit(0);}//为下次⽣成模块开始准备DisplayRock(nextRockIndex, &preRockLocation, false);//擦除旧的⽅块curRockIndex = nextRockIndex;nextRockIndex = rand() % rockTypeNum; //⽣成新的预览⽅块DisplayRock(curRockIndex, &initRockLocation, 1);DisplayRock(nextRockIndex, &preRockLocation, 1);FlushBatchDraw();//修改curRockLocation的值curRockLocation.left = initRockLocation.left;curRockLocation.top = initRockLocation.top;}if (kbhit()) //如果敲击键盘了就处理按键{userHit = getch();UserHitKeyBoard(userHit, &curRockIndex, &curRockLocation);}//没有就⾃动下移⼀个单位 :不能⽤else,因为可能按键不是上下左右DWORD newtime = GetTickCount();if (newtime - oldtime >= (unsigned int)(300) && moveAbled == TRUE){oldtime = newtime;DisplayRock(curRockIndex, &curRockLocation, false);curRockLocation.top += ROCK_SQUARE_WIDTH; //下落⼀格}//AutomaticDownMove(curRockIndex, &curRockLocation);//画出新⽅块DisplayRock(curRockIndex, &curRockLocation, 1);FlushBatchDraw();Sleep(20);}}//响应键盘命令时间void UserHitKeyBoard(char userHit, int* RockIndex, RockLocation_t* curRockLocation){switch (userHit){case 'W':case 'w'://↑if (MoveAble(RockArray[*RockIndex].nextRockIndex, curRockLocation, DIRECT_UP)){DisplayRock(*RockIndex, curRockLocation, false);*RockIndex = RockArray[*RockIndex].nextRockIndex;}break;case 'S':case 's'://↓if (MoveAble(*RockIndex, curRockLocation, DIRECT_DOWN)){DisplayRock(*RockIndex, curRockLocation, false);curRockLocation->top += 2 * (ROCK_SQUARE_WIDTH);if (!MoveAble(*RockIndex, curRockLocation, DIRECT_DOWN)){curRockLocation->top -= ROCK_SQUARE_WIDTH;}}break;case 'A':if (MoveAble(*RockIndex, curRockLocation, DIRECT_LEFT)){DisplayRock(*RockIndex, curRockLocation, false);curRockLocation->left -= ROCK_SQUARE_WIDTH;}break;case 'D':case 'd': //→if (MoveAble(*RockIndex, curRockLocation, DIRECT_RIGHT)){DisplayRock(*RockIndex, curRockLocation, FALSE);curRockLocation->left += ROCK_SQUARE_WIDTH;}break;case ' ': //暂停while (1){userHit = getch();if (userHit == ' ')break;}break;default:break;}}//判断是否满⾏,满⾏消除,然后计算得分void FullLine(){bool linefull = true;int idx = yROCK_SQUARE_NUM;//从最后⼀⾏往上查找 22int count = 0;while (count != xROCK_SQUARE_NUM ) //遇到空⾏ 14{linefull = true;count = 0;for (int i = 1; i <= xROCK_SQUARE_NUM; ++i){if (game_board[idx][i] == 0){linefull = false;count++;}}if (linefull) //满⾏,消除当前⾏,更新分数{DelCurLine(idx);game_socres += 3;UpdateSocres(game_socres);idx++;//因为下⾯要减1}idx--;}}void UpdateSocres(int scores){setcolor(RED);TCHAR s[10];_stprintf(s, _T("%d"), scores);outtextxy(GAME_WALL_WIDTH + 90, 200, s);}//消除当前⾏void DelCurLine(int rowIdx){//擦除当前⾏setcolor(BLACK);setfillcolor(BLACK);for (int i = 1; i < xROCK_SQUARE_NUM; ++i){fillrectangle(WALL_SQUARE_WIDTH + (i - 1)*ROCK_SQUARE_WIDTH, (rowIdx - 1)*ROCK_SQUARE_WIDTH + WALL_SQUARE_WIDTH, WALL_SQUARE_WIDTH + i*ROCK_SQUARE_WIDTH, rowIdx*ROCK_SQUARE_WIDTH + WALL_SQUARE_WIDTH);}//把上⾯的向下移int cnt = 0;while (cnt != xROCK_SQUARE_NUM) //直到遇到是空⾏的为⽌cnt = 0;for (int i = 1; i <= xROCK_SQUARE_NUM; i++){game_board[rowIdx][i] = game_board[rowIdx - 1][i];//擦除上⾯的⼀⾏setcolor(BLACK);setfillcolor(BLACK);fillrectangle(WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*i - ROCK_SQUARE_WIDTH , WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*(rowIdx - 1) - ROCK_SQUARE_WIDTH , WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*i,WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*(rowIdx - 1));//显⽰下⾯的⼀⾏if (game_board[rowIdx][i] == 1){setcolor(WHITE);setfillcolor(RED);fillrectangle(WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*i - ROCK_SQUARE_WIDTH , WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*rowIdx - ROCK_SQUARE_WIDTH ,WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*i,WALL_SQUARE_WIDTH + ROCK_SQUARE_WIDTH*rowIdx);}if (game_board[rowIdx][i] == 0)cnt++; //统计⼀⾏是不是都是空格}//forrowIdx--;}}//是否可以移动⽅块bool MoveAble(int rockIndex, RockLocation_t* currentLocatePtr, int f_direction){int mask;int rockX;int rockY;rockX = currentLocatePtr->left;rockY = currentLocatePtr->top;mask = (unsigned short)1 << 15;for (int i = 1; i <= 16; i++){//与掩码相与为1的即为⽅块上的点if ((RockArray[rockIndex].rockShapeBits & mask) != 0){//判断能否移动(即扫描即将移动的位置是否与设置的围墙有重叠)//若是向上(即翻滚变形)if (f_direction == DIRECT_UP){//因为此情况下传⼊的是下⼀个⽅块的形状,故我们直接判断此⽅块的位置是否已经被占//判断下⼀个⽅块if (game_board[(rockY - WALL_SQUARE_WIDTH) / ROCK_SQUARE_WIDTH + 1][(rockX - WALL_SQUARE_WIDTH) / ROCK_SQUARE_WIDTH + 1] == 1)return false;}//如果是向下⽅向移动else if (f_direction == DIRECT_DOWN){if (game_board[(rockY - WALL_SQUARE_WIDTH) / ROCK_SQUARE_WIDTH + 2][(rockX - WALL_SQUARE_WIDTH) / ROCK_SQUARE_WIDTH + 1] == 1)return false;}else //如果是左右⽅向移动{ //f_direction的DIRECT_LEFT为-1,DIRECT_RIGHT为1,故直接加f_direction即可判断。

C语言的俄罗斯方块

C语言的俄罗斯方块
/*清除掉满行的点阵,具体细节在函数内讲*/
int move(int dir);
/*左右移动下落盒子,dir指出向左还是向右,这个与drop
是一样的*/
int test(int mx, int my, int box[5][5]);
/*这个比较重点,判断box在mx,my为坐标上,与地图上的
非空点阵是否有重叠.很通用的一个函数*/
int rotate();
/*旋转下落的盒子,当然如果转了之后与地图有冲突,会
取消转动,返回0,但返回的值好像没什么用~*/
#define MAX_C 7 /*最大种类,这个无须解释*/
#define KEY_UP 'w' /*定义上下左右按按键*/
#define KEY_DOWN 's'
#define KEY_LEFT 'a'
#define KEY_RIGHT 'd'
}
将会定时(1个单位)在屏幕上打印Active!
一般来说testTimer必须放在循环中反复执行,激活时返回1
*/
void render(void); /*唯一的绘图函数*/
/*注意,此函数重画整个地图,根据地图中的点阵,以及根据
void rotateBox(int box1[5][5], int box2[5][5]);
/*核心函数成员,把box1逆时针旋转90度,并保存到box2中*/
void rebuidNext();
/*核心函数成员,生成下一个方块*/
int drop();
*main函数在程序的最后,你可以在这里看到整个游戏的组织架构

俄罗斯方块-C语言-完整代码

俄罗斯方块-C语言-完整代码
//游戏池 void printPoolBorder() {
int y; SetConsoleTextAttribute(Output,0xf0);
for(y=4;y<26;y++) {
//两条纵线 gotoxyWithFullwidth(10,y-3);//鼠标定位
gotoxyWithFullwidth(10,y-3);//鼠标定位 printf("%2s"," "); gotoxyWithFullwidth(23,y-3);//鼠标定位 printf("%2s"," "); }
bool dead;//挂 }Manager;//结构体别名
//构造存储游戏控制相关数据的结构体 typedef struct TetrisControl {
bool pause;//暂停 bool clockwise;//旋转方向;顺时针方向为ture int direction;//移动方向:0向左移动 1向右移动 //游戏池内每格的颜色 //此版本是彩色的,仅用游戏池数据无法存储颜色 int color[28][16]; }Control;//Control是结构体别名
//初始状态的游戏池 //每个元素表示游戏池的一行 //两端各置两个1,底部两行全部为1,便于进行碰撞 //这样一来游戏池的宽度为12列 共16列 //当某个元素为OXFFFF时,说明该行已经填满 //顶部4行用于给方块,不显示 //底部2行不显示,显示出来的游戏池高度为22行 static const unsigned int gs_uInitialTetrisPool[28]= {
效果图如下
俄罗斯方块-C语言-完整代码
#ifndef _DAY7_H #define _DAY7_H #include<windows.h> #include<time.h> #include<stdbool.h> #include<conio.h>//控制台输入输出函数getch通过键盘进行的操作 //游戏区域位置设计 #define COL_BEGIN 2 #define COL_END 14 #define ROW_BEGIN 4 #define ROW_END 26

俄罗斯方块c语言的原理

俄罗斯方块c语言的原理

俄罗斯方块c语言的原理
俄罗斯方块是一款经典的电子游戏,其开发语言包括C语言。

C 语言是一种通用的、高效的编程语言,可以被应用到多种不同的领域中,包括游戏开发。

在C语言中,俄罗斯方块的实现原理包含了以下几个步骤:
1. 初始化游戏界面。

这个过程包含了屏幕初始化、游戏元素初始化等等。

2. 确定方块的位置和形状。

游戏通过随机生成方块来增加游戏的难度和趣味性。

3. 对方块进行移动。

用户通过键盘输入来控制方块的位置改变,从而使其移动到所需的位置。

4. 碰撞检测。

游戏需要检测方块是否与其他游戏元素相碰,包括墙壁、已经下落的方块等等,从而判断该方块是否能够继续移动,或者需要停止移动。

5. 方块下落。

一旦该方块不能继续移动,则需要开始下落,并且生成新的方块,重复上述的步骤。

6. 计分。

当一行方块被填满时,游戏需要将其消除,并且增加用户的分数。

除此之外,俄罗斯方块中还需要应用到一些基本的编程概念,比如数据结构、条件语句、循环语句、函数调用等等。

通过这些编程概念的组合,C语言程序员可以实现一个完整的俄罗斯方块游戏,并且使其在计算机上运行。

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

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

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

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

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

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

俄罗斯方块c语言程序带注释

俄罗斯方块c语言程序带注释

1,1,0,0,0,1,0,0,0,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,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,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,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,0,1,0,0,1,1,0,0,1,0,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,1,0,0,0,1,1,0,0,0,1,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,}; /*方块模板*/int shape,dir,next_shape,next_dir;struct position{int x;int y;} now_position; /*纪录现在方块的位置*/int speed_level=1;int fall_to_land,be_lined; /*判断方块是否着地的*/ /*----------------------------------------*/void clscreen();void setxy(int x,int y);void display_back();void display_interface();void display_fk(int x,int y,int shape,int dir);void init();//int getkey();/*取键盘的扫描码*/void getinput();void m_sound(int freq,int time);void eras_fk(int x,int y,int shape,int dir);/*擦除方块*/void fk_down(bool quickly = false);bool is_illegal(int x,int y,int changed_dir);/*判断方块移动后坐标是否非法,非法1,合法0*/int get_random(int n); /*生成一个0----n-1的随机数*/void check_line(); /*检查是否有行可以消去,如果有就消去*/void game_over();/*----------------------------------*/int main(){int i;init();while (true){display_back();now_position.x=10;now_position.y=2;/*复原初始坐标*/be_lined=0; /*一个方块刚出现时没有成行*/shape=next_shape;dir=next_dir;next_shape=get_random(7);next_dir=get_random(4);eras_fk(55,5,shape,dir);/*擦去前一个方块*/display_fk(55,5,next_shape,next_dir);/*显示下一个方块*/display_fk(now_position.x,now_position.y,shape,dir);/*显示目前方块*/fall_to_land=0;while (!fall_to_land){for (i=15000-1500*speed_level;i>0;i--){getinput();}/*接受键盘输入*/fk_down(); /*方块自动下落*/}//m_sound(350,500); /*块落下的声音*/ check_line(); /*检查有没有可消去的行*/if (be_lined)m_sound(250,1000);elsem_sound(350,500);}return0;}/*------------------------------------*/void init(){int i,j;for (i=0;i<20;i++)for (j=0;j<10;j++)background[i][j]=0;/*背景数组赋初值0*/next_shape=(get_random(7)+5)/7;next_dir=(get_random(4)+2)/4;/*预先产生一个方块*/display_interface();/*画界面*/}void display_interface(){clscreen();setxy(40,5);printf("The Next: ");setxy(1,1);}/*-----------------------------------------*/void display_back()/*显示背景*/{int i,j;for (i=0;i<20;i++){for (j=0;j<10;j++){setxy(2*(j+1),i+2); /*数组下标到屏幕坐标的变换*/if (!background[i][j])/*背景数组中值为0*/printf(" ");elseprintf("[]");}}}/*---------------------------------------*/void display_fk(int x,int y,int shape,int dir)/*显示方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf("[]");}}}}/*-----------------------------------*/void getinput(){if(GetAsyncKeyState(VK_LEFT)){if (!is_illegal(now_position.x-2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x-2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置左移一格*/}else if(GetAsyncKeyState(VK_RIGHT)){if (!is_illegal(now_position.x+2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x+2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置右移一格*/}else if(GetAsyncKeyState(VK_UP)){if (!is_illegal(now_position.x,now_position.y,(dir+1)%4)){eras_fk(now_position.x,now_position.y,shape,dir);dir=(dir+1)%4;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}}else if(GetAsyncKeyState(VK_DOWN)){fk_down(true);}else if(GetAsyncKeyState(VK_SPACE)){game_over();}}/*------------------------------------*/void m_sound(int freq,int time){Beep(freq,time);}/*--------------------------------*/void eras_fk(int x,int y,int shape,int dir)/*擦除方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf(" ");}}}}/*----------------------------------------------------*/ void fk_down(bool quickly) /*方块下落*/{int i,j,x,y;if (!is_illegal(now_position.x,now_position.y+1,dir))/*下落没有阻碍*/{eras_fk(now_position.x,now_position.y,shape,dir);now_position.y=now_position.y+1;display_fk(now_position.x,now_position.y,shape,dir);if(quickly){Sleep(10);}else{Sleep(1000);}}else/*不可再下落了*/{/*方块并入背景*/x=now_position.x;y=now_position.y; /*x,y表示方便*/for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]==1) background[(y-2+i)][(x/2-1+j)]=1;}}fall_to_land=1; /*告诉主程序方块着地*/}}/*-----------------------------------------------------*/ bool is_illegal(int x,int y,int changed_dir){int i,j;bool illegal=false;/*先判断有没有出界,如果有x,y在界外并且此x,y处方块数组为1,就返回1*/for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&((x+j*2)>21 || (x+j*2)<2 || (y+i)>21 || (y+i)<2))illegal=true;/*再判断是否有原方块阻碍*/if (!illegal){for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&background[(y-2+i)][(x/2-1+j)]==1)illegal=true;/*有阻碍返回一*/}return illegal;}/*-----------------------------------------------------*/int get_random(int n){int x;Sleep(500);/*randomize();x=random(n);*/srand( (unsigned)time(NULL));x=rand()%n;return(x);}/*--------------------------------------------------------------*/void check_line() /*待修改*/{/*检查背景数组*/int i,j,k;int line,n;for (i=19;i>=0;i--){k=1; /*开始默认成行*/for (j=9;j>=0;j-- ){if (background[i][j]==0) /*不成行的条件*/k=0;}if (k==1) /*如果成行*/{be_lined=1; /*成行标志*/for (line=i;line>0;line--)for (n=9;n>=0;n--)background[line][n]=background[line-1][n];/*逐次下移一行*/i=i+1; /*把下一次待检的行重新设定*/}}}/*--------------------------------------------------------------*/void game_over(){clscreen();setxy(35,1);printf("GAME OVER");exit(0);}void clscreen(){system("cls");}void setxy(int x,int y){HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);COORD place;place.X = x;place.Y = y;SetConsoleCursorPosition(hConsole, place);}/* Colors defined for SetColor(int) */enum {BLACK = 0,DARK_BLUE = 1,DARK_GREEN = 2,TEAL = 3,DARK_RED = 4,DARK_PURPLE = 5,GOLD = 6,GREY = 7,DARK_WHITE = 8,BLUE = 9,GREEN = 10,CYAN = 11,RED = 12,PURPLE = 13,YELLOW = 14,WHITE = 15};void SetColor(const int foreground, const int background) {int Color = foreground + (background * 16);HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);}你把这段拿回去看哈吧,这是一个俄罗斯方块的程序,就是在控制台运行的,就是用你所说的纯数字和字符所运行,你现在只能在dos 下显示那些纯数字的东西,是因为你很多技术性的手法,你还不会,但你学习到一定程度后,你就会有所领悟,也不要太心急,当你练好内功后,修炼招数,应该会很快的!希望对你有帮助。

俄罗斯方块设计文档_C语言编写的彩色俄罗斯方块

俄罗斯方块设计文档_C语言编写的彩色俄罗斯方块

俄罗斯方块设计文档_C语言编写的彩色俄罗斯方块设计文档:彩色俄罗斯方块游戏1.引言彩色俄罗斯方块是一款非常经典的游戏,它的设计思想简单而有趣,具有很高的娱乐性和挑战性。

本文档是对彩色俄罗斯方块游戏的设计进行详细的说明和分析。

2.功能需求2.1游戏开始和结束在游戏开始时,显示游戏画面和初始的下一个方块,玩家通过按键控制方块的移动和旋转,直到方块无法再移动下去时,游戏结束。

2.2方块的生成和下落游戏中有7种不同形状的方块:I、J、L、O、S、T、Z。

在游戏开始时,随机生成一个方块,并显示在游戏区域的顶部。

方块从顶部开始向下移动,直到底部或者碰到其他方块时停止下落。

2.3方块的移动和旋转玩家通过键盘按键控制方块的移动和旋转。

方块可以向左或者向右移动,也可以进行顺时针或者逆时针旋转。

2.4方块的消除当一行的方块被填满时,该行会被消除,并且上面的方块将向下移动一行。

每次消除行,玩家得分增加。

2.5游戏分数和级别玩家的分数根据消除的行数进行计算。

随着分数的增加,游戏的级别也会逐渐提高,方块下落的速度也会加快。

2.6游戏暂停和恢复在游戏进行中,玩家可以选择暂停游戏,等待一段时间后可以恢复游戏。

3.数据结构和算法设计3.1游戏区域的表示游戏区域可以使用一个二维数组来表示,数组中的每个元素可以表示一个方块,方块的颜色可以使用一个整数来表示。

3.2方块的生成和下落方块的生成可以通过随机数生成器来实现,可以随机生成0到6之间的整数来表示不同的方块。

方块的下落可以通过定时器来实现,每经过一段时间,方块向下移动一个单位。

3.3方块的移动和旋转方块的移动可以通过键盘按键事件来实现,玩家按下左方向键或者右方向键时,方块向左或者向右移动一个单位。

方块的旋转可以通过键盘按键事件来实现,玩家按下上方向键时,方块顺时针旋转90度;按下下方向键时,方块逆时针旋转90度。

3.4方块的消除方块的消除可以通过检查游戏区域的每一行来实现,如果其中一行全满,将该行从游戏区域中删除,上面的方块向下移动一行,并且玩家得分增加。

用C语言写俄罗斯方块 源代码

用C语言写俄罗斯方块 源代码

// 程序名称:俄罗斯方块// 编译环境:Visual C++ 6.0,EasyX 2011惊蛰版// 程序编写:krissi <zhaoh1987@>// 最后更新:2010-12-18//#include "graphics.h"#include <conio.h>#include <time.h> /////////////////////////////////////////////// 定义常量、枚举量、结构体、全局变量/////////////////////////////////////////////#define WIDTH 10 // 游戏区宽度#define HEIGHT 22 // 游戏区高度#define SIZE 20 // 每个游戏区单位的实际像素// 定义操作类型enum CTRL{CTRL_ROTATE, // 方块旋转CTRL_LEFT, CTRL_RIGHT, CTRL_DOWN, // 方块左、右、下移动CTRL_SINK, // 方块沉底CTRL_QUIT // 退出游戏};// 定义绘制方块的方法enum DRAW{SHOW, // 显示方块HIDE, // 隐藏方块FIX // 固定方块};// 定义七种俄罗斯方块struct BLOCK{WORD dir[4]; // 方块的四个旋转状态COLORREF color; // 方块的颜色} g_Blocks[7] = { {0x0F00, 0x4444, 0x0F00, 0x4444, RED}, // I{0x0660, 0x0660, 0x0660, 0x0660, BLUE}, // 口{0x4460, 0x02E0, 0x0622, 0x0740, MAGENTA}, // L{0x2260, 0x0E20, 0x0644, 0x0470, YELLOW}, // 反L{0x0C60, 0x2640, 0x0C60, 0x2640, CYAN}, // Z{0x0360, 0x4620, 0x0360, 0x4620, GREEN}, // 反Z{0x4E00, 0x4C40, 0x0E40, 0x4640, BROWN}}; // T// 定义当前方块、下一个方块的信息struct BLOCKINFO{byte id; // 方块IDchar x, y; // 方块在游戏区中的坐标byte dir:2; // 方向} g_CurBlock, g_NextBlock;// 定义游戏区BYTE g_World[WIDTH][HEIGHT] = {0}; /////////////////////////////////////////////// 函数声明/////////////////////////////////////////////void Init(); // 初始化游戏void Quit(); // 退出游戏void NewGame(); // 开始新游戏void GameOver(); // 结束游戏CTRL GetControl(bool _onlyresettimer = false); // 获取控制命令void DispatchControl(CTRL _ctrl); // 分发控制命令void NewBlock(); // 生成新的方块bool CheckBlock(BLOCKINFO _block); // 检测指定方块是否可以放下void DrawBlock(BLOCKINFO _block, DRAW _draw = SHOW); // 画方块void OnRotate(); // 旋转方块void OnLeft(); // 左移方块void OnRight(); // 右移方块void OnDown(); // 下移方块void OnSink(); // 沉底方块/////////////////////////////////////////////// 函数定义/////////////////////////////////////////////// 主函数void main(){Init(); CTRL c;while(true){c = GetControl();DispatchControl(c); // 按退出时,显示对话框咨询用户是否退出if (c == CTRL_QUIT){HWND wnd = GetHWnd();if (MessageBox(wnd, "您要退出游戏吗?", "提醒", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)Quit();}}}// 初始化游戏void Init(){initgraph(640, 480);srand((unsigned)time(NULL)); // 显示操作说明setfont(14, 0, "宋体");outtextxy(20, 330, "操作说明");outtextxy(20, 350, "上:旋转");outtextxy(20, 370, "左:左移");outtextxy(20, 390, "右:右移");outtextxy(20, 410, "下:下移");outtextxy(20, 430, "空格:沉底");outtextxy(20, 450, "ESC:退出"); // 设置坐标原点setorigin(220, 20); // 绘制游戏区边界rectangle(-1, -1, WIDTH * SIZE, HEIGHT * SIZE);rectangle((WIDTH + 1) * SIZE - 1, -1, (WIDTH + 5) * SIZE, 4 * SIZE); // 开始新游戏NewGame();}// 退出游戏void Quit(){closegraph();exit(0);}// 开始新游戏void NewGame(){// 清空游戏区setfillstyle(BLACK);bar(0, 0, WIDTH * SIZE - 1, HEIGHT * SIZE - 1);ZeroMemory(g_World, WIDTH * HEIGHT); // 生成下一个方块g_NextBlock.id = rand() % 7;g_NextBlock.dir = rand() % 4;g_NextBlock.x = WIDTH + 1;g_NextBlock.y = HEIGHT - 1; // 获取新方块NewBlock();}// 结束游戏void GameOver(){HWND wnd = GetHWnd();if (MessageBox(wnd, "游戏结束。

C语言课程设计俄罗斯方块源代码

C语言课程设计俄罗斯方块源代码

函数和模块化编程
函数定义:C语言中的函数 是完成特定任务的独立代码

添加标题
函数参数:函数可以接受参 数,参数可以是变量、常量
或表达式
添加标题
模块化编程:将大型程序分 解为多个模块,每个模块完
成特定的任务
模块测试:对每个模块进行 单独测试,确保其正确性和
稳定性
添加标题Βιβλιοθήκη 添加标题添加标题添加标题
函数调用:通过函数名和参 数列表来调用函数
游戏界面:包括游戏区域、得分、等级、 下一块等元素
等级:使用全局变量记录,每消除一定 行增加一级
游戏区域:使用二维数组表示,每个元 素对应一个方块
下一块:使用数组表示,每次随机生成 一个新的方块
得分:使用全局变量记录,每次消除一 行增加一定分数
游戏结束:当游戏区域被填满时,游戏 结束,显示游戏结束界面
调试过程和方法
确定问题:找出俄罗斯方块游戏中存在的问题 定位问题:确定问题的具体位置和原因 修复问题:根据问题原因进行修复 测试修复:测试修复后的游戏是否正常运行 重复以上步骤,直到游戏运行正常 记录调试过程和方法,以便于后续维护和改进
测试结果的分析和总结
测试方法:单元测试、集成 测试、系统测试
游戏规则和玩法
游戏目标:消除方块,避免堆积到顶部 游戏操作:通过移动、旋转和下落方块来消除 游戏结束:当方块堆积到顶部时,游戏结束 游戏得分:根据消除的方块数量和难度来计算得分
游戏历史和发展
俄罗斯方块诞生于1984年,由苏联程序员阿列克谢·帕基特诺夫发明
1989年,俄罗斯方块被移植到任天堂Game Boy游戏机上,成为全球最畅 销的游戏之一
测试工具:JUnit、 TestNG、Se lenium 等

俄罗斯方块C语言实现

俄罗斯方块C语言实现

安阳师范学院本科学生毕业论文俄罗斯方块的C语言实现姓名马成强系(院)计算机与信息工程学院专业 __________ 网络__________年级 08 级_________________________学号080902072指导教师 ___________ 王希杰_________日期2012年5月目录1. 摘要 (2)2. 前言 (3)3.需求分析 (3)4. 游戏总体设计 (4)5. 功能设计分析 (4)5.1 游戏方块预览 (4)5.2 游戏方块控制 (4)5.3 游戏显示更新 (4)5.4 游戏速度分数更新 (4)6. 流程图 (5)7.具体设计 (6)7.1 定义变量 (6)7.2 定义声明函数 (6)7.3过程判断 (6)8.系统测试 (7)8.1 游戏界面显示测试 (7)8.2 按键功能测试 (7)8.3方块的消行和行满游戏结束功能的测试 (7)9. 参考文献 (8)10. 总结致谢 (8)11 源代码 (9)8.4 测试结果及界面显示 (7)1. 摘要:俄罗斯方块是一款风靡全球的掌上游戏机和PC机游戏,它造成的轰动与创造的经济价值可以说是游戏史上的一件大事。

它由俄罗斯人阿列克谢・帕基特诺夫发明,故得此名。

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

它看似简单却变化无穷,俄罗斯方块上手极其简单,但是要熟练地掌握其中的操作与摆放技巧,难度却不低。

作为家喻户晓老少皆宜的大众游戏,其普及程度可以说是史上任何一款游戏都无法相比的。

相信大多数人都还记得为它痴迷得茶不思饭不想的那个俄罗斯方块时代。

由于俄罗斯方块具有的数学性、动态性与知名度,也经常拿来作为游戏程序设计的练习题材。

关键词:俄罗斯方块开发游戏编程程序开发AbstractsT etris is a fashionable global handheld game and PC games,it caused stir and create the economic value of gaming history is a great event.It is invented by the Russian AlexeyPazhitnov.The basic rule of tetris is moving,rotation and put the Game output squares,It arranged in a complete row or a complete multi row,Chac and score.It seemssimple but Full of change.As household the mass games all ages,Its popularity is any games that cannot be compared.Tetris often used for game programming practice subject.Key words:Tetris development ,Game programming ,program development2. 前言:俄罗斯方块(Tetris )原本是前苏联科学家阿列克谢•帕吉特洛夫在1984年6月利用空闲时间所编写的游戏程序,据说游戏的作者最喜欢网球(Tennis)运动,于是,它把来源于希腊语的tetra (意为“四”)与其结合,造了“tetris ” 一词,之后开始提供授权给各个游戏公司,造成各平台上俄罗斯游戏软件大量发行的现象。

使用C语言写俄罗斯方块

使用C语言写俄罗斯方块

我设想的俄罗斯方块如下图:我们先弹出一个窗口。

首先,新建一个windows应用工程,如下图:然后删除工程里预写好的代码,添加如下代码:然后再点击“编译并运行”按钮,弹出窗口:这样,我们的第一步,就算完成了,呵。

以后的我们的所有代码都是在上边代码的基础上添加而成的。

如图:上图是一种方块变形的四种情况,为表示以上所有的四的情况,我们需要建立一个三维数组:上边建立的三维数组应该不难理解吧,m_olshapePiece[0][x][y]就表示第一种形状,m_olshapePiece[1][x][y]表示第二种形状,m_olshapePiece[2[x][y]表示第三种形状,m_olshapePiece[3][x][y]表示第四种形状。

我们按照同样的方法,把其它几种形状的矩阵弄好,并且把它们设为全局变量,如下:接下来,让我们来看仔细看看我们游戏的布局:如上图所示,我们的游戏由五大块组成:一、按钮:这个就是完成一些特定功能的,比如开始、停止、暂停等等,第一个按钮在窗口上的坐标是(12,16)。

二、BigMap:它是我们游戏的主要区域,它由二维数组BigMap[12][21]来储存该格子是已有方块,BigMap由DrawBigMap()函数完成在窗口上的绘制。

它在窗口上的坐标是(12,66)。

三、CurPiece:它是当前正在掉落的方块,它由三维数组CurPiece[4][5][5]来储存,CupPiece是一个5*5的二维平面,但因为它有4种变形,所以我们需要准备4个二维平面。

CurPiece由DrawCurPiece()函数完成在窗口上的绘制。

它在窗口上的坐标由变量xPos、yPos储存。

四、NextPiece:它表示下一个要掉落的方块,它由三维数组NextPiece[4][5][5]来储存,由DrawNextPiece()函数完成在窗口上的绘制。

它在窗口上的坐标是(277,66)。

五、Score:它表示当前得分和游戏等级,由变量score和level储存(为了方便,我们还需要同时字符串scoreString[20]和levelString[20]储存),由DrawScore()函数完成在窗口上的绘制。

教你用c语言写俄罗斯方块

教你用c语言写俄罗斯方块

来如鹏挺长时间了,受益很多希望更多的朋学加入进来做俄罗斯方块是因为无意中在杨老师的帖子看到说最少也要能做出俄罗斯方块这样的东西出来,我想这个意思能做出俄罗斯方块就说明水平到了一个层次了吧。

刚才注意到音乐播放器居然下载超过400次!我反醒我上传的代码很少解释而且做的都是没有趣味的东西。

俄罗斯方块如鹏已经有好几个同学做出来了,但是我想还有很多同学做不出来,我抛砖引玉,其实俄罗斯方块并不复杂今天先告诉大家第一步,在屏幕上把方块显示出来cfree 新建一个工程选窗口程序显示helloworld的win32的 api 图形函数都要用到 HDC 这是一个保存窗口图形的数据的句柄比如我要画一个正方形可以用Rectangle (hdc,标X,左上角坐标y,右下角坐标x,右下角坐标y);为了方便我们直接在switch (message){case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// 这个下面添加代码Rectangle (hdc,50,50,100,100);然后编译运行这是效果就是一个正方形没别的东西?别着急哈,慢慢来。

俄罗斯方块每块都是四部分的所以要画4个这里面需要一小点数学知识把这些复制到刚才的位置看一下效果{int x,y;const int size=50;//方块大小x=y=50;//从窗口的左上角位置开始画//第一个方块Rectangle (hdc,x,y,x+size,y+size);x+=size; //向右一块位置画第二个方块Rectangle (hdc,x,y,x+size,y+size);x+=size; //向右一块位置画第三个方块Rectangle (hdc,x,y,x+size,y+size);//最后一个方块//相对于第三个方块左下角的位置x-=50;y-=50;Rectangle (hdc,x,y,x+size,y+size);}这个画好像很麻烦我们可以自定义一个函数huafangkuai专门负责画这个正方形以后所有的其他函数也必须经过他才能画正方形这个类似于win32 api的封装思想void huafangkuai(int x,int y,int color);x y是方块的坐标color 就是color函数原理是x y 是相对于游戏里的坐标而不是屏幕坐标屏幕坐标要经过函数自己转换这样我们就可以把心关注在游戏的事情而不必分心了void huafangkuai(HDC hdc,int x,int y,int color){const int BEGINX= 50;//游戏图形的开始位置const int BEGINY= 50 ;const int FSIZE= 35 ; //方块大小int screenx=BEGINX +x*FSIZE; //方块左上角的坐标是x乘方块大小再加上起始位置int screeny=BEGINY +y*FSIZE;Rectangle (hdc,screenx,screeny,screenx+FSIZE,screeny+FSIZE);}这样我们再画就四个就容易多了 color 先不管int x,y;x=5;y=5;huafangkuai(hdc,x,y,0);huafangkuai(hdc,x+1,y,0);huafangkuai(hdc,x+2,y,0);huafangkuai(hdc,x+1,y+1,0);这样就画出了一个方块形状但是怎么能画出其它的呢?请听下回分解.弄这点东西我费了一个多小时时间 ...我终于理解为什么杨老师问最近没人反馈备课再加录视频一定花了很多心血可是没有几个同学问问题或做作业的心情...leeco 说的是我以前很少写注释这回一写反而乱写一通下次改进下一步有一些麻烦了为了省代码还是再定义一个函数void DrawTetris(HDC hdc, int dir,int shape,int color,int x,int y)dir 是方块的4个方向 shape 是形状比如有L 形 |形和田形 x y 游戏中的坐标我们定义一个全局数组把俄罗斯方块中7种不同的正式形状都保存在里面调用这个函数之后能把要求的方块显示出来void DrawTetris(HDC hdc, int dir,int shape,int color,int x,int y){int nx,ny;for(int i=0;i<4;i++){nx=SQRARRAY[shape][dir].x+x;ny=SQRARRAY[shape][dir].y+y;huafangkuai(hdc,nx,ny,color);}}要求所有的方块的形状都弄好我费了不少时间这个就是全局数组放到代码的最上面每4行是1个形状最后一个全是一样的就是田形const POINT SQRARRAY[7][FOUR][FOUR]={{0,-1,0,0,1,0,2,0,1,0,0,0,0,1,0,2,0,1,0,0,-1,0,-2,0,-1,0,0,0,0,-1,0,-2},{-1,0,0,0,0,1,0,2,-1,0,0,0,-2,0,0,-1,0,-1,0,0,0,-2,1,0,0,1,0,0,1,0,2,0},{ -1,0,0,0,0,-1,1,0,0,-1,0,0,1,0,0,1,-1,0,0,0,0,1,1,0,-1,0,0,0,0,-1,0,1},{ 0,-1,0,0,1,0,1,1,1,0,0,0,0,1,-1,1,0,-1,0,0,1,0,1,1,1,0,0,0,0,1,-1,1,},{ 0,-1,0,0,-1,0,-1,1,-1,0,0,0,0,1,1,1,0,-1,0,0,-1,0,-1,1,-1,0,0,0,0,1,1,1},{-1,0,0,0,1,0,2,0,0,-1,0,0,0,1,0,2,-1,0,0,0,1,0,2,0,0,-1,0,0,0,1,0,2},{-1,0,0,0,-1,1,0,1,-1,0,0,0,-1,1,0,1,-1,0,0,0,-1,1,0,1,-1,0,0,0,-1,1,0,1}} ;先调用试试效果switch (message){case WM_PAINT:hdc = BeginPaint(hWnd, &ps);//在这的加入这些static int shape=0;static int dir=0;++dir%=4;++shape%=7;DrawTetris(hdc,dir,shape,0,3,3);运行之后双击程序的标题栏要求窗口刷新每次图形都会变化下一步是想让图形怎么动起来这个要响应键盘消息在wm_paint 下面找到break;在break;下面的地方加入由于不在wm_paint 里面我们只能自己用getdc得到HDCcase WM_KEYDOWN:switch(wParam){case VK_SPACE:HDC hdc= GetDC(hWnd);static int shape=0;++shape%=7;DrawTetris(hdc,0,shape,0,6,2);ReleaseDC(hWnd,hdc);break;}break;这回VK_SPACE 就是空格还有其它键比如VK_DOWNVK_LEFTVK_RIGHT再运行之后按空格键图形都在一直变化但是变成这样的了因为每显示一次都不清除前面的话就这样这个怎么解决呢?未完待续...谢谢支持我以为没有同学感兴趣呢为了不显示混乱所以一定要先擦除前的用的方法是用背景色的画笔再画一遍定义一个结构体保存现在方块和以前方块的位置struct PosInfo{int x,y,dir,shape;};PosInfo CurrentPos,PrePos;//全局变量HPEN PenArray[10];PosInfo CurrentPos,PrePos;再定义一组画笔在程序开始时用这个函数初初化void Init(HWND hwnd){PenArray [0]=CreatePen(PS_SOLID,0,RGB(255,255,255));//现在是白色背景PenArray [1]=CreatePen(PS_SOLID,0,RGB(120,120,120));CurrentPos.dir=0;CurrentPos.shape=0;CurrentPos.x=2;CurrentPos.y=2;PrePos=CurrentPos;}在键盘击下后用这个函数改变方块位置void KeyDown(int keycode,HWND hwnd){HDC hdc= GetDC(hwnd);switch(keycode){case VK_LEFT:break;case VK_RIGHT:CurrentPos.x++;DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y); PrePos=CurrentPos;break;case VK_DOWN:break;case VK_SPACE:break;}ReleaseDC(hwnd,hdc);}然后就是检查方块是不是出格了用这个函数 MAPX MAPY 是游戏里数组的长和高map [][]是保存方块有没被放置状态有还是没有bool Check(int dir,int pX,int pY,int shape){int x,y;for(int ff=0;ff<4;ff++){x= SQRARRAY[shape][dir][ff].x+pX;y= SQRARRAY[shape][dir][ff].y+pY;if(x<0 || x>=MAPX || y<0 ||y>=MAPY ||map[Pos[ff].x][Pos[ff].y]!=0){return FALSE;}}return TRUE;}1.#include "tetris.h"2.const int BEGINX= 50;//游戏图形的开始位置3.const int BEGINY= 50 ;4.const int FSIZE= 19 ; //方块大小5.const int FOUR =4;6.const int MAPX =10;7.const int MAPY=20;8.struct PosInfo9.{10.int x,y,dir,shape;11.};12.13.PosInfo CurrentPos,PrePos;//全局变量14.int GameMap[MAPX][MAPY]; //游戏方格15.16.HBRUSH PenArray[10];//用画刷可以用fillrect 画实心的图形17.void Init(HWND hwnd)18.{19.20.PenArray [0]=CreateSolidBrush(RGB(255,255,255));//现在是白色背景21.PenArray [1]=CreateSolidBrush(RGB(120,120,120));22.CurrentPos.dir=0;23.CurrentPos.shape=0;24.CurrentPos.x=2;25.CurrentPos.y=2;26.PrePos=CurrentPos;27.}28.29.30.const POINT SQRARRAY[7][FOUR][FOUR]=31.{32.{0,-1,0,0,1,0,2,0,33.1,0,0,0,0,1,0,2,34.0,1,0,0,-1,0,-2,0,35.-1,0,0,0,0,-1,0,-2},36.{-1,0,0,0,0,1,0,2,37.-1,0,0,0,-2,0,0,-1,38.0,-1,0,0,0,-2,1,0,39.0,1,0,0,1,0,2,0},40.41.{ -1,0,0,0,0,-1,1,0,42.0,-1,0,0,1,0,0,1,43.-1,0,0,0,0,1,1,0,44.-1,0,0,0,0,-1,0,1},45.{ 0,-1,0,0,1,0,1,1,46.1,0,0,0,0,1,-1,1,47.0,-1,0,0,1,0,1,1,48.1,0,0,0,0,1,-1,1,49.},50.{ 0,-1,0,0,-1,0,-1,1,51.-1,0,0,0,0,1,1,1,52.0,-1,0,0,-1,0,-1,1,53.-1,0,0,0,0,1,1,1},54.55.{-1,0,0,0,1,0,2,0,56.0,-1,0,0,0,1,0,2,57.-1,0,0,0,1,0,2,0,58.0,-1,0,0,0,1,0,2},59.60.{-1,0,0,0,-1,1,0,1,61.-1,0,0,0,-1,1,0,1,62.-1,0,0,0,-1,1,0,1,63.-1,0,0,0,-1,1,0,1}64.} ;65.66.67.68.69.void huafangkuai(HDC hdc,int x,int y,int color)70.{71.72.int screenx=BEGINX +x*FSIZE; //方块左上角的坐标是x乘方块大小再加上起始位置73.int screeny=BEGINY +y*FSIZE;74.RECT rt;75.rt.left=screenx;76.rt.top=screeny;77.rt.right=screenx+FSIZE;78.rt.bottom=screeny+FSIZE;79.FillRect(hdc,&rt ,PenArray[color]);80.81.82.}83.84.//画所有7种俄罗斯方块 dir方块的方向 shape 方块的形状85.void DrawTetris(HDC hdc, int dir,int shape,int color,int x,int y)86.{87.88.89.90.int nx,ny;91.for(int i=0;i<4;i++)92.{93.94.nx=SQRARRAY[shape][dir].x+x;ny=SQRARRAY[shape][dir].y+y;95.huafangkuai(hdc,nx,ny,color);96.}97.}98.99.100.void KeyDown(int keycode,HWND hwnd)101.{102.HDC hdc= GetDC(hwnd);103.104.switch(keycode)105.{106.case VK_LEFT:107.if(!Check(CurrentPos.dir,CurrentPos.x-1,CurrentPos.y,CurrentPos.shape)) 108.{109.return;110.}111.112.CurrentPos.x--;113.DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);114.DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y); 115.PrePos=CurrentPos;116.break;117.case VK_RIGHT:118.119.if(!Check(CurrentPos.dir,CurrentPos.x+1,CurrentPos.y,CurrentPos.shape)) 120.{121.return;122.}123.CurrentPos.x++;124.DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);125.DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y); 126.PrePos=CurrentPos;127.break;128.case VK_DOWN:129.if(!Check(CurrentPos.dir,CurrentPos.x,CurrentPos.y+1,CurrentPos.shape))130.{131.return;132.}133.CurrentPos.y++;134.DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);135.DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y); 136.PrePos=CurrentPos;137.break;138.case VK_SPACE:139.if(!Check((CurrentPos.dir+1)%4,CurrentPos.x,CurrentPos.y,CurrentPos.shape)) 140.{141.return;142.}143.++CurrentPos.dir%=4;144.DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);145.DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y); 146.PrePos=CurrentPos;147.break;148.}149.ReleaseDC(hwnd,hdc);150.}151.152.153.//check 检查方块移动时是否有数组越界情况有则什么也不执行154.bool Check(int dir,int pX,int pY,int shape)155.156.{157.int x,y;158.for(int ff=0;ff<4;ff++)159.{160.x= SQRARRAY[shape][dir][ff].x+pX;161.y= SQRARRAY[shape][dir][ff].y+pY;162.if(x<0 || x>=MAPX || y<0 ||y>=MAPY ||GameMap[x][y]!=0)163.{164.return FALSE;165.}166.}167.168.return TRUE;169.170.}171.172.//画已经放在下面的方块通过检查数组是否大于0 是则画数数里面的色彩173.//否则画白色擦除174.void DrawMap(HDC hdc )175.{176.177.Rectangle(hdc,BEGINX-10,BEGINY-10,BEGINX+MAPX*FSIZE+10,BEGINY+MAPY*FSIZE+10); 178.//画基本的外框179.for(int x=0;x<MAPX;x++)180.{181.for(int y=0;y<MAPY;y++)182.{183.if(GameMap[x][y]>0)184.{185.huafangkuai(hdc,x,y,GameMap[x][y]);186.}187.else188.{189.huafangkuai(hdc,x,y,0);190.}191.}192.}193.}194.DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);DrawTetris(hdc,CurrentPos.dir,CurrentPos.shape,1,CurrentPos.x,CurrentPos.y);这个0就是调用和窗口一样的画刷1呢是我定义的方块的颜色PrePos 保存的是方块未移动时的位置DrawTetris(hdc,PrePos.dir,PrePos.shape,0,PrePos.x,PrePos.y);之后因为和之前画的在一个地方而且是白色的所以前面画的就清除掉了195.。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
return CTRL_DOWN;
}
// 如果有按键,返回按键对应的功能
if (_kbhit())
{
switch(_getch())
{
case 'w':
case 'W': return CTRL_ROTATE;
case 'a':
case ' ': return CTRL_SINK;
case 0:
case 0xE0:
switch(_getch())
{
case 72: return CTRL_ROTATE;
case 75: return CTRL_LEFT;
{
case CTRL_ROTATE: OnRotate(); break;
case CTRL_LEFT: OnLeft(); break;
case CTRL_RIGHT: OnRight(); break;
void OnLeft(); // 左移方块
void OnRight(); // 右移方块
void OnDown(); // 下移方块
void OnSink(); // 沉底方块
/////////////////////////////////////////////
// 函数定义
COLORREF color; // 方块的颜色
} g_Blocks[7] =
{
{0x0F00, 0x4444, 0x0F00, 0x4444, RED}, // I
{0x0660, 0x0660, 0x0660, 0x0660, BLUE}, // 口
{0x4460, 0x02E0, 0x0622, 0x0740, MAGENTA}, // L
// 获取控制值
while(true)
{
// 如果超时,自动下落一格
DWORD newtime = GetTickCount();
if (newtime - oldtime >= (530-LEVEL*50)) //控制下降速度
{
oldtime = newtime;
case 77: return CTRL_RIGHT;
case 80: return CTRL_DOWN; } 来自 } } }
}
// 分发控制命令
void DispatchControl(CTRL _ctrl)
{
switch(_ctrl)
outtextxy(20, 370, _T("左:左移"));
outtextxy(20, 390, _T("右:右移"));
outtextxy(20, 410, _T("下:下移"));
outtextxy(20, 430, _T( "空格:沉底"));
outtextxy(20, 450, _T("ESC:退出"));
LEVEL=hangshu/20+1; //每消除20行升一级,下降速度加快
outtextxy((WIDTH + 1) * SIZE, 150, _T("等级:"));
TCHAR s[10];
_stprintf(s, _T("%d"), LEVEL); // 高版本 VC 推荐使用 _stprintf_s 函数
outtextxy((WIDTH + 4) * SIZE, 150,s);
outtextxy((WIDTH + 1) * SIZE, 170, _T("得分:"));
TCHAR ss[10];
_stprintf(ss, _T("%d"), SCORE); // 高版本 VC 推荐使用 _stprintf_s 函数
{0x2260, 0x0E20, 0x0644, 0x0470, YELLOW}, // 反L
{0x0C60, 0x2640, 0x0C60, 0x2640, CYAN}, // Z
{0x0360, 0x4620, 0x0360, 0x4620, GREEN}, // 反Z
{0x4E00, 0x4C40, 0x0E40, 0x4640, BROWN} // T
case 'A': return CTRL_LEFT;
case 'd':
case 'D': return CTRL_RIGHT;
case 's':
case 'S': return CTRL_DOWN;
case 27: return CTRL_QUIT;
void Quit(); // 退出游戏
void NewGame(); // 开始新游戏
void GameOver(); // 结束游戏
CTRL GetControl(bool _onlyresettimer = false); // 获取控制命令
void DispatchControl(CTRL _ctrl); // 分发控制命令
{
static DWORD oldtime = GetTickCount(); // 重置计时器
if (_onlyresettimer)
{
oldtime = GetTickCount();
return CTRL_LEFT; // 仅仅为了重置计时器,随便返回一个值
}
NewGame();// 开始新游戏 这个函数有问题
}
// 退出游戏
void Quit()
{
closegraph();
exit(0);
}
// 开始新游戏
void NewGame()
{
// 清空游戏区
//setfillcolor(BLUE);
setfillstyle(1); //不填充
if (MessageBox(wnd,_T( "您要退出游戏吗?"),_T( "提醒"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
Quit();
}
}
}
// 初始化游戏
void Init()
{
initgraph(640, 480);
#define WIDTH 10 // 游戏区宽度
#define HEIGHT 22 // 游戏区高度
#define SIZE 20 // 每个游戏区单位的实际像素
// 定义操作类型
enum CTRL
{
CTRL_ROTATE, // 方块旋转
CTRL_LEFT, CTRL_RIGHT, CTRL_DOWN, // 方块左、右、下移动
g_NextBlock.x = WIDTH + 1;
g_NextBlock.y = HEIGHT - 1;
// 获取新方块
NewBlock(); //肯定有问题
}
// 结束游戏
void GameOver()
{
HWND wnd = GetHWnd();
if (MessageBox(wnd, _T("游戏结束。\n您想重新来一局吗?"),_T( "游戏结束"), MB_YESNO | MB_ICONQUESTION) == IDYES)
void NewBlock(); // 生成新的方块
bool CheckBlock(BLOCKINFO _block); // 检测指定方块是否可以放下
void DrawBlock(BLOCKINFO _block, DRAW _draw = SHOW); // 画方块
void OnRotate(); // 旋转方块
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <windows.h> /////////////////////////////////////////////
// 定义常量、枚举量、结构体、全局变量
/////////////////////////////////////////////
/////////////////////////////////////////////// 主函数
int LEVEL=1;
int SCORE=0;
int hangshu=0;
void main()
{
Init(); CTRL c;
while(true)
{
SCORE=hangshu*100; //得分等于行数乘以100
//outtextxy(20, 450, _T("ESC:退出"));
setorigin(220, 20);// 设置坐标原点
// 绘制游戏区边界
rectangle(-1, -1, WIDTH * SIZE, HEIGHT * SIZE);
rectangle((WIDTH + 1) * SIZE - 1, -1, (WIDTH + 5) * SIZE, 4 * SIZE);
srand((unsigned)time(NULL));
// 显示操作说明
//setfont(14, 0, "宋体");
相关文档
最新文档