C语言俄罗斯方块游戏源代码
- 格式:docx
- 大小:12.01 KB
- 文档页数:22
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复制代码#include<stdio.h>#include<stdlib.h>#include<unistd.h>#define WIDTH 20#define HEIGHT 10typedef enum {BLOCK_EMPTY,BLOCK_I,BLOCK_J,BLOCK_L,BLOCK_O,BLOCK_S,BLOCK_Z} BlockType;typedef struct {BlockType type;int x;int y;} Block;Block board[WIDTH][HEIGHT];BlockType currentBlock = BLOCK_I;int rotation = 0;int x = WIDTH / 2;int y = HEIGHT - 1;void drawBoard() {for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { char ch = ' ';switch (board[i][j].type) {case BLOCK_EMPTY:ch = '.';break;case BLOCK_I:ch = 'I';break;case BLOCK_J:ch = 'J';break;case BLOCK_L:ch = 'L';break;case BLOCK_O:ch = 'O';break;case BLOCK_S:ch = 'S';break;case BLOCK_Z:ch = 'Z';break;}printf("%c", ch);}printf("\n");}}void updateBoard() {for (int i = 0; i < WIDTH; i++) {for (int j = 0; j < HEIGHT; j++) {if (board[i][j].type != BLOCK_EMPTY) {board[i][j].y--; // Move block down one row.} else { // Place new block.switch (currentBlock) { // Place based on current block type.case BLOCK_I: // Place full I-block.board[i][j].type = BLOCK_I; // Column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column.j+1 y row.i+1 X -- column.j y row.i X -- column.j+1 y row.i X -- column.j y row.i+1 X -- column j Y n Row Y j Columns n - j 1 -- i 1 i - i j Row i Row i - 1 i Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column Column n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i - - - - - - - - - - - - - - -。
俄罗斯方块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语言俄罗斯方块源代码Vc6.0编译通过#include<windows.h>#include<stdio.h>#include<time.h>#include<stdlib.h>#include<malloc.h>#include<conio.h>#define MAP_WIDTH10#define MAP_HEIGHT20#define BLOCKM"■"#define BKBLOCK"□"#define OUTSTD GetStdHandle(STD_OUTPUT_HANDLE)typedef int(*PFUN)(void *pData);void ShowMapArray(int map[MAP_HEIGHT][MAP_WIDTH]);//生成方块int xyIsInarrBlock(int arrBlock[4][2], int x, int y) //有返回1 没有返回0 {int i;for (i = 0;i<4;i++)if (arrBlock[i][0] == x && arrBlock[i][1] == y)return 1;return 0;}void GetTransBlocks(int arrBlock[4][2])//坐标模式4*4方块{int nTmp, x, y;int nCount = 1;int i;int nMinx = 0, nMiny = 0;memset(arrBlock, 0, 8 * sizeof(int));while (nCount < 4){nTmp = rand() % nCount;x = arrBlock[nTmp][0];y = arrBlock[nTmp][1];nTmp = rand() % 4;switch (nTmp){case 0:x--;break;case 1:y--;break;case 2:x++;break;case 3:y++;break;}if (xyIsInarrBlock(arrBlock, x, y))continue;arrBlock[nCount][0] = x;arrBlock[nCount][1] = y;if (nMinx > x)nMinx = x;if (nMiny > y)nMiny = y;nCount++;}for (i = 0;i<4;i++){if (nMinx < 0)arrBlock[i][0] -= nMinx;if (nMiny < 0)arrBlock[i][1] -= nMiny;}}//旋转void Ratat(int arrBlock[4][2], int Direct) // driect 1 顺时针方向旋转,-1 逆时针方向旋转{int i;int nMinx, nMiny;int nTmp;for (i = 0;i<4;i++){nTmp = arrBlock[i][0];arrBlock[i][0] = arrBlock[i][1] * (-1)*Direct;arrBlock[i][1] = nTmp*Direct;if (i == 0){nMinx = arrBlock[i][0];nMiny = arrBlock[i][1];}else{if (nMinx > arrBlock[i][0])nMinx = arrBlock[i][0];if (nMiny > arrBlock[i][1])nMiny = arrBlock[i][1];}}for (i = 0;i<4;i++){if (nMinx < 0)arrBlock[i][0] -= nMinx;if (nMiny < 0)arrBlock[i][1] -= nMiny;}}void gotoxy(int x, int y){COORD pos = { x,y };SetConsoleCursorPosition(OUTSTD, pos);}void showxy(int x, int y, int bShow){COORD pos = { x * 2 + 2,y + 2 };SetConsoleCursorPosition(OUTSTD, pos);if (bShow)printf(BLOCKM);elseprintf(BKBLOCK);}void DisShowCursor(){CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(OUTSTD, &cci);cci.bVisible = FALSE;SetConsoleCursorInfo(OUTSTD, &cci);}int CheckBlockPlace(int map[MAP_HEIGHT][MAP_WIDTH], int x, int y, int block[4][2], int bShow) //判断位置是否可用{int i;if (x < 0 || y < 0 || x >= MAP_WIDTH || y >= MAP_HEIGHT)return 0;for (i = 0;i<4;i++){if (map[y + block[i][1]][x + block[i][0]] == 1 && bShow)return 0;if (y + block[i][1] >= MAP_HEIGHT || x + block[i][0] >= MAP_WIDTH)return 0;}return 1;}int ShowBlock(int x, int y, int block[4][2], int bShow){int i;for (i = 0;i<4;i++)showxy(block[i][0] + x, block[i][1] + y, bShow);return 1;}void LoadMap(int map[MAP_HEIGHT][MAP_WIDTH]){int i, j;DisShowCursor();system("cls");printf("----------------俄罗斯方块v0.1--------------");printf("\n\n");for (i = 0;i<MAP_HEIGHT;i++){printf(" ");for (j = 0;j<MAP_WIDTH;j++){if (map[i][j])printf(BLOCKM);elseprintf(BKBLOCK);}printf("\n");}gotoxy(MAP_WIDTH * 2 + 6, 4);printf("按s开始\n");gotoxy(MAP_WIDTH * 2 + 6, 5);printf("Next:");gotoxy(MAP_WIDTH * 2 + 6, 12);printf("分数:");}int gameDown(int map[MAP_HEIGHT][MAP_WIDTH], int blockxy[4][2], int nSec, PFUN OnFun, void *pOnData){int i, j, k;int nSelect;int x = 3, y = 0;static int maxy = 20;int missrow = 0;int xsum = 0;while (1){nSelect = OnFun(pOnData);if (nSelect){switch (nSelect){case 75:{if (CheckBlockPlace(map, x - 1, y, blockxy, 1))x--;}break;case 72:{Ratat(blockxy, 1);if (!CheckBlockPlace(map, x, y, blockxy, 1)){Ratat(blockxy, -1);}}break;case 77:{if (CheckBlockPlace(map, x + 1, y, blockxy, 1))x++;}break;}}else{if (CheckBlockPlace(map, x, y, blockxy, 1)){ShowBlock(x, y, blockxy, 1);Sleep(nSec);if (CheckBlockPlace(map, x, y + 1, blockxy, 1)){ShowBlock(x, y, blockxy, 0);y++;}else{for (i = 0;i<4;i++){map[y + blockxy[i][1]][x + blockxy[i][0]] = 1;}if (y < maxy)maxy = y;break;}}elsereturn -1;}}for (i = maxy;i<MAP_HEIGHT;i++){xsum = 0;for (j = 0;j<MAP_WIDTH;j++){xsum += map[i][j];}if (xsum == MAP_WIDTH){for (k = i;k >= maxy;k--)for (j = 0;j<MAP_WIDTH;j++)map[k][j] = map[k - 1][j];missrow++;LoadMap(map);}}return missrow;}// help functionvoid ShowMapArray(int map[MAP_HEIGHT][MAP_WIDTH]){int i, j;for (i = 0;i<MAP_HEIGHT;i++){COORD pos = { MAP_WIDTH * 2,i };SetConsoleCursorPosition(OUTSTD, pos);for (j = 0;j<MAP_WIDTH;j++){printf("%d", map[i][j]);}}}int GetInfo(void *pData){while (kbhit()){char ch1 = getch();if (ch1 < 0){ch1 = getch();}return ch1;}while (kbhit())getch();return 0;}int main(){int map[MAP_HEIGHT][MAP_WIDTH] = { 0 };int blockarrnow[4][2] = { 0 }, blockarrnext[4][2] = { 0 };int ch, nRe, i, j, nScro = 0, nSpeed = 300;BOOL bRun = TRUE;LoadMap(map);srand((unsigned)time(NULL));while (bRun){if (kbhit()){ch = getch();}if (ch == 's' || ch == 'S'){GetTransBlocks(blockarrnow);while (bRun){GetTransBlocks(blockarrnext);ShowBlock(MAP_WIDTH + 2, 5, blockarrnext, 1);nRe = gameDown(map, blockarrnow, nSpeed, GetInfo, NULL);for (i = 0;i<4;i++){blockarrnow[i][0] = blockarrnext[i][0];blockarrnow[i][1] = blockarrnext[i][1];}for (i = 0;i <= 4;i++)for (j = 0;j <= 4;j++){gotoxy(MAP_WIDTH * 2 + 4 + j * 2, 7 + i);printf(" ");}if (nRe < 0){bRun = FALSE;break;}else{nScro += (nRe * 100);gotoxy(MAP_WIDTH * 2 + 11, 12);printf("%d", nScro);}}}}return 0;}Vs2015 编译运行配图。
//俄罗斯方块#include "stdio.h"#include "conio.h"#include "stdlib.h"#include "windows.h"#include "time.h"#define N 17#define M 13#define K 19int s[N][M]={{0,0,0},{0,0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, {1},{1,0,0,1},{1,1,1,1,1,1,0,1,1,0,0,1,1}};/*当前状态*/inta[K][3][3]={{0,2,0,2,2,2},{0,2,0,2,2,0,0,2},{0,2,0,0,2,2,0,2},{2,2,2,0,2},{2,2,2,0,0,2 ,0},{2,0,0,2,2,2},{2,0,0,2,0,0,2,2},{0,0,2,0,0,2,0,2,2},{0,0,2,2,2,2},{2,2,2,2,0,0}, {2,2,0,0,2,0,0,2,0},{0,2,2,0,2,0,0,2,0},{{2},{2},{2}},{2,2,2},{2,2,0,2,2,0},{2,0,0,2,2,0,0,2},{0,0,2,0,2,2,0,2},{2,2,0,0,2,2},{0,2,2,2,2,0}};void Disp(){int i,j;for(i=0;i<N;i++){for(j=0;j<M;j++)printf("%c",s[i][j]?48+s[i][j]:' ');printf("┃\n");}printf("━━━━━━━━");printf("\n\n操作说明:A-->左移,D-->右移,W-->变形,ESC-->退出\n");}void Down(){int i,j,k;for(j=0;j<M;j++)if(s[N-1][j]==2)break;/*判断是否在下边界*/if(j<M)/*若方块在下边界则将方块由2变1;因为用两种不同的符号,容易判断方块是否“着陆”及左右移动时,是否碰壁*/{for(i=0;i<N;i++)for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=1;for(i=N-1;i>=0;i--){for(j=0;j<M;j++)//判断第i行是否有空格if(s[i][j]==0)break;if(j==M)/*若第i行没空格消去第i行*/for(k=i++-1;k>=0;k--)//?for(j=0;j<M;j++)s[k+1][j]=s[k][j];}return;}for(i=0;i<N-1;i++){for(j=0;j<M;j++)if(s[i][j]==2)if(s[i+1][j]!=0&&s[i+1][j]!=2)break;/*方块下方不空说明触到1了退出内循环*/ if(j<M)break;/*方块下方不空退出外循环*/}if(i<N-1||j<M){for(i=0;i<N;i++)//若已触到1则将方块由 2变1*/for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=1;for(i=N-1;i>=0;i--){for(j=0;j<M;j++)if(s[i][j]==0)break;//判断第i行是否有空格if(j==M)/*若第i行没空格消去第i行*/for(k=i++-1;k>=0;k--)for(j=0;j<M;j++)s[k+1][j]=s[k][j];}return;}for(i=N-1;i>=0;i--)for(j=0;j<M;j++)if(s[i][j]==2)s[i+1][j]=s[i][j],s[i][j]=0;/*方块下移*/}void Right(){int i,j;for(i=0;i<N;i++)if(s[i][M-1]==2)return;/* 已经在右边界退出 */for(i=0;i<N;i++)for(j=0;j<M-1;j++)if(s[i][j]==2)if(s[i][j+1]!=0&&s[i][j+1]!=2)return;/* 方块右方不空,即方块右边有1 退出 */ for(j=M-2;j>=0;j--)for(i=0;i<N;i++)if(s[i][j]==2)s[i][j+1]=s[i][j],s[i][j]=0;/* 方块右移 */}void Left(){int i,j;for(i=0;i<N;i++)if(s[i][0]==2)return;/* 已经在左边界退出 */for(i=0;i<N;i++)for(j=1;j<M;j++)if(s[i][j]==2)if(s[i][j-1]!=0&&s[i][j-1]!=2)return;/* 方块左方不空退出 */ for(j=1;j<M;j++)for(i=0;i<N;i++)if(s[i][j]==2)s[i][j-1]=s[i][j],s[i][j]=0;/* 方块左移 */}int Have()/*判断是否有可移动方块,没有返回1,否则返回0*/{int i,j;for(i=0;i<N;i++)for(j=1;j<M;j++)if(s[i][j]==2)return 0;return 1;}int Add()/*随机生成方块*/{int t,x;/*生成两随机数t和x分别作为第t种方块和第x位置出现*/int i,j;srand((unsigned int)time(NULL));t=rand()%K;x=rand()%(M-3);if(x<0) x=-x%(M-3);//?for(i=0;i<3;i++)for(j=x;j<x+3;j++)//把生成的方块存到初状态中s[i][j]=a[t][i][j-x];}void bianxing(int t,int n){int i,j,k,m,x,y;for(i=0;i<N;i++)//首先扫描是否有移动方块;及方块变形前的位置“行、列”{m=-1;for(j=0;j<M;j++)if(s[i][j]==2){m=i,x=j,y=i;break;//y,x记录所在行、列;并退出内循环}if(m!=-1)//m!=-1证明有移动方块break;//退出外循环}if(m!=-1)//m!=-1证明有移动方块{if(x+3>M||y+3>N) return;//判断是否有可变形空间,没有就返回for(i=y;i<y+3;i++)//判断是否有3*3的变形空间,没有就返回for(j=x;j<x+3;j++)if(s[i][j]==1) return;/*擦除当前移动方块;因为上面判断3*3的移动空间,是从上面开始扫描,遇到第一个小格子时,依他为基点向右下方扫描是否有3*3的空间;显然只进行下面的变形--存储是不行的;如:002002022-->2220020时,显然前面的方格倒数第二个2,留在了3*3变形空间的外面,输出图形将多一个格子,所以要在变形-->存储操作前进行擦除操作*/for(i=y;i<y+3;i++)for(j=0;j<M;j++)if(s[i][j]==2)s[i][j]=0;//变形并把它存储到当前状态中if(t<=3&&t>=0){static int h1;if(h1>n)h1=0;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h1][i-y][j-x];h1++;}else if(t<=11&&t>=4){static int h2=4;if(h2>n)h2=4;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h2][i-y][j-x];h2++;}else if(t<=13&&t>=12){static int h3=12;if(h3>n)h3=12;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h3][i-y][j-x];h3++;}else if(t<=18&&t>=15){static int h4=15;if(h4>n)h4=0;for(i=y;i<y+3;i++)//把方块存储到当前状态中for(j=x;j<x+3;j++)s[i][j]=a[h4][i-y][j-x];h4++;}}void main(){char c;int i=0,t;char str[][50]={" ((`'-\"``\"\"-'`))"," ) - - ( "," / (o _ o) \ "," \ ( 0 ) /"," _'-.._'='_..-'_ "," /`;#'#'#.-.#'#'#;`\ "," \_)) '#' ((_/ "," #. ☆ Game ☆ # "," '#. Over! .#' "," / '#. .#' \ "," _\ \'#. .#'/ /_"," (((___) '#' (___) ",""};system("color 0a");while(1)/*判断是否有按键,没有循环输出i,否则停,conio.h*/{if(!kbhit())/*kbhit用来判断是否有按键输入,若有按键返回非零值,否则返回零;没有按键时c被赋予一个“非操作键值”,它将一直下移;有按键是调用getch函数,读取键值*/c='2';elsec=getch();if(c=='p')//停止键;按任意键可解除停止getch();system("CLS");/*清屏,TC用clrscr();,VC用system("CLS");*/if(Have())//Have()判断是否有可移动方块,没有返回1,否则返回0t=Add();switch(c){case 'a':Left();break; /*左移*/case 'd':Right();break; /*右移*/case 27: system("pause");return; /*按Esc(=27)另存后退出*/default:;}//变形if(c=='w')if(t>=0&&t<=3) bianxing(t,3);else if(t>=4&&t<=11) bianxing(t,11);else if(t==12||t==13) bianxing(t,13);else if(t>=15&&t<=18) bianxing(t,18);c='2';Down();//判断方块的停、走和消除//判断顶层是否有1 有:游戏结束for(i=0;i<M;i++)if(s[0][i]==1){system("CLS");i=0;while(1){if(strlen(str[i])==0)break;printf("%s\n",str[i++]);}system("pause");exit(0);}Disp();//刷屏Sleep(500);/*睡眠ms,windows.h*/}}***********************************************************。
#include <stdio.h>#include <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: { /*下方向键,横坐标加一。
#include<stdio.h>#include<stdlib.h>#include<graphics.h>#include<bios.h>/*下面定义了一些控制命令*//*重画界面命令*/#define CMDDRAW5/*消去一个满行的命令*/#define CMDDELLINE6/*自动下移一行的命令*/#define CMDAOTODOWN7/*生产新的方块*/#define CMDGEN8/*向左移动的命令,以左箭头<-控制,它的ASCII码值是75*/ #define CMDLEFTMOVE75/*向右移动的命令,以右箭头->控制,它的ASCII码值是77*/ #define CMDRINGHTMOVE 77/*旋转方块的命令,以空格来控制*/#define CMDROTATE57/*向下移动的命令,以向下的箭头控制,它的ASCII码值是80*/ #define CMDDOWNMOVE80/*退出游戏的控制命令,以esc键控制,它的ASCII码值是1*/#define CMDESC1/*定义了方块下降的时间间隔*/#define TIMEINTERVAL4/*下面定义了游戏区的大小*/#define MAXWIDTH15#define MAXHEIGHT30/*组成方块的小格子的宽度*/#define BOXWIDTH15/*用两个数组来表示新旧两个矩形游戏区*/int oldarea[MAXHEIGHT+1][MAXWIDTH];int area[MAXHEIGHT+1][MAXWIDTH];/*定义一个需要改变的屏幕区域,初次之外的区域不用进行重绘*/ int actW,actH,actX,actY;/*当前方块的一些属性(坐标,颜色,高,宽)*/int curX,curY,curColor,curW,curH;/*新的方块的一些属性(坐标,颜色,高,宽)*/int newX,newY,newColor,newW,newH;/*制定方块的状态*/int active;/*存储当前方块的数组*/int box[4][4];/*当前方块的颜色*/int BOXCOLOR;/*控制命令*/int CMD;/*定义七种基本的方块形状*/int BOX[7][4][4]={{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},{{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}};/*得到方块的宽度,即从右向左第一个不空的列*/ int GetWidth(){int i,j;for(i=3;i>0;i--)for(j=0;j<4;j++)if(box[j][i]) return i;return 0;}/*得到方块的高度,从上往下第一个不空的行*/ int GetHeight(){int i,j;for(j=3;j>0;j--)for(i=0;i<4;i++)if(box[j][i]) return j;return 0;}/*清除原有的方块占有的空间*/void ClearOldspace(){int i,j;for(j=0;j<=curH; j++)for(i=0;i<=curW; i++)if(box[j][i])area[curY+j][curX+i]=0;}/*置位新方块的位置*/void PutNewspace(){int i,j;for(j=0;j<=newH;j++)for(i=0;i<=newW;i++)if(box[j][i])area[newY+j][newX+i]=BOXCOLOR;}/*判断方块的移动是否造成区域冲突*/int MoveCollision(int box[][4]){int i,j;if(newX<0) return 1;if(newX+newW>=MAXWIDTH) return 1;if(newY<0) return 1;for(j=0;j<=newH;j++)for(i=0;i<=newW;i++)if(area[newY+j][newX+i]&&box[j][i]) return 1; return 0;}/*判断翻转方块是否造成区域的冲突*/int RotateBoxCollision(int box[][4]){int i,j;if(newX+newW>=MAXWIDTH) newX=MAXWIDTH-1-newW; if(newY+newH>=MAXHEIGHT) newY=MAXHEIGHT-1-newH; if(MoveCollision(box)) return 1;for(i=0;i<=newW;i++)for(j=0;j<=newH;j++)if(area[newY+j][newX+i]){newX-=newW-i+1; goto L;}L: return MoveCollision(box);}/*游戏结束*/int GameOver(){if(!active &&(curY+curH>MAXHEIGHT-3))return 1;elsereturn 0;}/*判断是否超时,即是否超过允许的时间间隔*/ int TimeOut(){static long tm,old;tm=biostime(0,tm);if(tm-old<TIMEINTERVAL)return 0;else{old=tm;return 1;}}/*重绘游戏区*/void DrawSpace(){int row,col,x1,y1,x2,y2;for(row=actY;row<=actY+actH;row++)for(col=actX;col<=actX+actW;col++)if(area[row][col]!=oldarea[row][col]) {if(area[row][col]==0)setfillstyle(SOLID_FILL,BLACK);elsesetfillstyle(SOLID_FILL,BOXCOLOR); x1=56+col*BOXWIDTH;x2=x1+BOXWIDTH;y1=464-(row+1)*BOXWIDTH;y2=y1+BOXWIDTH;bar(++x1,++y1,--x2,--y2);oldarea[row][col]=area[row][col]; }CMD=0;}/*消去满行*/void ClearFullline(){int row,col, rowEnd,full,i,j; rowEnd=newY+newH;if(rowEnd>=MAXHEIGHT-1)rowEnd=MAXHEIGHT-2;for(row=newY; row<=rowEnd;) {full=1;for(col=0;col<MAXWIDTH;col++) if(!area[row][col]){full=0; break;}if(!full){++row;continue;}for(j=row; j<MAXHEIGHT-1;j++) for(i=0;i<MAXWIDTH;i++)area[j][i]=area[j+1][i];actX=0;actY=row;actW=MAXWIDTH-1;actH=MAXHEIGHT-1-row; DrawSpace();rowEnd--;}CMD=CMDGEN;}/*向左移动方块*/ int MoveLeft(){newX=curX-1; ClearOldspace();if(MoveCollision(box)) {newX=curX; PutNewspace(); CMD=0;return 0;}PutNewspace(); actW=curW+1;actX=curX=newX; CMD=CMDDRAW; return 1;}/*向右移动方块*/int MoveRight(){newX=curX+1; ClearOldspace(); if(MoveCollision(box)){newX=curX;PutNewspace();CMD=0;return 0;}PutNewspace();actW=curW+1;actX=curX;curX=newX;CMD=CMDDRAW;return 1;}/*向下移动方块*/int MoveDown(){int i,j;newY=curY-1;ClearOldspace();if(MoveCollision(box)){newY=curY;PutNewspace();active=0;CMD=CMDDELLINE;return 0;}PutNewspace();actH=curH+1;actY=newY;curY=newY;CMD=CMDDRAW;return 1;}/*按加速键后方块迅速下落到底*/ void MoveBottom(){while(active){MoveDown();DrawSpace();}CMD=CMDDELLINE;}/*初始化*/void InitialGame(){int i,j,x1,y1,x2,y2;int driver=DETECT, mode=0; initgraph(&driver,&mode,"e:\\tc"); cleardevice();randomize();setfillstyle(SOLID_FILL,BLUE);bar(0,0,639,479);x1=56;y1=464-BOXWIDTH*MAXHEIGHT; x2=56+MAXWIDTH*BOXWIDTH;y2=464;rectangle(--x1,--y1,++x2,++y2);setfillstyle(SOLID_FILL,BLACK);bar(++x1,++y1,--x2,--y2);y1=464-MAXHEIGHT*BOXWIDTH; y2=464;setcolor(DARKGRAY);for(i=0;i<MAXWIDTH;i++){x1=56+i*BOXWIDTH;line(x1,y1,x1,y2);}x1=56; x2=x1+MAXWIDTH*BOXWIDTH;for(j=0;j<MAXHEIGHT;j++){y1=464-j*BOXWIDTH;line(x1,y1,x2,y1);}for(j=0;j<MAXHEIGHT;j++)for(i=0;i<MAXWIDTH;i++)area[j][i]=oldarea[j][i]=0;actX=0; actY=0; actW=MAXWIDTH-1; actH=MAXHEIGHT-1; DrawSpace();CMD=CMDGEN;}/*得到控制命令*/ void GetCMD(){if(CMD) return;if(TimeOut()){CMD=CMDAOTODOWN; return;}if(bioskey(1)){CMD=bioskey(0)>>8; return;}}/*生成一个新的方块*/ int GenerateNewbox() {int i,j,boxidx;boxidx=random(7); BOXCOLOR=random(7)+1;for(j=0;j<4;j++)for(i=0;i<4;i++)box[j][i]=BOX[boxidx][j][i];curW=GetWidth(); curH=GetHeight();curX=(MAXWIDTH+curW)/2;if(curX+curW>=MAXWIDTH)curX=MAXWIDTH-1-curW; curY=MAXHEIGHT-1-curH;newX=curX; newY=curY; actX=curX;actY=curY;actW=newW=curW; actH=newH=curH;active=1;if(MoveCollision(box)) return 0;PutNewspace();DrawSpace(); CMD=0;return 1;}/*翻转方块*/int RotateBox(){int newBox[4][4];int i,j;ClearOldspace();for(j=0;j<4;j++)for(i=0;i<4;i++)newBox[j][i]=0;for(j=0;j<4;j++)for(i=0;i<4;i++)newBox[curW-i][j]=box[j][i]; newW=curH;newH=curW;if(RotateBoxCollision(newBox)) {newW=curW;newH=curH;newX=curX;newY=curY;PutNewspace();CMD=0;return 0;}for(j=0;j<4;j++)for(i=0;i<4;i++)box[j][i]=newBox[j][i];PutNewspace();actH=newH>curH? newH:curH;actW=curX+actH-newX;actX=newX;actY=newY;curX=newX;curY=newY;curW=newW;curH=newH;CMD=CMDDRAW;return 1;}/*根据获得的命令来执行不同的操作*/ void ExecuteCMD(){switch(CMD){case CMDLEFTMOVE:MoveLeft();break;case CMDRINGHTMOVE: MoveRight();break;case CMDAOTODOWN: MoveDown();break;case CMDROTATE: RotateBox();break;case CMDDOWNMOVE: MoveBottom(); break;case CMDDRAW: DrawSpace();break;case CMDDELLINE: ClearFullline(); break;case CMDGEN: GenerateNewbox(); break;case CMDESC: closegraph(); return 0; default:CMD=0;}}/*主函数*/int main(){int i;InitialGame();do{GetCMD(); ExecuteCMD();}while(!GameOver()); getch(); closegraph(); return 0;}21/ 21。
C语⾔源码实现俄罗斯⽅块介绍俄罗斯⽅块(Tetris,俄⽂:Тетрис)是⼀款电视游戏机和掌上游戏机游戏,它由俄罗斯⼈阿列克谢·帕基特诺夫发明,故得此名。
俄罗斯⽅块的基本规则是移动、旋转和摆放游戏⾃动输出的各种⽅块,使之排列成完整的⼀⾏或多⾏并且消除得分。
由于上⼿简单、⽼少皆宜,从⽽家喻户晓,风靡世界。
源码#include <stdio.h>#include <string.h>#include <stdlib.h>#include <time.h>#include <conio.h>#include <windows.h>#ifdef _MSC_VER // M$的编译器要给予特殊照顾#if _MSC_VER <= 1200 // VC6及以下版本#error 你是不是还在⽤VC6?!#else // VC6以上版本#if _MSC_VER >= 1600 // 据说VC10及以上版本有stdint.h了#include <stdint.h>#else // VC10以下版本,⾃⼰定义int8_t和uint16_ttypedef signed char int8_t;typedef unsigned short uint16_t;#endif#ifndef __cplusplus // 据说VC都没有stdbool.h,不⽤C++编译,⾃⼰定义booltypedef int bool;#define true 1#define false 0#endif#endif#else // 其他的编译器都好说#include <stdint.h>#ifndef __cplusplus // 不⽤C++编译,需要stdbool.h⾥的bool#include <stdbool.h>#endif#endif// =============================================================================// 7种⽅块的4旋转状态(4位为⼀⾏)static const uint16_t gs_uTetrisTable[7][4] ={{ 0x00F0U, 0x2222U, 0x00F0U, 0x2222U }, // I型{ 0x0072U, 0x0262U, 0x0270U, 0x0232U }, // T型{ 0x0223U, 0x0074U, 0x0622U, 0x0170U }, // L型{ 0x0226U, 0x0470U, 0x0322U, 0x0071U }, // J型{ 0x0063U, 0x0264U, 0x0063U, 0x0264U }, // Z型{ 0x006CU, 0x0462U, 0x006CU, 0x0462U }, // S型{ 0x0660U, 0x0660U, 0x0660U, 0x0660U } // O型};// =============================================================================// 初始状态的游戏池// 每个元素表⽰游戏池的⼀⾏,下标⼤的是游戏池底部// 两端各置2个1,底部2全置为1,便于进⾏碰撞检测// 这样⼀来游戏池的宽度为12列// 如果想要传统的10列,只需多填两个1即可(0xE007),当然显⽰相关部分也要随之改动// 当某个元素为0xFFFFU时,说明该⾏已被填满// 顶部4⾏⽤于给⽅块,不显⽰出来// 再除去底部2⾏,显⽰出来的游戏池⾼度为22⾏static const uint16_t gs_uInitialTetrisPool[28] ={0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U,0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xC003U, 0xFFFFU, 0xFFFFU};#define COL_BEGIN 2#define COL_END 14// ============================================================================= typedef struct TetrisManager // 这个结构体存储游戏相关数据{uint16_t pool[28]; // 游戏池int8_t x; // 当前⽅块x坐标,此处坐标为⽅块左上⾓坐标int8_t y; // 当前⽅块y坐标int8_t type[3]; // 当前、下⼀个和下下⼀个⽅块类型int8_t orientation[3]; // 当前、下⼀个和下下⼀个⽅块旋转状态unsigned score; // 得分unsigned erasedCount[4]; // 消⾏数unsigned erasedTotal; // 消⾏总数unsigned tetrisCount[7]; // 各⽅块数unsigned tetrisTotal; // ⽅块总数bool dead; // 挂} TetrisManager;// ============================================================================= typedef struct TetrisControl // 这个结构体存储控制相关数据{bool pause; // 暂停bool clockwise; // 旋转⽅向:顺时针为trueint8_t direction; // 移动⽅向:0向左移动 1向右移动// 游戏池内每格的颜⾊// 由于此版本是彩⾊的,仅⽤游戏池数据⽆法存储颜⾊信息// 当然,如果只实现单⾊版的,就没必要⽤这个数组了int8_t color[28][16];} TetrisControl;HANDLE g_hConsoleOutput; // 控制台输出句柄// ============================================================================= // 函数声明// 如果使⽤全局变量⽅式实现,就没必要传参了void initGame(TetrisManager *manager, TetrisControl *control); // 初始化游戏void restartGame(TetrisManager *manager, TetrisControl *control); // 重新开始游戏void giveTetris(TetrisManager *manager); // 给⼀个⽅块bool checkCollision(const TetrisManager *manager); // 碰撞检测void insertTetris(TetrisManager *manager); // 插⼊⽅块void removeTetris(TetrisManager *manager); // 移除⽅块void horzMoveTetris(TetrisManager *manager, TetrisControl *control); // ⽔平移动⽅块void moveDownTetris(TetrisManager *manager, TetrisControl *control); // 向下移动⽅块void rotateTetris(TetrisManager *manager, TetrisControl *control); // 旋转⽅块void dropDownTetris(TetrisManager *manager, TetrisControl *control); // ⽅块直接落地bool checkErasing(TetrisManager *manager, TetrisControl *control); // 消⾏检测void keydownControl(TetrisManager *manager, TetrisControl *control, int key); // 键按下void setPoolColor(const TetrisManager *manager, TetrisControl *control); // 设置颜⾊void gotoxyWithFullwidth(short x, short y); // 以全⾓定位void printPoolBorder(); // 显⽰游戏池边界void printTetrisPool(const TetrisManager *manager, const TetrisControl *control); // 显⽰游戏池void printCurrentTetris(const TetrisManager *manager, const TetrisControl *control); // 显⽰当前⽅块void printNextTetris(const TetrisManager *manager); // 显⽰下⼀个和下下⼀个⽅块void printScore(const TetrisManager *manager); // 显⽰得分信息void runGame(TetrisManager *manager, TetrisControl *control); // 运⾏游戏void printPrompting(); // 显⽰提⽰信息bool ifPlayAgain(); // 再来⼀次// ============================================================================= // 主函数int main(){TetrisManager tetrisManager;TetrisControl tetrisControl;initGame(&tetrisManager, &tetrisControl); // 初始化游戏do{printPrompting(); // 显⽰提⽰信息printPoolBorder(); // 显⽰游戏池边界runGame(&tetrisManager, &tetrisControl); // 运⾏游戏if (ifPlayAgain()) // 再来⼀次{SetConsoleTextAttribute(g_hConsoleOutput, 0x7);system("cls"); // 清屏restartGame(&tetrisManager, &tetrisControl); // 重新开始游戏else{break;}} while (1);gotoxyWithFullwidth(0, 0);CloseHandle(g_hConsoleOutput);return 0;}// ============================================================================= // 初始化游戏void initGame(TetrisManager *manager, TetrisControl *control){CONSOLE_CURSOR_INFO cursorInfo = { 1, FALSE }; // 光标信息g_hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); // 获取控制台输出句柄SetConsoleCursorInfo(g_hConsoleOutput, &cursorInfo); // 设置光标隐藏SetConsoleTitleA("俄罗斯⽅块控制台版——By: NEWPLAN");restartGame(manager, control);}// ============================================================================= // 重新开始游戏void restartGame(TetrisManager *manager, TetrisControl *control){memset(manager, 0, sizeof(TetrisManager)); // 全部置0// 初始化游戏池memcpy(manager->pool, gs_uInitialTetrisPool, sizeof(uint16_t [28]));srand((unsigned)time(NULL)); // 设置随机种⼦manager->type[1] = rand() % 7; // 下⼀个manager->orientation[1] = rand() & 3;manager->type[2] = rand() % 7; // 下下⼀个manager->orientation[2] = rand() & 3;memset(control, 0, sizeof(TetrisControl)); // 全部置0giveTetris(manager); // 给下⼀个⽅块setPoolColor(manager, control); // 设置颜⾊}// ============================================================================= // 给⼀个⽅块void giveTetris(TetrisManager *manager){uint16_t tetris;manager->type[0] = manager->type[1]; // 下⼀个⽅块置为当前manager->orientation[0] = manager->orientation[1];manager->type[1] = manager->type[2];// 下下⼀个置⽅块为下⼀个manager->orientation[1] = manager->orientation[2];manager->type[2] = rand() % 7;// 随机⽣成下下⼀个⽅块manager->orientation[2] = rand() & 3;tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]]; // 当前⽅块// 设置当前⽅块y坐标,保证刚给出时只显⽰⽅块最下⾯⼀⾏// 这种实现使得玩家可以以很快的速度将⽅块落在不显⽰出来的顶部4⾏内if (tetris & 0xF000){manager->y = 0;}else{manager->y = (tetris & 0xFF00) ? 1 : 2;}manager->x = 6; // 设置当前⽅块x坐标if (checkCollision(manager)) // 检测到碰撞manager->dead = true; // 标记游戏结束}else // 未检测到碰撞{insertTetris(manager); // 将当前⽅块加⼊游戏池}++manager->tetrisTotal; // ⽅块总数++manager->tetrisCount[manager->type[0]]; // 相应⽅块数printNextTetris(manager); // 显⽰下⼀个⽅块printScore(manager); // 显⽰得分信息}// ============================================================================= // 碰撞检测bool checkCollision(const TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];uint16_t dest = 0;// 获取当前⽅块在游戏池中的区域:// 游戏池坐标x y处⼩⽅格信息,按低到⾼存放在16位⽆符号数中dest |= (((manager->pool[manager->y + 0] >> manager->x) << 0x0) & 0x000F);dest |= (((manager->pool[manager->y + 1] >> manager->x) << 0x4) & 0x00F0);dest |= (((manager->pool[manager->y + 2] >> manager->x) << 0x8) & 0x0F00);dest |= (((manager->pool[manager->y + 3] >> manager->x) << 0xC) & 0xF000);// 若当前⽅块与⽬标区域存在重叠(碰撞),则位与的结果不为0return ((dest & tetris) != 0);}// ============================================================================= // 插⼊⽅块void insertTetris(TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];// 当前⽅块每4位取出,位或到游戏池相应位置,即完成插⼊⽅块manager->pool[manager->y + 0] |= (((tetris >> 0x0) & 0x000F) << manager->x);manager->pool[manager->y + 1] |= (((tetris >> 0x4) & 0x000F) << manager->x);manager->pool[manager->y + 2] |= (((tetris >> 0x8) & 0x000F) << manager->x);manager->pool[manager->y + 3] |= (((tetris >> 0xC) & 0x000F) << manager->x);}// ============================================================================= // 移除⽅块void removeTetris(TetrisManager *manager){// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];// 当前⽅块每4位取出,按位取反后位与到游戏池相应位置,即完成移除⽅块manager->pool[manager->y + 0] &= ~(((tetris >> 0x0) & 0x000F) << manager->x);manager->pool[manager->y + 1] &= ~(((tetris >> 0x4) & 0x000F) << manager->x);manager->pool[manager->y + 2] &= ~(((tetris >> 0x8) & 0x000F) << manager->x);manager->pool[manager->y + 3] &= ~(((tetris >> 0xC) & 0x000F) << manager->x);}// ============================================================================= // 设置颜⾊void setPoolColor(const TetrisManager *manager, TetrisControl *control){// 由于显⽰游戏池时,先要在游戏池⾥判断某⼀⽅格有⽅块才显⽰相应⽅格的颜⾊// 这⾥只作设置即可,没必要清除// 当移动⽅块或给⼀个⽅块时调⽤int8_t i, x, y;// 当前⽅块uint16_t tetris = gs_uTetrisTable[manager->type[0]][manager->orientation[0]];for (i = 0; i < 16; ++i)y = (i >> 2) + manager->y; // 待设置的列if (y > ROW_END) // 超过底部限制{break;}x = (i & 3) + manager->x; // 待设置的⾏if ((tetris >> i) & 1) // 检测的到⼩⽅格属于当前⽅块区域{control->color[y][x] = (manager->type[0] | 8); // 设置颜⾊}}}// ============================================================================= // 旋转⽅块void rotateTetris(TetrisManager *manager, TetrisControl *control){int8_t ori = manager->orientation[0]; // 记录原旋转状态removeTetris(manager); // 移⾛当前⽅块// 顺/逆时针旋转manager->orientation[0] = (control->clockwise) ? ((ori + 1) & 3) : ((ori + 3) & 3);if (checkCollision(manager)) // 检测到碰撞{manager->orientation[0] = ori; // 恢复为原旋转状态insertTetris(manager); // 放⼊当前⽅块。
#include <conio.h>#include <stdlib.h>#include<stdio.h>#include <windows.h>#include <mmsystem.h>#pragma comment(lib,"winmm.lib") //播放背景音乐的头文件#include "colorConsole.h"#include<time.h>#define SQUARE_COLOR BACKGROUD_BLUE|BACKGROUD_RED| BACKGROUD_INTENSITY //背景颜色#define SQUARE_COLOR FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY //方块的颜色#define up 72#define down 80#define left 75#define right 77#define esc 27#define MAPW 15 //地图的宽度#define MAPH 25 //地图的高度void initiate1();int * build(); //创建方块//初始化工作BOOL isavailable(int a[],int x,int y,int w,int h); //判定是否能放下void drawblocks(int a[],int w,int h,int x,int y,WORD wColors[],int nColors);void delete_cache(); //清除键盘缓冲区void revolve(int a[][4],int w,int h,int *x,int y); //转动方块void pro();void end();void delete_blocks(int *a,int w,int h,int x,int y);void gameover();void deletefull_line(int m[][MAPW],int row,int w,int h); //消除一行int dx=30,dy=5; //屏幕上的偏移量int score=0,level=0;int map[MAPH][MAPW];int a1[4][4]={{1},{1,1,1}};int a2[4][4]={{0,1},{1,1,1}};int a3[4][4]={{1,1},{0,1,1}};int a4[4][4]={{0,0,1},{1,1,1}};int a5[4][4]={{0,1,1},{1,1}};int a6[4][4]={{1,1,1,1}};int a7[4][4]={{1,1},{1,1}};int main(){HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_BLUE| FOREGROUND_GREEN|FOREGROUND_INTENSITY };while(1){sndPlaySound("Resource\\Just Dance.wav",SND_LOOP|SND_ASYNC);//用异步方式播放音乐,PlaySound函数在开始播放后立即返回system("CLS");int n=0;printf("目录\n1.开始游戏\n2.退出游戏\n\n\n");scanf("%d",&n);switch(n){case 1:system("CLS");textout(handle,22,6,wColors+2,1,"请选择游戏等级:");textout(handle,32,8,wColors+2,1,"1.初级");textout(handle,32,10,wColors+2,1,"2.中级");textout(handle,32,12,wColors+2,1,"3.高级");while(1){char choice;choice=_getch();if(choice=='1'){textout(handle,22,6,wColors+2,1,"开始游戏,初级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=0,score=0;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice=='2'){textout(handle,22,6,wColors+2,1,"开始游戏,中级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=2,score=20;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice=='3'){textout(handle,22,6,wColors+2,1,"开始游戏,高级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=4,score=40;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice!='1'&&choice!='2'&&choice!='3')continue;}pro();break;case 2:return 0;default:printf("错误,按键继续");while(!_kbhit());}}}void pro() //游戏主题{initiate1();int *b=NULL;b=build(); //创建方块int sign,blank,x,y;while(1){for(int i=0;i<4;i++) //复制方块for(int j=0;j<4;j++)if(a[i][j]=*(b+i*4+j)) blank=i;y=1-blank;x=4;delete_blocks(&a[0][0],4,4,16,10);b=build();HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_BLUE| FOREGROUND_GREEN|FOREGROUND_INTENSITY };drawblocks(b,4,4,16,10,wColors,1);wColors[0]=SQUARE_COLOR;drawblocks(&a[0][0],4,4,x,y,wColors,1);delete_cache();char string[5];wColors[0]=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,dx-10,8+dy,wColors,1,itoa(score,string,10));textout(handle,dx-10,14+dy,wColors,1,itoa(level,string,10));sign=1;while(sign){int delay=0,max_delay=100-10*level; //延迟量while(delay<max_delay){if(_kbhit()) //用if避免按住键使方块卡住{int draw=0;int key=_getch();switch (key){case up:delete_blocks(&a[0][0],4,4,x,y);revolve(a,4,4,&x,y);draw=1;break;case down:delay=max_delay;break;case left:if(isavailable(&a[0][0],x-1,y,4,4)){delete_blocks(&a[0][0],4,4,x,y);x--;draw=1;}break;case right:if(isavailable(&a[0][0],x+1,y,4,4)){delete_blocks(&a[0][0],4,4,x,y);x++;draw=1;}break;case 32://32 是空格键的ASCII码,按空格键暂停while(1){textout(handle,dx,-2+dy,wColors,1,"Press any key to continue");Sleep(200);textout(handle,dx,-2+dy,wColors,1,"");Sleep(200);if(_kbhit()){draw=1;break;}}break;case esc://按键退出游戏exit(EXIT_SUCCESS);}if(draw){HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};drawblocks(&a[0][0],4,4,x,y,wColors,1);draw=0;}}_sleep(5);delay++;}if(isavailable(&a[0][0],x,y+1,4,4)) //是否能下移{delete_blocks(&a[0][0],4,4,x,y);y++;HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};drawblocks(&a[0][0],4,4,x,y,wColors,1);}else{sign=0; //标记,使跳出while(sign) 循环,产生新方块if(y<=1){system("CLS");HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_RED| FOREGROUND_GREEN};textout(handle,4+dx,6+dy,wColors,1,"GAME OVER!!!");textout(handle,4+dx,8+dy,wColors,1,"分数:");textout(handle,10+dx,8+dy,wColors,1,itoa(score,string,10));textout(handle,4+dx,10+dy,wColors,1,"制作者:***");delete_cache();exit(EXIT_SUCCESS);} //是否结束for(int i=0;i<4;i++) //放下方块for(int j=0;j<4;j++)if(a[i][j]&&((i+y)<MAPH-1)&&((j+x)<MAPW-1))map[i+y][j+x]=a[i][j];int full,k=0;for( i=y;i<min(y+4,MAPH-1);i++){full=1;for(int j=1;j<14;j++)if(!map[i][j]) full=0;if(full) //消掉一行{deletefull_line(map,i,MAPW,MAPH);k++;score=score+k;level=min(score/10,9);}}}}}}void initiate1() //初始化{int i;for(i=0;i<25;i++){map[i][0]=-2;map[i][14]=-2;}for(i=0;i<15;i++){map[0][i]=-1;map[24][i]=-1;}map[0][0]=-3;map[0][14]=-3;map[24][0]=-3;map[24][14]=-3;HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_GREEN| FOREGROUND_BLUE|FOREGROUND_INTENSITY};textout(handle,dx-10,6+dy,wColors,1,"SCORE");textout(handle,dx-10,12+dy,wColors,1,"LEVEL");textout(handle,32+dx,8+dy,wColors,1,"NEXT");wColors[0]=FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY;drawblocks(&map[0][0],15,25,0,0,wColors,1);textout(handle,dx,dy,wColors,1,"◎═════════════◎");wColors[0]=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,dx+8,dy+5,wColors,1,"按任意键开始");wColors[0]=FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY ;textout(handle,dx+7,dy-3,wColors,1,"制作者:***");int x=_getch();srand(time(NULL));textout(handle,dx+8,dy+5,wColors,1," ");}int * build() //创建方块{int * a=NULL;int c=rand()%7;switch(c){case 0:a=&a1[0][0];break;case 1:a=&a2[0][0];break;case 2:a=&a3[0][0];break;case 3:a=&a4[0][0];break;case 4:a=&a5[0][0];break;case 5:a=&a6[0][0];break;case 6:a=&a7[0][0];break;}return a;}void drawblocks(int a[],int w,int h,int x,int y,WORD wColors[],int nColors) //画出方块{HANDLE handle;handle = initiate();int temp;for(int i=0;i<h;i++)for(int j=0;j<w;j++)if((temp=a[i*w+j])&&y+i>0){if(temp==-3){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"◎");_sleep(30);}else if(temp==-2){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"║");_sleep(30);}else if(temp==1)textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"◎");else if(temp==-1){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"═");_sleep(30);}}}void delete_cache() //清除缓冲区{while(_kbhit()){_getch();}}void delete_blocks(int *a,int w,int h,int x,int y) //覆盖方块{HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};for(int i=0;i<h;i++)for(int j=0;j<w;j++)if(a[i*w+j]&&i+y>0)textout(handle,2*(x+j)+dx,y+i+dy,wColors,1," ");}void revolve(int a[][4],int w,int h,int *x,int y) //转动方块{int b[4][4]={{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};int sign=0,line=0;for(int i=h-1;i>=0;i--){for(int j=0;j<w;j++)if(a[i][j]){b[j][line]=a[i][j];sign=1;}if(sign){line++;sign=0;}}for(i=0;i<4;i++)if(isavailable(&b[0][0],*x-i,y,w,h)){*x-=i;for(int k=0;k<h;k++)for(int j=0;j<w;j++)a[k][j]=b[k][j];break;}}void deletefull_line(int m[][MAPW],int row,int w,int h) //消除满行的方块{HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};textout(handle,2+dx,row+dy,wColors,1,"﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌");_sleep(100);int i;for(i=row;i>1;i--){delete_blocks(&m[i][1],MAPW-2,1,1,i);for(int j=1;j<MAPW-1;j++)m[i][j]=m[i-1][j];drawblocks(&m[i][1],MAPW-2,1,1,i,wColors,1);}for(i=1;i<MAPW-1;i++)m[1][i]=0;}BOOL isavailable(int a[],int x,int y,int w,int h){for(int i=max(y,1);i<y+h;i++)for(int j=x;j<x+w;j++)if(map[i][j]&&a[w*(i-y)+j-x])return 0;return 1;}第二个cpp:#include "colorConsole.h"HANDLE initiate(){HANDLE hOutput;hOutput = GetStdHandle(STD_OUTPUT_HANDLE);return hOutput;}BOOL textout(HANDLE hOutput,int x,int y,WORD wColors[],int nColors,LPTSTR lpszString) {DWORD cWritten;BOOL fSuccess;COORD coord;coord.X = x; // start at first cellcoord.Y = y; // of first rowfSuccess = WriteConsoleOutputCharacter(hOutput, // screen buffer handlelpszString, // pointer to source stringlstrlen(lpszString), // length of stringcoord, // first cell to write to&cWritten); // actual number writtenif (! fSuccess)cout<<"error:WriteConsoleOutputCharacter"<<endl;for (;fSuccess && coord.X < lstrlen(lpszString)+x; coord.X += nColors){fSuccess = WriteConsoleOutputAttribute(hOutput, // screen buffer handlewColors, // pointer to source stringnColors, // length of stringcoord, // first cell to write to&cWritten); // actual number written}if (! fSuccess)cout<<"error:WriteConsoleOutputAttribute"<<endl;return 0;}二很经典的游戏.简单又让人着迷.今天就用mfc来实现个自己的俄罗斯方块.运行截图如下:看起来还行吧..网上有很多版本的实现代码.但是看了几个都是用一个很大的数组记录这些下落的物体的形状.然后写一个很大的switch case来实现变形.感觉真麻烦.今天提出一个容易的实现方法.下面切入正题思路是这样的:一:随机生成物体二:控制1.变形围绕一个方块向右旋转90度.以变形2.左右下移动1>物体左右移动的时候不要过界.2>物体落定后.(1).设定它落下的位置.(2).看是否满了一行.满了一行消去(3).看是否方块垒到顶了.到了game over三:重复以上步骤约定:下落的会变形的那个小东东,我们叫物体Object (--!!.大家忍受下这个名字.我是想不出其他的名字了.)左侧那个物体在里面移动的区域叫游戏区域Block实现这个游戏的思路跟玩这个游戏一样简单...1,随机生成一个物体.2,响应键盘的输入,做左右下移动和变形3,物体落到底部,判断是否满一行,物块垒满一行消除之.垒到顶部game over但是实现起来貌似又不是那么简单了.首先看起来随机生成一个不同形状的物体就是挑战怎么在视图上画一个个的不同形状的物体呢?我们看下这个游戏.每个物体都是由更小的方块组成.这些基本的小方块没有什么不同,再看看这个二维的游戏界面,左边的游戏区域,一个个的小方块合在一起是否就是我们所熟悉的二维数组?假如我们把这个游戏区域映射到一个二维数组,当这个数组元素有物体占据的时候就在上面涂颜色,没有则涂背景色.不就实现了么?.好了可以定义游戏的区域的数据结构了.这个游戏中由于要画不同的颜色,因此数据结构可以如下定义:2struct tagBlock3{4bSet;5COLORREF color;6}block[18][10]; // 我们将这个游戏区域格式化为18*10 (row*col);那么画一个物体又该如何画呢?假如我们先用数组定义好物体的形状,然后移动变化,那就太麻烦了.可以看到这些物体都是更小的方块组成的.(我们用四个小方块组成一个大的物体).用四个小方块,通过相对位置的不同可以变化成各种各样的不同形状.我们最终是要在那个二维数组中画不同形状的物体.那么在画的时候就要直到当前的物体应该画到哪儿.假如我们对二维数组的每个元素再抽象出来一个数据结构.在这个数据结构中保存当前它在二维数组中的位置(行列值).那就容易多了.7typedef struct tagPane9int row; // 在block[18][10]的行10int col; // 列11}Pane;这是一个小方格的定义,那每个物体要四个小方格,于是12struct tagObject13{14Pane object[4];15COLORREF color; // 每个物体有自己的颜色16int t; // 对应于最上面的一个方块的行值row17int b; // 对应于最下面一个方块行值18int l; // 对应于最左面一个方块的列值col19int r; // 对应于最右面一个方块列值20};由于我们要在画一个当前的下落的物体和一个下次将出现的物体.因此定义两个物体的对象21tagObject Object,NextObject;每个物体都是有边界的(把四个小方格全部盛下的最小矩形边界),我们把这个物体的四个小方块当前在block中的行列值,记录下来作为边界,放置在 tblr中.下面很多地方是用到这几个值的我们规定每个小方块的实际大小是 (24*24)像素那这个游戏区域实际上就是 height = 18*24 ,width = 10*24大小的矩形内(要注意数组的行列和矩形宽高的对应,col 对应的是width, row 对应的是height)22// 定义方格大小和游戏区域的矩形23const int PANE_WIDTH = 24; // 每个方格大小时24 * 24 pixel24const CRect BLOCK_RECT = CRect(29,31,271,463); // 游戏区域矩形现在的问题是,你怎么知道具体应该在视图的哪个地方画这些小方块呢?太简单了.我们可以由行列值(row,col)立即得到它在视图中所对应的矩形区域CRect(col*PANE_WIDTH,row*PANE_WIDTH,(col+1)*PANE_WIDTH,(row+1)*PANE_WIDTH); 假如我们要画一个物体,物体的四个方块的行列值都知道的.比如是在二维数组中(<0,0> <0,1> <1,0> <1,1>) 那<0,0>对应的视图的坐标矩形是(0,0,24,24)<0,1> -----(24,0,48,24)....自己那么对比几下就明白了.可以写一个函数专门获取小方块对应的实际视图中的矩形区域(实际上,我们的游戏区域不是从视图的0,0开始画的,而是上和左都有空白,左边空白LEFT_MARGIN个像素,上边空白是TOP_MARGIN个像素,因此是以(LEFT_MARGIN,TOP_MARGIN)点处作为游戏区域的左上角 .方块的长和宽相等,定义为PANE_WIDTH = 24)25// 根据坐标取得客户区矩形26CRect CRBlock::GetPaneRect(int row, int col)27{28if (row < 0 || col < 0)29{30return CRect(0,0,0,0);32returnCRect(col*PANE_WIDTH+LEFT_MARGIN,row*PANE_WIDTH+TOP_MARGIN,33(col+1)*PANE_WIDTH+LEFT_MARGIN,(row+1)*PANE_WIDTH+TOP_MARGIN);34}35//为方便.给出另一个重载的版本36// 由Pane的坐标取得对应的客户区的矩形37CRect CRBlock::GetPaneRect(Pane *p)38{39return GetPaneRect(p->row,p->col);40}现在再绘制一个物体还难么???张飞吃豆芽.!41#define RANDOM_COLOR RGB(rand()%256,rand()%256,rand()%256)42// 绘制当前下落的物体43void CRBlock::DrawFallingObject(CDC *pDC)44{45CBrush brush(Object.color);46CBrush brBorder(RANDOM_COLOR);47CBrush *pOld = pDC->SelectObject(&brush);48for (int i = 0; i < 4; i++)49{50CRect rc = GetPaneRect(&(Object.object[i]));51if (!rc.IsRectNull()) //这个组成物体的小方块还未出现在游戏区域内52{53pDC->Rectangle(&rc);54pDC->FrameRect(&rc,&brBorder); // 绘制边界,看起来会漂亮点哦.55}56}57pDC->SelectObject(pOld);58}咦.郁闷了...吃豆芽的时候遇到点problem.....需要绘制下一个将出现的物体.这个物体不是绘制在游戏区域内的.而是在游戏区域的右侧.没关系.假如我们在游戏区域和这下个物体绘制的区域之间隔一个方块的宽度.所有的问题都又解决了,原来的函数还照样可以用......继续吃豆芽59const CRect RECT_NEXTOBJECT = CRect(294,30,438,174); // 在这个矩形局域画下一个物体4*6 *PANE_WIDTH 大小60//294 = LEFT_MARGIN + 10 * PANE_WIDTH + 1*PANE_WIDTH;61现在这个4*6的区域的左上角,即是第一个方格的列坐标就是10+1 = 11 了.至于行坐标,由于这个区域是和原来的游戏区域上对齐的,所以依然是0;62// 绘制下一个将出现的物体63void CRBlock::DrawNextObject(CDC *pDC)64{65int l = NextObject.l;66int t = NextObject.t;67int r = NextObject.r;68int b = NextObject.b;6970// 把NextObject 的行列映射到要画在的矩形中71int offsetRow = (0+(6-(b-t+1))/2)-t; /// 这只是要把物体画到这个区域的中心72int offsetCol = (11+(6-(r-l+1))/2)-l; //7374// 这一段只是美化75CBrush brBkgnd(COLOR_BKGND);76CBrush *pOld = pDC->SelectObject(&brBkgnd);77CPen pen;78pen.CreatePen(PS_SOLID,1,RANDOM_COLOR);79CPen *pOldPen = pDC->SelectObject(&pen);80pDC->Rectangle(&RECT_NEXTOBJECT);81pDC->SelectObject(pOldPen);82pDC->SelectObject(pOld);8384CBrush brush(NextObject.color);85CBrush brBorder(RANDOM_COLOR);86pDC->SelectObject(&brush);87// 画下一个物体88for (int i = 0; i < 4; i++)89{90int row = NextObject.object[i].row;91int col = NextObject.object[i].col;92CRect rc = GetPaneRect(row+offsetRow,col+offsetCol);93if (!rc.IsRectNull())94{95pDC->Rectangle(&rc);96pDC->FrameRect(&rc,&brBorder);97}98}99}1>生成物体大家想的都过于复杂了.生成物体只是为几个小方块生成几个行列值,当然这个行列值不是随意的.而是有限制的.假如我们让第一个方块的行列值为 <-1,4> 然后依据这个方块在它的上下左右四个方向随机生成第二个方块,然后再根据第二个生成第三....根据第三个生成第四个.每个方块都是上一个方块的上下左右四个方向中非上一个方块的地方,那这个生成的物体正是我们要的!!!不信在纸上画一下! 根据这个思路进行改变.可以生成任何你要的形状!! 但是这样生成的却没有 T 形状的...(下面给出的是可以生成这个形状的代码)知道了上一个方块的位置,我们只要一个相对于上一个方块位置的偏移就好了(0,1) ---- 右(-1,0) ---- 上(1,0) ---- 下(0,-1) -- 左我们随机在这四个偏移量中拿出一个,生成下一个物体,但是又不能和上一个物体重叠 ,其实这次生成的偏移量不等于上一次生成偏移量的取反就满足要求.(在纸上画一下.任何时候你在纸上画画都能很快想明白一些问题,有时会得到不同的灵感)1// 随机的产生物体2void CRBlock::GenerateObject(struct tagObject &obj)3{4obj.object[0].row = obj.object[3].row = -1;5obj.object[0].col = obj.object[3].col = 4;6int x = -2,y = -2; // x,y 为偏移量7for (int c = 1; c <= 2; c++)8{9MakeRandomOffset(x,y); // 每次产生的位移不能是上一个方块的位置10obj.object[c].row = obj.object[c-1].row + x;11obj.object[c].col = obj.object[c-1].col + y;12x=-x,y=-y; // 上次生成的偏移量的取反13}14UpdateLimit(obj);15MakeRandomOffset(x,y);16/// 这个只是为了要得到一个T 形状的物体而做的.否则把下面的代码写到上面的循环中就完成任务了17if (obj.r-obj.l == 2 || obj.b-obj.t == 2)18{19obj.object[c].row = obj.object[1].row + x;20obj.object[c].col = obj.object[1].col + y;21}22else23{24obj.object[c].row = obj.object[2].row + x;25obj.object[c].col = obj.object[2].col + y;26}27obj.color = RANDOM_COLOR;28UpdateLimit(obj);29}3031// 随即产生一个偏移量.这个偏移量不能是参数x和y相同的32// 随即值只有4种可取,即是x和y的绝对值不相同的.(0,0) (+-1,+-1) 的偏移都是不合法的.33void CRBlock::MakeRandomOffset(int &offsetX, int &offsetY)34{35static const int offset[] = {-1,0, 1,0, 0,-1, 0,1};36int oldX = offsetX;37int oldY = offsetY;38do39{40int _i = (rand()%4)*2;41offsetX = offset[_i];42offsetY = offset[_i+1];43} while (offsetX == oldX && offsetY == offsetY);44}4546上面有一个函数还没有定义下面就是:4748// 更新物体的上下左右边界49// 左和上取最小50// 右和下取最大51void CRBlock::UpdateLimit(struct tagObject &obj)52{53obj.l = obj.object[0].col;54obj.r = obj.object[0].col;55obj.t = obj.object[0].row;56obj.b = obj.object[0].row;57for (int i = 1; i <= 3; i++)58{59if (obj.l > obj.object[i].col)60{61obj.l = obj.object[i].col;62}63if (obj.r < obj.object[i].col)64{65obj.r = obj.object[i].col;66}67if (obj.t > obj.object[i].row)68{69obj.t = obj.object[i].row;70}71if (obj.b < obj.object[i].row)72{73obj.b = obj.object[i].row;74}75}76}假如你不想要这样的形状,你可以调整生成的四个小方块的相对位置.就这样简单几步你就可以生成任何你想要的形状.爽否?三>变形上面是吃豆芽,下面就是啃骨头了.这是本程序的第二个难点真的那么难么?你认为变形会如何解决?说出来真让人失望.但又不得不说.这个骨头如此的脆弱,以至于当初摩拳擦掌准备下一翻苦功夫,栽几个大跟头的决心后备都用不上了,像是下了老劲而一拳打在了棉花上.用钱钟书在<围城>里形容李梓梅见到"情敌"方鸿渐的时候的话说:这是快意的失望!(最近在看<围城>,钱钟书真是人才.写的书太好了.)假如我们先找出这四个小方块最中间的一个,让它保持位置不变.而让其余的三个方块围着他向右做90度的旋转.是不是就是变形了?估计有人在这个时候该骂 "他妈的" 了...我当时就是.在纸上坐标啊.角啊,余弦啊,比划了半天.结果就是这样就变形了. 真 "他妈的".但是我想用三角函数和角在一个 x轴向右为正方向,y轴向下为正方向的坐标象限内(二维数组的逻辑)进行变形.就只是套用几个三角函数的公式就能完成了.这样程序将会简洁许多了.谁数学好,可以做一下,做好别忘了告诉我啊.(恨当初不该花那么多的时间跑出去玩通宵,数学没学好,真是后悔的我肠子都青了.童鞋们引以为戒).现在是0点48分.每这个时候大脑都会脱离我的精神独立控制四肢,因此废话多了些.说话意识流了点儿.不要介意.--!!下面是变形的代码:变形的过程中要注意的事情是:变形后不能覆盖住原来已经存在的方块位置.不能超出游戏区域边界.因此一旦变形失败就重建到原来的状态.77// 方块变形78// 变形的实现步骤:79// 找出4个方块的中心方块..80// 其他3个方块围绕这个方块向右旋转90度.81// 其他3个方块相对于这个中心方块的位置只可能时8中情况,82// 即是它的八个方向(包括对角线上的和水平垂直)83// 这个算法对物体变形的同时可能会造成物体左移,因此规定连续两次变形就右移一列84void CRBlock::Transform()85{86// 假如变形后失败,则重建到原来状态87struct tagObject objTemp = Object;88// 以(row,col)为中心旋转89int l = Object.l;90int ri = Object.r;91int t = Object.t;92int b = Object.b;93if (ri-l == b-t) // 正方形方块不变形,这个判断依据是,只有正方形的长和宽是相等的94{95return;96}97const int r = (t + b)/2;98const int c = (l + ri)/2;99// 变形实现,对4个小方块依次判断重新设定位置100 for (int i = 0; i < 4; i++)101 {102103 int &row = Object.object[i].row;104 int &col = Object.object[i].col;105 if ( row== r && col == c) // 中心方块不旋转106 continue;107 int offsetX = col - c;108 int offsetY = row - r;109 // 分八种情况分别变化110 if (offsetX > 0) // 在中心方块右边111 {112 if (offsetY == 0) // 正右方113 { // 到正下方114 row = r + offsetX;115 col = c;116 }117 else if (offsetY > 0) // 在右下方118 { // 到左下方119 col = c - offsetX;120 }121 else // 右上方122 { // 到右下方123 // 列不变124 row = r - offsetY;125 }126 }127 else if (offsetX == 0) // 和中心点在同一列,offsetY有正负号,恰好可以写成一个式子128 {129 row = r;130 col = c - offsetY;131 }132 else // 在中心方块左边133 {134 if (offsetY > 0) // 左下135 {// 到左上136 //列不变137 row = r - offsetY;138 }139 else if (offsetY == 0)// 正左方140 {// 到正上方141 row = r + offsetX;142 col = c;143 }144 else // 左上145 {// 到右上146 // 行不变147 col = c - offsetX;148 }149 }150 if (col < 0 || col >= 10 || (row > 0 && block[row][col].bSet)) // 变形失败151 {152 Object = objTemp;153 return;154 }155 }156 UpdateLimit(Object); // 更新方块的边界157 if (m_nTimesTransform == 2) // 连续变形了两次158 {159 Move(RIGHT); // 右移一个单位160 m_nTimesTransform = 0;161 }162 }3> 控制控制程序比控制我自己的意识要容易多了. 响应键盘的上下左右键就万事大吉enum {TRANSFORM = 0,DOWN = 2,LEFT = -1,RIGHT = 1,FASTTOBOTOOM = 3};先定义好变形和移动代码,在switch case中用到.FASTTOBOTOOM = 3 是什么意思咧? 先它是说不要一格一格的移动而要立即落到底部滴干活.每按一下向下的方向键它就下移动一行,但是要按空格键它就会立即下落到底部了.(对急性子和需要炫耀自己反应灵敏的人来说这个定义尤其爽!我属于有时候会炫耀自己反应敏捷的急性子的人!每次按空格键浑身都舒畅无比)....需要很多代码么?不需要.需要的是一点编码技巧1// 移动2// 左右下3void CRBlock::Move(int to)4{5int i;6switch (to)7{8case TRANSFORM: // 方向键向上是变形9m_nTimesTransform++; // 连续变形的次数10Transform();11break;12case LEFT:13case RIGHT:14if (IsBorder(to)) // 到最左或最右边或者物体下面有物体阻挡15{16return;17}18for (i = 0; i < 4; i++)19{20Object.object[i].col += to;21}22Object.r += to;23Object.l += to;24break;25case DOWN: // 一行26MoveDown(FALSE);27break;28case FASTTOBOTOOM: // 到底儿29MoveDown(TRUE);30break;31}32}技巧在这儿,do while 循环配合BOOL参数加上break.不需要额外的判断,顺溜的就向<梦想照进现实>中的那男人喝的好酒:冰爪子,从这儿下去到胃里成火线了.冰火两重天,你来试试!33// 向下移动bContinue 代表是一次到底还是移动一行34void CRBlock::MoveDown(BOOL bContinue)35{36do37{38if (IsBottom()) // 到底了39{40SetBlockFlag();41IsLineFull(); // 是否一行满?42if (Object.t < 0) // 组成当前物体的最上面的方块在游戏区域外43GameOver();44Object = NextObject;45GenerateObject(NextObject);// 产生下一个46m_nTimesTransform = 0; // 新产生的方块还未变形47break;48}49for (int i = 0; i < 4; i++)50{51Object.object[i].row += 1; // 方块下移一行52}53Object.b += 1; // 方块边界变了54Object.t += 1;55} while (bContinue);56}在移动物体的时候要注意的事项:1>不能过界吧2>不能覆盖已有物体吧57// 检测正在下落的物体下面是否已经存在物体了58// 或者到了最下面59BOOL CRBlock::IsBottom()60{61if (Object.b >= 17) // 游戏区域时10 * 18 转换到数组是9 17 ,9 是最右,17 是最下62{63return TRUE;64}65for (int c = 0; c < 4; c++) // 找出每一个物体的4个方块的位置然后判断66{67int i = Object.object[c].row;68int j = Object.object[c].col;69if ((i >= 0 && j >= 0) && block[i+1][j].bSet) // 此处已经有物体了70{71return TRUE;72}73}74return FALSE;75}物体落下后要干什么?当然是保存它落下的位置了?76// 检查现在在游戏区域中最上面的一个物体所在row (0 ~ 17)77// 在物体落下的位置标志为true.表示应该在这个地方画图形78void CRBlock::SetBlockFlag(BOOL bSet)79{80if (m_topLine > Object.t)81{82m_topLine = Object.t;83}84// 检测组成物体的4个方块的位置85for (int c = 0; c < 4; c++)86{87int i = Object.object[c].row;88int j = Object.object[c].col;89block[i][j].bSet = TRUE; // 设置此处已经被物体占据90block[i][j].color = Object.color;91}92}m_topLine 又是什么东东? 是当前垒的最高的物体所在二维数组的行值.这个值变成小于0 就算是game over了.....希望你垒的最后一块砖不是长条.....因为那样就像是囧到极点的老坟! ----- 装上了避雷针的埃及金字塔! <猜火车>中屎霸对马克说:That's fucking nightmare! 物体落下后光记录它落在的位置还不够,还得判断是否一行满了.93// 看一行是否满了,假如某一行都被标记为TRUE就时满了94BOOL CRBlock::IsLineFull()95{96int s = Object.t; // 最上97int topLine = m_topLine;98for (int e = Object.b; e >= s;) // e 和s都有被改变的可能99{100 int k = 0;101 for (k; k < 10; k++)102 {103 if (!block[e][k].bSet) // 未满104 {105 break;106 }107 }108 if (k == 10) // 满了就得删除这一行,并且自这行向上的行都要下移一行109 {110 for (int i = e; i >= m_topLine; i--)111 {112 for (int j = 0; j < 10; j++)113 {114 block[i][j].bSet = block[i-1][j].bSet;115 }116 }117 for (i = 0; i < 10; i++)118 {119 block[m_topLine][i].bSet = FALSE;120 }121 m_score += 100;122 m_topLine++; // 删除一行,则最高行向下移动一行123 s++; // Object所占的位置最上的一行要下移一行124 }125 else // 没有满126 {127 e--; // 则从object所占的位置行自下向上依次检测128 }129 }130 return FALSE; 131 }。
五子棋#include <stdio.h>#include <bios.h>#include <ctype.h>#include <conio.h>#include <dos.h>#define CROSSRU 0xbf /*右上角点*/#define CROSSLU 0xda /*左上角点*/#define CROSSLD 0xc0 /*左下角点*/#define CROSSRD 0xd9 /*右下角点*/#define CROSSL 0xc3 /*左边*/#define CROSSR 0xb4 /*右边*/#define CROSSU 0xc2 /*上边*/#define CROSSD 0xc1 /*下边*/#define CROSS 0xc5 /*十字交叉点*//*定义棋盘左上角点在屏幕上的位置*/#define MAPXOFT 5#define MAPYOFT 2/*定义1号玩家的操作键键码*/#define PLAY1UP 0x1157/*上移--'W'*/#define PLAY1DOWN 0x1f53/*下移--'S'*/#define PLAY1LEFT 0x1e41/*左移--'A'*/#define PLAY1RIGHT 0x2044/*右移--'D'*/#define PLAY1DO 0x3920/*落子--空格键*//*定义2号玩家的操作键键码*/#define PLAY2UP 0x4800/*上移--方向键up*/#define PLAY2DOWN 0x5000/*下移--方向键down*/ #define PLAY2LEFT 0x4b00/*左移--方向键left*/#define PLAY2RIGHT 0x4d00/*右移--方向键right*/ #define PLAY2DO 0x1c0d/*落子--回车键Enter*//*若想在游戏中途退出, 可按Esc 键*/#define ESCAPE 0x011b/*定义棋盘上交叉点的状态, 即该点有无棋子*//*若有棋子, 还应能指出是哪个玩家的棋子*/#define CHESSNULL 0 /*没有棋子*/#define CHESS1 'O'/*一号玩家的棋子*/#define CHESS2 'X'/*二号玩家的棋子*//*定义按键类别*/#define KEYEXIT 0/*退出键*/#define KEYFALLCHESS 1/*落子键*/#define KEYMOVECURSOR 2/*光标移动键*/#define KEYINV ALID 3/*无效键*//*定义符号常量: 真, 假--- 真为1, 假为0 */#define TRUE 1#define FALSE 0/**********************************************************/ /* 定义数据结构*//*棋盘交叉点坐标的数据结构*/struct point{int x,y;};/**********************************************************/ /*自定义函数原型说明*/void Init(void);int GetKey(void);int CheckKey(int press);int ChangeOrder(void);int ChessGo(int Order,struct point Cursor);void DoError(void);void DoOK(void);void DoWin(int Order);void MoveCursor(int Order,int press);void DrawCross(int x,int y);void DrawMap(void);int JudgeWin(int Order,struct point Cursor);int JudgeWinLine(int Order,struct point Cursor,int direction);void ShowOrderMsg(int Order);void EndGame(void);/**********************************************************//**********************************************************/ /* 定义全局变量*/int gPlayOrder; /*指示当前行棋方*/struct point gCursor; /*光标在棋盘上的位置*/char gChessBoard[19][19];/*用于记录棋盘上各点的状态*//**********************************************************//**********************************************************/ /*主函数*/void main(){int press;int bOutWhile=FALSE;/*退出循环标志*/printf("Welcome ");Init();/*初始化图象,数据*/while(1){press=GetKey();/*获取用户的按键值*/switch(CheckKey(press))/*判断按键类别*/{/*是退出键*/case KEYEXIT:clrscr();/*清屏*/bOutWhile = TRUE;break;/*是落子键*/case KEYFALLCHESS:if(ChessGo(gPlayOrder,gCursor)==FALSE)/*走棋*/DoError();/*落子错误*/else{DoOK();/*落子正确*//*如果当前行棋方赢棋*/if(JudgeWin(gPlayOrder,gCursor)==TRUE){DoWin(gPlayOrder);bOutWhile = TRUE;/*退出循环标志置为真*/}/*否则*/else/*交换行棋方*/ChangeOrder();ShowOrderMsg(gPlayOrder);}break;/*是光标移动键*/case KEYMOVECURSOR:MoveCursor(gPlayOrder,press);break;/*是无效键*/case KEYINV ALID:break;}if(bOutWhile==TRUE)break;}/*游戏结束*/EndGame();}/**********************************************************//*界面初始化,数据初始化*/void Init(void){int i,j;char *Msg[]={"Player1 key:"," UP----w"," DOWN--s"," LEFT--a"," RIGHT-d"," DO----space","","Player2 key:"," UP----up"," DOWN--down"," LEFT--left"," RIGHT-right"," DO----ENTER","","exit game:"," ESC",NULL,/* 先手方为1号玩家*/gPlayOrder = CHESS1;/* 棋盘数据清零, 即棋盘上各点开始的时候都没有棋子*/ for(i=0;i<19;i++)for(j=0;j<19;j++)gChessBoard[i][j]=CHESSNULL;/*光标初始位置*/gCursor.x=gCursor.y=0;/*画棋盘*/textmode(C40);DrawMap();/*显示操作键说明*/i=0;textcolor(BROWN);while(Msg[i]!=NULL){gotoxy(25,3+i);cputs(Msg[i]);i++;}/*显示当前行棋方*/ShowOrderMsg(gPlayOrder);/*光标移至棋盘的左上角点处*/gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT);}/*画棋盘*/void DrawMap(void){int i,j;clrscr();for(i=0;i<19;i++)for(j=0;j<19;j++)DrawCross(i,j);}/*画棋盘上的交叉点*/void DrawCross(int x,int y){gotoxy(x+MAPXOFT,y+MAPYOFT); /*交叉点上是一号玩家的棋子*/if(gChessBoard[x][y]==CHESS1) {textcolor(LIGHTBLUE);putch(CHESS1);return;}/*交叉点上是二号玩家的棋子*/if(gChessBoard[x][y]==CHESS2) {textcolor(LIGHTBLUE);putch(CHESS2);return;}textcolor(GREEN);/*左上角交叉点*/if(x==0&&y==0){putch(CROSSLU);return;}/*左下角交叉点*/if(x==0&&y==18){putch(CROSSLD);return;}/*右上角交叉点*/if(x==18&&y==0){putch(CROSSRU);return;}/*右下角交叉点*/if(x==18&&y==18){putch(CROSSRD); return;}/*左边界交叉点*/if(x==0){putch(CROSSL); return;}/*右边界交叉点*/if(x==18){putch(CROSSR); return;}/*上边界交叉点*/if(y==0){putch(CROSSU); return;}/*下边界交叉点*/if(y==18){putch(CROSSD); return;}/*棋盘中间的交叉点*/ putch(CROSS);}/*交换行棋方*/int ChangeOrder(void) {if(gPlayOrder==CHESS1) gPlayOrder=CHESS2; elsegPlayOrder=CHESS1;return(gPlayOrder);}/*获取按键值*/int GetKey(void){char lowbyte;int press;while (bioskey(1) == 0);/*如果用户没有按键,空循环*/press=bioskey(0);lowbyte=press&0xff;press=press&0xff00 + toupper(lowbyte); return(press);}/*落子错误处理*/void DoError(void){sound(1200);delay(50);nosound();}/*赢棋处理*/void DoWin(int Order){sound(1500);delay(100);sound(0); delay(50);sound(800); delay(100);sound(0); delay(50);sound(1500);delay(100);sound(0); delay(50);sound(800); delay(100);sound(0); delay(50);nosound();textcolor(RED+BLINK);gotoxy(25,20);if(Order==CHESS1)cputs("PLAYER1 WIN!");elsecputs("PLAYER2 WIN!");gotoxy(25,21);cputs(" \\<^+^>/");getch();}/*走棋*/int ChessGo(int Order,struct point Cursor){/*判断交叉点上有无棋子*/if(gChessBoard[Cursor.x][Cursor.y]==CHESSNULL){/*若没有棋子, 则可以落子*/gotoxy(Cursor.x+MAPXOFT,Cursor.y+MAPYOFT); textcolor(LIGHTBLUE);putch(Order);gotoxy(Cursor.x+MAPXOFT,Cursor.y+MAPYOFT); gChessBoard[Cursor.x][Cursor.y]=Order;return TRUE;}elsereturn FALSE;}/*判断当前行棋方落子后是否赢棋*/int JudgeWin(int Order,struct point Cursor){int i;for(i=0;i<4;i++)/*判断在指定方向上是否有连续5个行棋方的棋子*/if(JudgeWinLine(Order,Cursor,i))return TRUE;return FALSE;}/*判断在指定方向上是否有连续5个行棋方的棋子*/int JudgeWinLine(int Order,struct point Cursor,int direction) {int i;struct point pos,dpos;const int testnum = 5;int count;switch(direction){case 0:/*在水平方向*/pos.x=Cursor.x-(testnum-1);pos.y=Cursor.y;dpos.x=1;dpos.y=0;break;case 1:/*在垂直方向*/pos.x=Cursor.x;pos.y=Cursor.y-(testnum-1);dpos.x=0;dpos.y=1;break;case 2:/*在左下至右上的斜方向*/pos.x=Cursor.x-(testnum-1);pos.y=Cursor.y+(testnum-1);dpos.x=1;dpos.y=-1;break;case 3:/*在左上至右下的斜方向*/pos.x=Cursor.x-(testnum-1);pos.y=Cursor.y-(testnum-1);dpos.x=1;dpos.y=1;break;}count=0;for(i=0;i<testnum*2+1;i++)/*????????i<testnum*2-1*/ {if(pos.x>=0&&pos.x<=18&&pos.y>=0&&pos.y<=18) {if(gChessBoard[pos.x][pos.y]==Order){count++;if(count>=testnum)return TRUE;}elsecount=0;}pos.x+=dpos.x;pos.y+=dpos.y;}return FALSE;}/*移动光标*/void MoveCursor(int Order,int press) {switch(press){case PLAY1UP:if(Order==CHESS1&&gCursor.y>0) gCursor.y--;break;case PLAY1DOWN:if(Order==CHESS1&&gCursor.y<18) gCursor.y++;break;case PLAY1LEFT:if(Order==CHESS1&&gCursor.x>0) gCursor.x--;break;case PLAY1RIGHT:if(Order==CHESS1&&gCursor.x<18) gCursor.x++;break;case PLAY2UP:if(Order==CHESS2&&gCursor.y>0) gCursor.y--;break;case PLAY2DOWN:if(Order==CHESS2&&gCursor.y<18) gCursor.y++;break;case PLAY2LEFT:if(Order==CHESS2&&gCursor.x>0) gCursor.x--;break;case PLAY2RIGHT:if(Order==CHESS2&&gCursor.x<18) gCursor.x++;break;}gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT); }/*游戏结束处理*/void EndGame(void){textmode(C80);}/*显示当前行棋方*/void ShowOrderMsg(int Order){gotoxy(6,MAPYOFT+20);textcolor(LIGHTRED);if(Order==CHESS1)cputs("Player1 go!");elsecputs("Player2 go!");gotoxy(gCursor.x+MAPXOFT,gCursor.y+MAPYOFT); }/*落子正确处理*/void DoOK(void){sound(500);delay(70);sound(600);delay(50);sound(1000);delay(100);nosound();}/*检查用户的按键类别*/int CheckKey(int press){if(press==ESCAPE)return KEYEXIT;/*是退出键*/elseif( ( press==PLAY1DO && gPlayOrder==CHESS1) || ( press==PLAY2DO && gPlayOrder==CHESS2))return KEYFALLCHESS;/*是落子键*/elseif( press==PLAY1UP || press==PLAY1DOWN || press==PLAY1LEFT || press==PLAY1RIGHT || press==PLAY2UP || press==PLAY2DOWN ||press==PLAY2LEFT || press==PLAY2RIGHT)return KEYMOVECURSOR;/*是光标移动键*/elsereturn KEYINV ALID;/*按键无效*/}贪吃蛇#define N 200#include <graphics.h>#include <stdlib.h>#include <dos.h>#define LEFT 0x4b00#define RIGHT 0x4d00#define DOWN 0x5000#define UP 0x4800#define ESC 0x011bint i,key;int score=0;/*得分*/int gamespeed=50000;/*游戏速度自己调整*/ struct Food{int x;/*食物的横坐标*/int y;/*食物的纵坐标*/int yes;/*判断是否要出现食物的变量*/ }food;/*食物的结构体*/struct Snake{int x[N];int y[N];int node;/*蛇的节数*/int direction;/*蛇移动方向*/int life;/* 蛇的生命,0活着,1死亡*/}snake;void Init(void);/*图形驱动*/void Close(void);/*图形结束*/void DrawK(void);/*开始画面*/void GameOver(void);/*结束游戏*/void GamePlay(void);/*玩游戏具体过程*/void PrScore(void);/*输出成绩*//*主函数*/void main(void){Init();/*图形驱动*/DrawK();/*开始画面*/GamePlay();/*玩游戏具体过程*/Close();/*图形结束*/}/*图形驱动*/void Init(void){int gd=DETECT,gm;initgraph(&gd,&gm,"c:\\tc");cleardevice();}/*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/ void DrawK(void){/*setbkcolor(LIGHTGREEN);*/setcolor(11);setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/for(i=50;i<=600;i+=10)/*画围墙*/{rectangle(i,40,i+10,49); /*上边*/rectangle(i,451,i+10,460);/*下边*/}for(i=40;i<=450;i+=10){rectangle(50,i,59,i+10); /*左边*/rectangle(601,i,610,i+10);/*右边*/}}/*玩游戏具体过程*/void GamePlay(void){randomize();/*随机数发生器*/food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/snake.life=0;/*活着*/snake.direction=1;/*方向往右*/snake.x[0]=100;snake.y[0]=100;/*蛇头*/snake.x[1]=110;snake.y[1]=100;snake.node=2;/*节数*/PrScore();/*输出得分*/while(1)/*可以重复玩游戏,压ESC键结束*/{while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/{if(food.yes==1)/*需要出现新食物*/{food.x=rand()%400+60;food.y=rand()%350+60;while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/ food.x++;while(food.y%10!=0)food.y++;food.yes=0;/*画面上有食物了*/}if(food.yes==0)/*画面上有食物了就要显示*/{setcolor(GREEN);rectangle(food.x,food.y,food.x+10,food.y-10);}for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/{snake.x[i]=snake.x[i-1];snake.y[i]=snake.y[i-1];}/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/switch(snake.direction){case 1:snake.x[0]+=10;break;case 2: snake.x[0]-=10;break;case 3: snake.y[0]-=10;break;case 4: snake.y[0]+=10;break;}for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/{if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]){GameOver();/*显示失败*/snake.life=1;break;}}if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||snake.y[0]>455)/*蛇是否撞到墙壁*/{GameOver();/*本次游戏结束*/snake.life=1; /*蛇死*/}if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/ break;if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/{setcolor(0);/*把画面上的食物东西去掉*/rectangle(food.x,food.y,food.x+10,food.y-10);snake.x[snake.node]=-20;snake.y[snake.node]=-20;/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/snake.node++;/*蛇的身体长一节*/food.yes=1;/*画面上需要出现新的食物*/score+=10;PrScore();/*输出新得分*/}setcolor(4);/*画出蛇*/for(i=0;i<snake.node;i++)rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);delay(gamespeed);setcolor(0);/*用黑色去除蛇的的最后一节*/rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);} /*endwhile(!kbhit)*/if(snake.life==1)/*如果蛇死就跳出循环*/break;key=bioskey(0);/*接收按键*/if(key==ESC)/*按ESC键退出*/break;elseif(key==UP&&snake.direction!=4)/*判断是否往相反的方向移动*/snake.direction=3;elseif(key==RIGHT&&snake.direction!=2)snake.direction=1;elseif(key==LEFT&&snake.direction!=1)snake.direction=2;elseif(key==DOWN&&snake.direction!=3)snake.direction=4;}/*endwhile(1)*/}/*游戏结束*/void GameOver(void){cleardevice();PrScore();setcolor(RED);settextstyle(0,0,4);outtextxy(200,200,"GAME OVER");getch();}/*输出成绩*/void PrScore(void){char str[10];setfillstyle(SOLID_FILL,YELLOW);bar(50,15,220,35);setcolor(6);settextstyle(0,0,2);sprintf(str,"score:%d",score);outtextxy(55,20,str);}/*图形结束*/void Close(void){getch();closegraph();}扫雷游戏/*模拟扫雷游戏*/#include <graphics.h>#include <math.h>#include <stdio.h>#include <dos.h>#include <stdlib.h>#include <conio.h>#include <alloc.h>union REGS regs;int size=15;/*用于表示每个方块的大小(正方形的边长)*/int pix,piy=50;/*pix,piy是矩阵的偏移量*/char b[2]="1";/*用于显示方格周围的雷的个数*/int pan[30][16];/*用于记录盘面的情况:0:没有、9:有雷、1~8:周围雷的个数*/int pan1[30][16];/*pan1[][]纪录当前的挖雷情况,0:没有操作、1:打开了、2:标记了*/int tt;/*纪录时间参数*/int Eflags;/*用于标记鼠标按钮的有效性,0:有效,1:无效,2:这是鼠标的任意键等于重新开始*/int Msinit();void Draw(int x,int y,int sizex,int sizey);void Facedraw(int x,int y,int sizel,int k);void Dead(int sizel,int x,int y);void Setmouse(int xmax,int ymax,int x,int y);int Msread(int *xp,int *yp,int *bup,struct time t1,int k);void Draw1(int x,int y);int Open(int x,int y);float Random();void Have(int sum,int x,int y,int xx,int yy);void Help();void Coread();void Ddraw2(int x,int y);/*下面是主函数*/main(){int mode=VGAHI,devices=VGA;/*图形模式初始化的变量*/char ams; /*鼠标操作中的标志变量*/int xms,yms,bms; /*鼠标的状态变量*/int i,j,k,k1=0; /*i,j,k是循环变量*/int x=9,y=9,flags=0; /*x,y矩阵的大小*/int sum=10; /*sum 盘面的雷的总数目,是个x,y的函数*/int x1=0,y1=0; /*用于记录光标当前的位置*/int x11=0,y11=0; /*暂时保存鼠标位置的值*/int sizel=10; /*脸的大小*/int cflags=1; /*这是菜单操作标志变量,没有弹出1,弹出0*/struct time t1={0,0,0,0}; /*时间结构体,头文件已定义*/int co[3]; /*暂时纪录历史纪录*/void far *Map; /*用于保存鼠标图片*/char name[3][20]; /*名字字符串,用于记录名字*/FILE * p; /*文件指针用于文件操作*/Msinit(); /*鼠标初始化*//*registerbgidriver(EGA VGA_driver);*/initgraph(&devices,&mode,"C:\\tc"); /*图形模式初始化*//*为图片指针分配内存*/if((Map=farmalloc(imagesize(0,0,20,20)))==NULL)/*图片的大小是20*20*/{printf("Memory ererr!\n");printf("Press any key to out!\n");exit(1);}/*用于检验文件是否完整*/while((p = fopen("score.dat", "r")) == NULL) /*如果不能打开就新建一个*/{if((p = fopen("score.dat", "w")) == NULL)/*如果不能新建就提示错误并推出*/{printf("The file cannot open!\n");printf("Presss any key to exit!\n");getch();exit(1);}/*写入初始内容*/fprintf(p,"%d %d %d,%s\n%s\n%s\n",999,999,999,"xiajia","xiajia","xiajia");fclose(p);}/*暂时读出历史纪录。
C语⾔实现俄罗斯⽅块⼩游戏C语⾔实现俄罗斯⽅块⼩游戏的制作代码,具体内容如下#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define TTY_PATH "/dev/tty"#define STTY_ON "stty raw -echo -F"#define STTY_OFF "stty -raw echo -F"int map[21][14];char direct;int node[7][4][16]={{{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,1,0,0,0,1,0,0,0,1,0,0,0,1,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,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},//3边加⼀中点{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}},{{0,1,1,0,0,1,0,0,0,1,0,0,0,0,0,0},//右锄头型{0,0,0,0,1,1,1,0,0,0,1,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,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},{0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0},{0,0,0,0,1,1,1,0,1,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,1,1,0,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,1,1,0,0,0,0,0,0,0,0,0,0}},{{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0},//左曲折型{1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0},{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0},{1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}}};typedef struct block{int x;int y;int blockType;int blockDirect;}Block;Block bl;void init_map()//初始化边框{int i,j;for(i=0; i<21; i++)for(j=0; j<14; j++){if(j==0 || j==13)map[i][j] = 200;else if(i==20)map[i][j] = 201;elsemap[i][j] = 0;}}void new_block()//⽣成随机的俄罗斯⽅块{int blockType = rand()%7;int blockDirect = rand()%4;int x = 1;int y = 5;bl.x = x;bl.y = y;bl.blockType = blockType;bl.blockDirect = blockDirect;}void input()//将移动后的俄罗斯⽅块,导⼊地图中作标记{int i, j;for(i=0; i<4; i++)for(j=0; j<4; j++)if(node[bl.blockType][bl.blockDirect][i*4+j]==1){map[bl.x+i][bl.y+j] = 1;}}void output()//移动时,将之前俄罗斯⽅块在地图信息清空。
/*学无止境*/ #include <stdlib.h>#include <stdio.h>#include <graphics.h>#define ESC 27#define UP 328#define DOWN 336#define LEFT 331#define RIGHT 333#define BLANK 32#define BOTTOM 2#define CANNOT 1#define CAN 0#define MAX 30#define F1 315#define ADD 43#define EQUAL 61#define DEC 45#define SOUNDs 115#define SOUNDS 83#define PAUSEP 80#define PAUSEp 112void Init();void Down();void GoOn();void ksdown();void Display(int color);void Give();int Touch(int x,int y,int dx,int dy);int GeyKey();void Select();void DetectFill();void GetScores();void Fail();void Help();void Quit();void DrawBox(int x,int y,int Color);void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch);void DrawNext(int Color);int Heng=12,Shu=20; /*横竖*/int Position[MAX][MAX];int middle[MAX][MAX];int ActH,ActS;int Act,Staus;int i,j,k;int Wid=10;int NoPass=CAN;float Delays=15000;int BeginH=250,BeginS=7;float Seconds=0;int Scores=0;int flag=1;int Sounds=CAN;int PreAct,NextAct;int a[8][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}},{{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},{{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},{0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}}, {{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}; int b[4][4];main(int argc,char *argv[]){if (argc!=1){if (argv[1]!="")Heng=atoi(argv[1]);if (argv[2]!="")Shu=atoi(argv[2]);}Init(); /*初始化界面*/PreAct=random(8); /*取得当前的方块*/for(;;) /*以下是游戏流程*/{NextAct=random(8); /*取得下一个方块*/ DrawNext(1); /*画出下一个方块*/Act=PreAct;if (Heng%2==0) ActH=Heng/2;else ActH=(Heng-1)/2;ActS=0; /*方块开始从游戏空间的中间下落*/ Staus=0; /*取开始的状态*/NoPass=CAN; /*物体可以下落*/Give(); /*取得当前的方块*/Display(Act+1); /*显示当前的方块,每种方块的颜色不同*/ GoOn(); /*游戏的算法精髓所在*/PreAct=NextAct; /*方块下落完毕,取得下一个方块*/ DrawNext(0);}}void Init(){int GraphDriver=DETECT,GraphMode;registerbgidriver(EGAVGA_driver);initgraph(&GraphDriver,&GraphMode,"");if (kbhit()) Sounds=CANNOT;setcolor(1);OutTextXY(10,10,"Tetris");OutTextXY(30,30,"Version 2.0");OutTextXY(10,120,"Help:");OutTextXY(20,140,"+ :Faster");OutTextXY(20,160,"- :Slower");OutTextXY(20,180,"Esc :Quit");OutTextXY(20,200,"F1 :Help");OutTextXY(10,310,"Copyright(c) 1998.2.22"); OutTextXY(10,320,"By Mr. Unique");outtextxy(10,250,"Score: 00000");rectangle(BeginH-3,BeginS-3,BeginH+Heng*(Wid+2)+2,BeginS+Sh u*(Wid+2)+2);rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Sh u*(Wid+2)+4);rectangle(BeginH+(Heng+4)*(Wid+2)-2,BeginS+10,BeginH+(Heng+ 8)*(Wid+2)+2,BeginS+12+4*(Wid+2));for (i=0;i<MAX;i++)for (j=0;j<MAX;j++){Position[i][j]=1;middle[i][j]=-1;}for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)Position[i][j]=0;for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)DrawBox(i,j,0);randomize();}void GoOn(){for(;;){Seconds+=0.2; /*控制方块的下落速度*/ if (Seconds>=Delays){Down();Seconds=0;if (NoPass==BOTTOM){DetectFill();middle[ActH][ActS]=Act;if (ActS==0)Fail();return;}}if (kbhit())Select();}}void Down() /*方块下降*/{Display(0);if (Touch(ActH,ActS,0,1)==CAN)ActS++;elsemiddle[ActH][ActS]=Act;Display(Staus+1);}int Touch(int x,int y,int dx,int dy) {NoPass=CAN;for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+dx+i][y+dy+j]+=b[i][j]; for (i=0;i<MAX;i++)for (j=0;j<MAX;j++)if (Position[i][j]>1)NoPass=CANNOT;for (i=0;i<4;i++)for (j=0;j<4;j++){Position[x+dx+i][y+dy+j]-=b[i][j]; middle[x+dx+i][y+dy+j]=Act;}if (NoPass==CANNOT && dx==0 && dy==1) {for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+i][y+j]+=b[i][j];NoPass=BOTTOM;}return NoPass;}int GetKey(void){int Ch,Low,Hig;Ch=bioskey(0);Low=Ch&0x00ff;Hig=(Ch&0xff00)>>8;return(Low==0?Hig+256:Low);}void Select(){int OldStaus,acts=ActS;switch(GetKey()){case ESC :Quit();break;case DOWN :Seconds+=14500;break;case LEFT :Display(0);if (ActH>0 && Touch(ActH,ActS,-1,0)==CAN) { ActH--;}Display(Act+1);break;case RIGHT :Display(0);if (ActH<Heng && Touch(ActH,ActS,1,0)==CAN) { ActH++;}Display(Act+1);break;case BLANK : Display(0);ksdown();Display(Act+1);break;case F1 :Help();break;case EQUAL :case ADD :if (Delays>300) Delays-=100;break; case DEC :if (Delays<3000) Delays+=100;break; case PAUSEP :case PAUSEp :getch();break;case SOUNDS :case SOUNDs :if (Sounds==CAN)Sounds=CANNOT;elseSounds=CAN;break;case UP :if(Act==7){while(acts<Shu-1&&Position[ActH][acts]!=1)acts++;Position[ActH][acts]=0;DrawBox(ActH,acts,0);acts=ActS;break;}else{Display(0);OldStaus=Staus;switch(Act){case 0:case 3:case 4:if (Staus==1) Staus=0;else Staus=1;break;case 1:break;case 2:case 5:case 6:if (Staus==3) Staus=0;else Staus++;break; }Give();if (Touch(ActH,ActS,0,0)==CANNOT){Staus=OldStaus;Give();}Display(Act+1);break;}}}void ksdown(){while(flag){if(Touch(ActH,ActS,0,0)==CAN){ActS++;}else {ActS--;flag=0;}}flag=1;}void Quit(){int ch,TopScore;FILE *fp;if ((fp=fopen("Russian.scr","r+"))!=NULL) {fscanf(fp,"%d",&TopScore);if (Scores>TopScore){setcolor(1);outtextxy(470,80,"Hello !");outtextxy(470,100,"In all the players,"); outtextxy(470,120,"You are the First !"); outtextxy(470,140,"And your score will"); outtextxy(470,160,"be the NEW RECORD !"); fseek(fp,0L,0);fprintf(fp,"%d",Scores);fclose(fp);}setcolor(1);OutTextXY(470,220,"Are You Sure (Yes/no)?"); ch=getch();if (ch=='y'||ch=='Y'){closegraph();delay(20);exit(0);}setcolor(0);outtextxy(470,220,"Are You Sure (Yes/no)?"); }void OutTextXY(int x,int y,char *String) {int i=0;char a[2];moveto(x,y);a[1]='\0';while (*(String+i)!='\0')a[0]=*(String+i);outtext(a);if (Sounds==CAN && a[0]!=' ') {sound(3000);delay(50);nosound();}i++;}}void Help(){unsigned Save;void *Buf;Save=imagesize(160,120,500,360); Buf=malloc(Save);getimage(160,120,500,360,Buf); setfillstyle(1,1);bar(160,120,500,280);setcolor(0);OutTextXY(170,130," About & Help");OutTextXY(170,150," # # # ########## # # # "); OutTextXY(170,160," # ## # # # # # # ###### ### "); OutTextXY(170,170," ########## ########## ## # # "); OutTextXY(170,180," # # # # # # # ## #### "); OutTextXY(170,190," # ## # #### ## # # # "); OutTextXY(170,200," # ## # # # # # ## # # # "); OutTextXY(170,210," # # # ## ## # ###### # # # "); OutTextXY(170,220," ## # ## # ## # # # # "); OutTextXY(170,230," # ## # #### # ## # "); OutTextXY(170,260," Good Luckly to You ");getch();putimage(160,120,Buf,0);free(Buf);}void GetScores(){int Sec10000,Sec1000,Sec100,Sec10,Sec1;setfillstyle(0,1);bar(60,250,109,260);Sec1=Scores%10;Sec10=(Scores%100-Scores%10)/10;Sec100=(Scores%1000-Scores%100)/100;Sec1000=(Scores%10000-Scores%1000)/1000; Sec10000=(Scores%100000-Scores%10000)/10000; DispScore(60,250,'0'+Sec10000);DispScore(70,250,'0'+Sec1000);DispScore(80,250,'0'+Sec100);DispScore(90,250,'0'+Sec10);DispScore(100,250,'0'+Sec1);DispScore(110,250,'0');DispScore(120,250,'0');}void DispScore(int x,int y,char Ch){char a[2];a[1]='\0';a[0]=Ch;outtextxy(x,y,a);}void Give(){for (i=0;i<4;i++)for (j=0;j<4;j++)b[i][j]=a[Act][Staus][i][j];}void Display(int color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (b[i][j]==1) DrawBox(ActH+i,ActS+j,color); }void DrawBox(int x,int y,int Color){x=BeginH+x*(Wid+2);y=BeginS+y*(Wid+2);setfillstyle(1,Color);bar(x+2,y+2,x+Wid-1,y+Wid-1);if (Color==0)setcolor(9);elsesetcolor(Act+1);rectangle(x+4,y+4,x+Wid-4,y+Wid-4);}void DrawNext(int Color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (a[NextAct][0][i][j]==1) DrawBox(Heng+4+i,1+j,Color); }void DetectFill(){int Number,Fall,FallTime=0;for (i=Shu-1;i>=0;i--){Number=0;for (j=0;j<Heng;j++)if (Position[j][i]==1) Number++;if (Number==Heng){FallTime++;if (Sounds==CAN){sound(500);delay(500);nosound();}for (Fall=i;Fall>0;Fall--)for (j=0;j<Heng;j++){Position[j][Fall]=Position[j][Fall-1]; middle[j][Fall]=middle[j][Fall-1];if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,middle[j][Fall]+1);}i++;}}switch(FallTime){case 0:break;case 1:Scores+=1;break;case 2:Scores+=3;break;case 3:Scores+=6;break;case 4:Scores+=10;break;}if (FallTime!=0){GetScores();if (Scores%100==0) Delays-=100;}}void Fail(){if (Sounds==CAN){for (k=0;k<3;k++){sound(300);delay(200);nosound();}}setcolor(1);OutTextXY(440,200,"Game over!"); Quit();closegraph();exit(0);}。
#include <>#include <>#include <>#include <>#include <ctime>#include "" //老师的文件void begin(); //开始游戏void frame(); //边框设定int * getblocks(); //方块产生void move(int line); //移动void drawblocks(int line); //方块显示void clearsquare(int line); //方块擦出void turn(int line); //方块旋转bool isavailable(int line); //判断是否能下落void remember(int line); //记忆方块位置void deleteline(int line); //方块满一行消除bool ifgameover(); //判断是否游戏结束void end(); //游戏结束#define up 72#define down 80#define left 75#define right 77#define esc 27HANDLE handle;int a1[4][4]={{1},{1,1,1}}; //七种方块的二维数组int a2[4][4]={{0,1},{1,1,1}};int a3[4][4]={{1,1},{0,1,1}};int a4[4][4]={{0,0,1},{1,1,1}};int a5[4][4]={{0,1,1},{1,1}};int a6[4][4]={{1,1,1,1}};int a7[4][4]={{1,1},{1,1}};int row=0; //列数int score=0;int level=0;int * block1=NULL;int * block2=NULL;int * block3=NULL;int coordinate[12][18]={0}; //坐标数组,边框12*18(最后一行,两边边框计算在内)int judge=0;int scorex=0;int temp[4][4]={0};void main() //主函数{int t=1;handle = initiate();while(t){t=0;begin();sndPlaySound("",SND_LOOP|SND_ASYNC);frame();WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;for(int k=1;k<=999999;k++){if(ifgameover()) //判断是否结束{textout(handle,34,10,wColors,1,"Game Over");Sleep(800);end();}else{if(k==1)block2=getblocks();block3=block2; //block2指向将出现的方块地址block2=getblocks(); //获取下一个新的方块block1=block3;row=52;clearsquare(16); //擦除next的方块block1=block2;drawblocks(15); //在next显示下一块方块图形row=34;block1=block3;for(int i=4;i<=7;i++) //所构建的方块图形最多只有占有两排,所以只用4-7即可对应{if(*(block1+i))textout(handle,26+i*2,4,wColors,1,"■"); //方块先露出下面部分}Sleep(500-50*level);for(int line=4;line<=22;line++) //方块自主下落,方块从第四排开始出现{if(isavailable(line)) //检验刚产生的方块是否碰壁,碰到已落方块{clearsquare(line); //消除方块先露初的下面分drawblocks(line); //产生完整的下落方块move(line);}else{remember(line); //落定后将这些位置对应的all数组中元素置1deleteline(line); //消行以及加分if(line==4)judge=1;break;}}}}}}void begin(){int i=1;WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_INTENSITY;WORD wColors1[2];wColors1[0]=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;wColors1[1]=FOREGROUND_RED|FOREGROUND_INTENSITY;textout(handle,18,4,wColors,1," ◢◣◢◣");textout(handle,18,5,wColors,1," ◢◎◣◢◎◣");textout(handle,18,6,wColors,1,"◢█████████◣");textout(handle,18,7,wColors,1,"██◤^^◥██");textout(handle,18,8,wColors,1,"████");textout(handle,18,9,wColors,1,"◢████◣");textout(handle,18,10,wColors,1,"██◤●●◥██");textout(handle,18,11,wColors,1,"██◎◎██");textout(handle,18,12,wColors,1,"◥█◣T◢█◤");textout(handle,18,13,wColors,1,"██◣◢██");textout(handle,18,14,wColors,1,"◥███████◤");textout(handle,18,15,wColors,1," ");textout(handle,18,16,wColors,1,"简单◥███████◤中等"); textout(handle,18,17,wColors,1,"请按1█请按2"); textout(handle,18,18,wColors,1,"█");textout(handle,18,19,wColors,1,"◢██◣");textout(handle,18,20,wColors,1," 困难请按3");textout(handle,54,22,wColors,1,"MADE BY ");while(i){textout(handle,30,8,wColors1,2,"俄罗斯方块");Sleep(800);textout(handle,30,8,wColors1,2," ");Sleep(800);if (_kbhit()) //输入等级{switch(_getch()){case '1':{level=1;i=0; //跳出循环break;}case '2':{level=4;i=0;break;}case '3':{level=7;i=0;break;}}}}system("cls"); //清屏}void frame() //边框的设定{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY;WORD wColors1[1];wColors1[0]=FOREGROUND_RED|FOREGROUND_INTENSITY;for(int i=0;i<=11;i++)coordinate[i][17]=1; //底排边框定义为1for(int j=0;j<=17;j++){coordinate[0][j]=1; //两边边框定义为1coordinate[11][j]=1;}char string[5];textout(handle,59,5,wColors,1,itoa(level,string,10)); textout(handle,52,5,wColors,1,"level: ");textout(handle,52,9,wColors,1,"score: 0");textout(handle,52,13,wColors,1,"next:");textout(handle,10,6,wColors1,1,"暂停SPACE"); textout(handle,10,7,wColors1,1,"退出ESC"); textout(handle,10,8,wColors1,1,"翻转↑"); textout(handle,10,9,wColors1,1,"向右→"); textout(handle,10,10,wColors1,1,"向左←"); textout(handle,10,11,wColors1,1,"加速↓"); textout(handle,33,2,wColors,1,"来~战个痛");for(int m=13;m<=24;m++){textout(handle,2*m,3,wColors,1,"═"); //上边框}for(int n=4;n<=21;n++){textout(handle,26,n,wColors,1,"‖"); //左边框}for(int k=4;k<=21;k++){textout(handle,48,k,wColors,1,"‖"); //右边框}for(int l=13;l<=23;l++){textout(handle,2*l,21,wColors,1,"═"); //下边框}textout(handle,26,3,wColors,1,"◤");textout(handle,48,3,wColors,1,"◥");textout(handle,26,21,wColors,1,"◣");textout(handle,48,21,wColors,1,"◢");}int * getblocks() //随机方块生成{int * m=NULL;srand(time(NULL));int n=rand()%7;switch(n){case 0:m=&a1[0][0];break;case 1:m=&a2[0][0];break;case 2:m=&a3[0][0];break;case 3:m=&a4[0][0];break;case 4:m=&a5[0][0];break;case 5:m=&a6[0][0];break;case 6:m=&a7[0][0];break;}return m;}void drawblocks(int line) //出现方块{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;for(int j=0;j<=15;j++){int temp;temp=j/4;if(*(block1+j))textout(handle,row+j*2-temp*8,line+temp,wColors,1,"■");}}void clearsquare(int line) //方块消失{WORD wColors[1];wColors[0]=FOREGROUND_BLUE|FOREGROUND_INTENSITY;if(line==4) //针对消除刚产生的下排{textout(handle,34,4,wColors,1," ");textout(handle,36,4,wColors,1," ");textout(handle,38,4,wColors,1," ");textout(handle,40,4,wColors,1," ");}else{for(int m=0;m<=15;m++){int temp;temp=m/4; //得0-3对应方块数组1-4行if(*(block1+m))textout(handle,row+m*2-temp*8,line-1+temp,wColors,1," ");}}}void move(int line) //方块的左右移动,加速下落,翻转等{int mid=0,speed=100-10*level;while(mid<speed){if (_kbhit()){switch(_getch()){case 72: //翻转{turn(line);}case 75: //左移{row=row-2; //纵坐标减2if(isavailable(line)) //判断是否能移动{row=row+2;clearsquare(line+1); //消除原来图案,line+1是避免line=4程序出错row=row-2;drawblocks(line); //出现新图案}elserow=row+2; //若不能移动则纵坐标不变break;}case 77: //右移{row=row+2;if(isavailable(line)){row=row-2;clearsquare(line+1);row=row+2;drawblocks(line);}row=row-2;break;}case 80: //加速下落,即直接跳除循环{mid=speed;break;}case 27: //终止游戏{end();break;}case 32: //暂停{int flag=1;while(flag){if (_kbhit()){if(_getch()==32)flag=0;break;}elseSleep(10);}default:break;}}Sleep(8); //使方块延迟mid++;}}void turn(int line){clearsquare(line+1); //消除原来的图案int b[4][4]={0}; //保存旋转前的方块int num=0,l=0;for(int m=0;m<=3;m++){for(int n=0;n<=3;n++){b[m][n]=*(block1+m*4+n); //把b[4][4]全赋值为当前图形数组temp[m][n]=0;}}for(int i=3;i>=0;i--) //按行从下向上扫描{for(int j=0;j<4;j++) //按列从左向右扫描{if(b[i][j]) //如果为有效点,则进行90度旋转{temp[j][l]=b[i][j];num=1;}}if(num){l++;num=0;}}block1=&temp[0][0];if(isavailable(line))drawblocks(line);else{for(int p=0;p<=3;p++){for(int q=0;q<=3;q++)temp[p][q]=b[p][q];}block1=&temp[0][0];drawblocks(line);}}bool isavailable(int line) //检验,即看方块即将存在位置是否已经有1 {int x,y;for(int m=0;m<=15;m++){int temp;temp=m/4;x=row/2-13-4*temp+m; //边框左边已有13个位置y=line-4+temp; //上面已有4个位置if(*(block1+m)&&coordinate[x][y]) //相与为1则返回0,否则跳出并循环继续return 0;}}void remember(int line) //记忆{int x,y;for(int m=0;m<=15;m++){int temp;temp=m/4;x=row/2-13-temp*4+m;y=line-4+temp;if(*(block1+m)) //如果当前位置为1,则返回原位置,并设置为1coordinate[x][y-1]=1;}}void deleteline(int l) //消行{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;int snum=0,b=0;for(int m=0;m<=16;m++) //从上向下消去方块{if(coordinate[1][m]==1&&coordinate[2][m]==1&&coordinate[3][m]==1&&coordinate[4][m]==1& &coordinate[5][m]==1&&coordinate[6][m]==1&&coordinate[7][m]==1&&coordinate[8][m]==1& &coordinate[9][m]==1&&coordinate[10][m]==1){textout(handle,28,m+4,wColors,1,"﹌﹌﹌﹌good﹌﹌﹌﹌");Sleep(750);for(int n=1;n<=m;n++){for(int j=1;j<=10;j++)coordinate[j][m-n+1]=coordinate[j][m-n];}snum++;}}for(int n=1;n<=10;n++){for(int d=0;d<=16;d++){int x,y;x=n*2+26;y=d+4;textout(handle,x,y,wColors,1," ");if(coordinate[n][d]){textout(handle,x,y,wColors,1,"■");}}}score=score+(snum*(snum+1)/2);if((score-scorex)>=30) //每得到30分自动加速{level++;scorex=score;}char string[5];textout(handle,59,9,wColors,1,itoa(score,string,10));textout(handle,59,5,wColors,1,itoa(level,string,10));}bool ifgameover() //终止游戏{if(judge==1){return 1;}elsereturn 0;}void end() //退出{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,28,22,wColors,1,"Press any key to exit");while(1){if (_kbhit()){exit(EXIT_SUCCESS);}}}。
/*学无止境*/ #include <stdlib.h>#include <stdio.h>#include <graphics.h>#define ESC 27#define UP 328#define DOWN 336#define LEFT 331#define RIGHT 333#define BLANK 32#define BOTTOM 2#define CANNOT 1#define CAN 0#define MAX 30#define F1 315#define ADD 43#define EQUAL 61#define DEC 45#define SOUNDs 115#define SOUNDS 83#define PAUSEP 80#define PAUSEp 112void Init();void Down();void GoOn();void ksdown();void Display(int color);void Give();int Touch(int x,int y,int dx,int dy);int GeyKey();void Select();void DetectFill();void GetScores();void Fail();void Help();void Quit();void DrawBox(int x,int y,int Color);void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch);void DrawNext(int Color);int Heng=12,Shu=20; /*横竖*/int Position[MAX][MAX];int middle[MAX][MAX];int ActH,ActS;int Act,Staus;int i,j,k;int Wid=10;int NoPass=CAN;float Delays=15000;int BeginH=250,BeginS=7;float Seconds=0;int Scores=0;int flag=1;int Sounds=CAN;int PreAct,NextAct;int a[8][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}},{{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},{{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},{0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}, {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}}, {{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}, {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}}, {{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0}, {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0}}, {{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}; int b[4][4];main(int argc,char *argv[]){if (argc!=1){if (argv[1]!="")Heng=atoi(argv[1]);if (argv[2]!="")Shu=atoi(argv[2]);}Init(); /*初始化界面*/PreAct=random(8); /*取得当前的方块*/for(;;) /*以下是游戏流程*/{NextAct=random(8); /*取得下一个方块*/ DrawNext(1); /*画出下一个方块*/Act=PreAct;if (Heng%2==0) ActH=Heng/2;else ActH=(Heng-1)/2;ActS=0; /*方块开始从游戏空间的中间下落*/ Staus=0; /*取开始的状态*/NoPass=CAN; /*物体可以下落*/Give(); /*取得当前的方块*/Display(Act+1); /*显示当前的方块,每种方块的颜色不同*/ GoOn(); /*游戏的算法精髓所在*/PreAct=NextAct; /*方块下落完毕,取得下一个方块*/ DrawNext(0);}}void Init(){int GraphDriver=DETECT,GraphMode;registerbgidriver(EGAVGA_driver);initgraph(&GraphDriver,&GraphMode,"");if (kbhit()) Sounds=CANNOT;setcolor(1);OutTextXY(10,10,"Tetris");OutTextXY(30,30,"Version 2.0");OutTextXY(10,120,"Help:");OutTextXY(20,140,"+ :Faster");OutTextXY(20,160,"- :Slower");OutTextXY(20,180,"Esc :Quit");OutTextXY(20,200,"F1 :Help");OutTextXY(10,310,"Copyright(c) 1998.2.22"); OutTextXY(10,320,"By Mr. Unique");outtextxy(10,250,"Score: 00000");rectangle(BeginH-3,BeginS-3,BeginH+Heng*(Wid+2)+2,BeginS+Sh u*(Wid+2)+2);rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Sh u*(Wid+2)+4);rectangle(BeginH+(Heng+4)*(Wid+2)-2,BeginS+10,BeginH+(Heng+ 8)*(Wid+2)+2,BeginS+12+4*(Wid+2));for (i=0;i<MAX;i++)for (j=0;j<MAX;j++){Position[i][j]=1;middle[i][j]=-1;}for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)Position[i][j]=0;for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)DrawBox(i,j,0);randomize();}void GoOn(){for(;;){Seconds+=0.2; /*控制方块的下落速度*/ if (Seconds>=Delays){Down();Seconds=0;if (NoPass==BOTTOM){DetectFill();middle[ActH][ActS]=Act;if (ActS==0)Fail();return;}}if (kbhit())Select();}}void Down() /*方块下降*/{Display(0);if (Touch(ActH,ActS,0,1)==CAN)ActS++;elsemiddle[ActH][ActS]=Act;Display(Staus+1);}int Touch(int x,int y,int dx,int dy) {NoPass=CAN;for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+dx+i][y+dy+j]+=b[i][j]; for (i=0;i<MAX;i++)for (j=0;j<MAX;j++)if (Position[i][j]>1)NoPass=CANNOT;for (i=0;i<4;i++)for (j=0;j<4;j++){Position[x+dx+i][y+dy+j]-=b[i][j]; middle[x+dx+i][y+dy+j]=Act;}if (NoPass==CANNOT && dx==0 && dy==1) {for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+i][y+j]+=b[i][j];NoPass=BOTTOM;}return NoPass;}int GetKey(void){int Ch,Low,Hig;Ch=bioskey(0);Low=Ch&0x00ff;Hig=(Ch&0xff00)>>8;return(Low==0?Hig+256:Low);}void Select(){int OldStaus,acts=ActS;switch(GetKey()){case ESC :Quit();break;case DOWN :Seconds+=14500;break;case LEFT :Display(0);if (ActH>0 && Touch(ActH,ActS,-1,0)==CAN) { ActH--;}Display(Act+1);break;case RIGHT :Display(0);if (ActH<Heng && Touch(ActH,ActS,1,0)==CAN) { ActH++;}Display(Act+1);break;case BLANK : Display(0);ksdown();Display(Act+1);break;case F1 :Help();break;case EQUAL :case ADD :if (Delays>300) Delays-=100;break; case DEC :if (Delays<3000) Delays+=100;break; case PAUSEP :case PAUSEp :getch();break;case SOUNDS :case SOUNDs :if (Sounds==CAN)Sounds=CANNOT;elseSounds=CAN;break;case UP :if(Act==7){while(acts<Shu-1&&Position[ActH][acts]!=1)acts++;Position[ActH][acts]=0;DrawBox(ActH,acts,0);acts=ActS;break;}else{Display(0);OldStaus=Staus;switch(Act){case 0:case 3:case 4:if (Staus==1) Staus=0;else Staus=1;break;case 1:break;case 2:case 5:case 6:if (Staus==3) Staus=0;else Staus++;break; }Give();if (Touch(ActH,ActS,0,0)==CANNOT){Staus=OldStaus;Give();}Display(Act+1);break;}}}void ksdown(){while(flag){if(Touch(ActH,ActS,0,0)==CAN){ActS++;}else {ActS--;flag=0;}}flag=1;}void Quit(){int ch,TopScore;FILE *fp;if ((fp=fopen("Russian.scr","r+"))!=NULL) {fscanf(fp,"%d",&TopScore);if (Scores>TopScore){setcolor(1);outtextxy(470,80,"Hello !");outtextxy(470,100,"In all the players,"); outtextxy(470,120,"You are the First !"); outtextxy(470,140,"And your score will"); outtextxy(470,160,"be the NEW RECORD !"); fseek(fp,0L,0);fprintf(fp,"%d",Scores);fclose(fp);}setcolor(1);OutTextXY(470,220,"Are You Sure (Yes/no)?"); ch=getch();if (ch=='y'||ch=='Y'){closegraph();delay(20);exit(0);}setcolor(0);outtextxy(470,220,"Are You Sure (Yes/no)?"); }void OutTextXY(int x,int y,char *String) {int i=0;char a[2];moveto(x,y);a[1]='\0';while (*(String+i)!='\0')a[0]=*(String+i);outtext(a);if (Sounds==CAN && a[0]!=' ') {sound(3000);delay(50);nosound();}i++;}}void Help(){unsigned Save;void *Buf;Save=imagesize(160,120,500,360); Buf=malloc(Save);getimage(160,120,500,360,Buf); setfillstyle(1,1);bar(160,120,500,280);setcolor(0);OutTextXY(170,130," About & Help");OutTextXY(170,150," # # # ########## # # # "); OutTextXY(170,160," # ## # # # # # # ###### ### "); OutTextXY(170,170," ########## ########## ## # # "); OutTextXY(170,180," # # # # # # # ## #### "); OutTextXY(170,190," # ## # #### ## # # # "); OutTextXY(170,200," # ## # # # # # ## # # # "); OutTextXY(170,210," # # # ## ## # ###### # # # "); OutTextXY(170,220," ## # ## # ## # # # # "); OutTextXY(170,230," # ## # #### # ## # "); OutTextXY(170,260," Good Luckly to You ");getch();putimage(160,120,Buf,0);free(Buf);}void GetScores(){int Sec10000,Sec1000,Sec100,Sec10,Sec1;setfillstyle(0,1);bar(60,250,109,260);Sec1=Scores%10;Sec10=(Scores%100-Scores%10)/10;Sec100=(Scores%1000-Scores%100)/100;Sec1000=(Scores%10000-Scores%1000)/1000; Sec10000=(Scores%100000-Scores%10000)/10000; DispScore(60,250,'0'+Sec10000);DispScore(70,250,'0'+Sec1000);DispScore(80,250,'0'+Sec100);DispScore(90,250,'0'+Sec10);DispScore(100,250,'0'+Sec1);DispScore(110,250,'0');DispScore(120,250,'0');}void DispScore(int x,int y,char Ch){char a[2];a[1]='\0';a[0]=Ch;outtextxy(x,y,a);}void Give(){for (i=0;i<4;i++)for (j=0;j<4;j++)b[i][j]=a[Act][Staus][i][j];}void Display(int color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (b[i][j]==1) DrawBox(ActH+i,ActS+j,color); }void DrawBox(int x,int y,int Color){x=BeginH+x*(Wid+2);y=BeginS+y*(Wid+2);setfillstyle(1,Color);bar(x+2,y+2,x+Wid-1,y+Wid-1);if (Color==0)setcolor(9);elsesetcolor(Act+1);rectangle(x+4,y+4,x+Wid-4,y+Wid-4);}void DrawNext(int Color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (a[NextAct][0][i][j]==1) DrawBox(Heng+4+i,1+j,Color); }void DetectFill(){int Number,Fall,FallTime=0;for (i=Shu-1;i>=0;i--){Number=0;for (j=0;j<Heng;j++)if (Position[j][i]==1) Number++;if (Number==Heng){FallTime++;if (Sounds==CAN){sound(500);delay(500);nosound();}for (Fall=i;Fall>0;Fall--)for (j=0;j<Heng;j++){Position[j][Fall]=Position[j][Fall-1]; middle[j][Fall]=middle[j][Fall-1];if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,middle[j][Fall]+1);}i++;}}switch(FallTime){case 0:break;case 1:Scores+=1;break;case 2:Scores+=3;break;case 3:Scores+=6;break;case 4:Scores+=10;break;}if (FallTime!=0){GetScores();if (Scores%100==0) Delays-=100;}}void Fail(){if (Sounds==CAN){for (k=0;k<3;k++){sound(300);delay(200);nosound();}}setcolor(1);OutTextXY(440,200,"Game over!"); Quit();closegraph();exit(0);}。