C语言程序设计-俄罗斯方块源程序
- 格式:doc
- 大小:42.00 KB
- 文档页数:15
#include<stdio.h>#include<graphics.h>#include<conio.h>#include<time.h>#include<dos.h>#include<stdlib.h>#include<math.h>#define LEFT 0x4b00#define RIGHT 0x4d00#define DOWN 0x5000#define UP 0x4800#define ESC 0x011bintBox_x[5],Box_y[5],Box_xy[15][10]={0},num,life=1,score,mx,my,key,x[5],y[5],size,g rade=0;int *buf;void Init();void my_ad_1();void my_ad_2();void my_ad_3();void play();void jiang();void De_B_xy();void Draw_Box();void Ad_Box_y();void Mi_Box_x();void Ad_Box_x();void ch_B_xy();void rebuild();void Draw_New();void close();void delay_n(int n);void main(){Init();my_ad_1();my_ad_2();my_ad_3();play();close();}void Init(){int driver=DETECT,mode;initgraph(&driver,&mode,"C:\\Program Files\\CYuYan\\bin");mx=getmaxx();my=getmaxy();setbkcolor(BLUE);size=imagesize(0,0,32,32);if(size!=-1)buf=malloc(size);getimage(0,0,32,32,buf);}void my_ad_1(){intch1[]={100,120,100,300,120,300,120,200,200,200,200,280,180,280,180,300,220,30 0,220,180,120,180,120,140,300,140,300,100,280,120,100,120},ch2[]={240,100,280,300,300,300,260,100,240,100},ch3[]={280,160,264,280,284,280,300,160,280,160},j1[]={300,120,340,160,360,160,320,100,300,120},j2[]={300,180,340,220,360,220,320,160,300,180},j3[]={300,300,340,300,380,220,360,220,300,300},j4[]={380,120,380,140,420,140,420,280,360,280,360,300,500,300,500,280,440,280, 440,140,480,140,480,120,380,120};settextjustify(CENTER_TEXT,CENTER_TEXT);settextstyle(TRIPLEX_FONT,HORIZ_DIR,5);setcolor(WHITE);sleep(2);outtextxy(320,200,"C Program Flash Creation");settextstyle(3,HORIZ_DIR,3);sleep(1);outtextxy(320,300,"Cheng Jiang,Electronic Class 1,Physic Department, GDUT");sleep(1);cleardevice();fillpoly(16,ch1);fillpoly(5,ch2);fillpoly(5,ch3);fillpoly(5,j1);fillpoly(5,j2);fillpoly(5,j3);fillpoly(12,j4);sleep(2);cleardevice();}void my_ad_2(){setfillstyle(SOLID_FILL,LIGHTBLUE);bar(0,0,150,my);bar(450,0,mx,my);setviewport(150,0,450,my,1);}void my_ad_3()int i,j;outtextxy(150,30,"Waitting...");setlinestyle(1,1,1);rectangle(0,60,450,90);setlinestyle(SOLID_LINE,1,THICK_WIDTH); jiang();for(i=0;i<10;i++){bar(30*i,60,30*(i+1),90);rectangle(30*i,60,30*(i+1),90);sleep(1);}clearviewport();outtextxy(150,240,"OK! Press [Enter]");getch();clearviewport();}void play(){int i,j;outtextxy(150,460,"grade:0 score: 0 ");while(1){randomize();num=random(19);De_B_xy();while(1){while(kbhit()){key=bioskey(0);Draw_Box();switch(key){case UP:getch();break;case DOWN:Ad_Box_y();break; case RIGHT:Ad_Box_x();break; case LEFT:Mi_Box_x();break; case ESC:close();break;default:ch_B_xy();break;}if(check()) break;}Draw_Box();if(check()) break;for(i=1;i<5;i++)Box_y[i]+=1;if(!kbhit())delay_n(10-grade);}rebuild();Draw_New();if(!life) break;}}void Draw_Box(){int i;for(i=1;i<5;i++)putimage(x[i]*30-1,30*y[i]-1,buf,COPY_PUT);if(!(y[1]&&y[2]&&y[3]&&y[0]))for(i=4;i<8;i++)putimage(30*i-1,0,buf,COPY_PUT);for(i=1;i<5;i++){x[i]=Box_x[i];y[i]=Box_y[i];bar(Box_x[i]*30, Box_y[i]*30, (Box_x[i]+1)*30, (Box_y[i]+1)*30);rectangle(Box_x[i]*30, Box_y[i]*30, (Box_x[i]+1)*30, (Box_y[i]+1)*30); }}void De_B_xy(){int i;switch(num){case 0: {Box_x[1]=Box_x[2]=Box_x[3]=Box_x[4]=0;Box_y[1]=0;Box_y[2]=1;Box_y[3]=2;Box_y[4]=3;} break;case 1: {Box_y[1]=Box_y[2]=Box_y[3]=Box_y[4]=0;Box_x[1]=0;Box_x[2]=1;Box_x[3]=2;Box_x[4]=3;} break;case 2: {Box_x[1]=0;Box_x[2]=1; Box_x[3]=0;Box_x[4]=1;Box_y[1]=0;Box_y[2]=0; Box_y[3]=1;Box_y[4]=1;} break;case 3: {Box_x[1]=0;Box_x[2]=0; Box_x[3]=0;Box_x[4]=1;Box_y[1]=0;Box_y[2]=1; Box_y[3]=2;Box_y[4]=1;} break;case 4: {Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=2;Box_y[1]=2;Box_y[2]=1; Box_y[3]=2;Box_y[4]=2;} break;case 5: {Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=1;Box_y[1]=1;Box_y[2]=0; Box_y[3]=1;Box_y[4]=2;} break;case 6: {Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=2; Box_y[1]=1;Box_y[2]=1; Box_y[3]=2;Box_y[4]=1;} break; case 7: {Box_x[1]=0;Box_x[2]=0; Box_x[3]=1;Box_x[4]=1;Box_y[1]=0;Box_y[2]=1; Box_y[3]=1;Box_y[4]=2;} break; case 8: {Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=2; Box_y[1]=1;Box_y[2]=0; Box_y[3]=1;Box_y[4]=0;} break; case 9: {Box_x[1]=0;Box_x[2]=0; Box_x[3]=1;Box_x[4]=1; Box_y[1]=1;Box_y[2]=2; Box_y[3]=0;Box_y[4]=1;} break; case 10:{Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=2; Box_y[1]=1;Box_y[2]=1; Box_y[3]=2;Box_y[4]=2;} break; case 11:{Box_x[1]=0;Box_x[2]=0; Box_x[3]=0;Box_x[4]=1; Box_y[1]=0;Box_y[2]=1; Box_y[3]=2;Box_y[4]=2;} break; case 12:{Box_x[1]=0;Box_x[2]=1; Box_x[3]=2;Box_x[4]=2; Box_y[1]=1;Box_y[2]=1; Box_y[3]=0;Box_y[4]=1;} break; case 13:{Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=1; Box_y[1]=0;Box_y[2]=0; Box_y[3]=1;Box_y[4]=2;} break; case 14:{Box_x[1]=0;Box_x[2]=0; Box_x[3]=1;Box_x[4]=2; Box_y[1]=0;Box_y[2]=1; Box_y[3]=0;Box_y[4]=0;} break; case 15:{Box_x[1]=0;Box_x[2]=1; Box_x[3]=1;Box_x[4]=1; Box_y[1]=2;Box_y[2]=0; Box_y[3]=1;Box_y[4]=2;} break; case 16:{Box_x[1]=0;Box_x[2]=1; Box_x[3]=2;Box_x[4]=2; Box_y[1]=0;Box_y[2]=0; Box_y[3]=0;Box_y[4]=1;} break; case 17:{Box_x[1]=0;Box_x[2]=0; Box_x[3]=0;Box_x[4]=1; Box_y[1]=0;Box_y[2]=1; Box_y[3]=2;Box_y[4]=0;} break; case 18:{Box_x[1]=0;Box_x[2]=0; Box_x[3]=1;Box_x[4]=2; Box_y[1]=0;Box_y[2]=1; Box_y[3]=1;Box_y[4]=1;} break; }for(i=1;i<5;i++)Box_x[i]+=4;}int check(){int i,p=0;for(i=1;i<5;i++)if(Box_xy[Box_y[i]+1][Box_x[i]]||Box_y[i]>13) p=1;return(p);}void Ad_Box_y(){int i,p=1;for(i=1;i<5;i++)if(Box_xy[Box_y[i]+1][Box_x[i]]||Box_y[i]>13) p=0;if(p)for(i=1;i<5;i++)Box_y[i]+=1;}void Ad_Box_x(){int i,p=1;for(i=1;i<5;i++)if(Box_xy[Box_y[i]][ Box_x[i]+1]||Box_x[i]>8) p=0;if(p)for(i=1;i<5;i++)Box_x[i]+=1;}void Mi_Box_x(){int i,p=1;for(i=1;i<5;i++)if(Box_xy[Box_y[i]][ Box_x[i]-1]||Box_x[i]<1) p=0;if(p)for(i=1;i<5;i++)Box_x[i]-=1;}void ch_B_xy(){int i,j,t,maxx=Box_x[1],maxy=Box_y[1];for(i=2;i<5;i++){if(maxx<Box_x[i])maxx=Box_x[i];if(maxy<Box_y[i])maxy=Box_y[i];}switch(num){case 0:num=num+1;break;case 1:num=num-1;case 2: ;break;case 3:num=num+1;break;case 4:num=num+1;break;case 5:num=num+1;break;case 6:num=num-3;break;case 7:num=num+1;break;case 8:num=num-1;break;case 9:num=num+1;break;case 10:num=num-1;break;case 11:num=num+1;break;case 12:num=num+1;break;case 13:num=num+1;break;case 14:num=num-3;break;case 15:num=num+1;break;case 16:num=num+1;break;case 17:num=num+1;break;case 18:num=num-3;break;}De_B_xy();for(i=1;i<5;i++){Box_x[i]=Box_x[i]+maxx-Box_x[4]; Box_y[i]=Box_y[i]+maxy-2;}}void rebuild(){int i,j,p,t[4]={0},k=0;for(i=1;i<5;i++)Box_xy[Box_y[i]][Box_x[i]]=1;for(i=0;i<15;i++){p=1;for(j=0;j<10;j++)if(!Box_xy[i][j])p=0;if(p)t[k]=i;k++;score+=10*k;}}for(k=0;k<4;k++){if(t[k]){for(i=t[k];i>0;i--)for(j=0;j<10;j++)Box_xy[i][j]=Box_xy[i-1][j]; }}for(i=0;i<10;i++)if(Box_xy[0][i])life=0;setfillstyle(1,4);for(i=0;i<4;i++)if(t[i])bar(0,30*t[i],300,30*(t[i]+1)); setfillstyle(1,9);for(i=1;i<5;i++){x[i]=0;y[i]=0;}grade=(score-score%100)/100 ; delay(30000);void Draw_New(){int i,j;char text[20];clearviewport();for(i=0;i<15;i++)for(j=0;j<10;j++)if(Box_xy[i][j]){bar(30*j,30*i,30*j+30,30*i+30);rectangle(30*j,30*i,30*j+30,30*i+30);}sprintf(text,"grade: %d score: %d",grade,score); gotoxy(100,460);outtextxy(150,460,text);}void close(){int i,j;for(i=14;i>=0;i--){for(j=0;j<10;j++){bar(30*j,30*i,30*(j+1),30*(i+1));rectangle(30*j,30*i,30*(j+1),30*(i+1));}delay(20000);}clearviewport();jiang();outtextxy(150,60,"game over");getch();closegraph();}void delay_n( int n){int i;for(i=0;i<n;i++) delay(50000);}void jiang(){int jx=0,jy=4;for(jx=0;jx<3;jx++){bar(30*jx,30*jy,30*(jx+1),30*(jy+1));rectangle(30*jx,30*jy,30*(jx+1),30*(jy+1));bar(30*jx,30*(jy+3),30*(jx+1),30*(jy+4));rectangle(30*jx,30*(jy+3),30*(jx+1),30*(jy+4)); jy++;}jy=14;for(jx=0;jx<4;jx++){bar(30*jx,30*jy,30*(jx+1),30*(jy+1));rectangle(30*jx,30*jy,30*(jx+1),30*(jy+1));jy--;}jy=4;for(jx=4;jx<9;jx++){bar(30*jx,30*jy,30*(jx+1),30*(jy+1));rectangle(30*jx,30*jy,30*(jx+1),30*(jy+1)); }jy=14;for(jx=3;jx<11;jx++){bar(30*jx,30*jy,30*(jx+1),30*(jy+1));rectangle(30*jx,30*jy,30*(jx+1),30*(jy+1)); }jx=6;for(jy=5;jy<15;jy++){bar(30*jx,30*jy,30*(jx+1),30*(jy+1));rectangle(30*jx,30*jy,30*(jx+1),30*(jy+1)); }}。
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语言课程设计报告主标题: C语言课程设计副标题:俄罗斯方块游戏----界面设计姓名:卢文俊指导教师:刘慧院系:信息工程学院专业:计算机科学与技术班级: 11计本(二)班小组成员:卢文俊,齐伟,陈龙提交日期: 2012-6-7俄罗斯方块程序设计报告一、问题描述:要求支持键盘操作和7种不同类型方块的旋转变换,并且界面上显示下一个方块的提示以及当前的玩家的得分,随着游戏的进行,等级越高,游戏难度越大,即方块的下落速度越快,相应的等级,等级越高,消去一行所得到的分数越高,为玩家提供了不同的选择。
二、功能分析:俄罗斯方块游戏需要解决的问题包括:⑴按任意键开始游戏,随机产生方块并自动下移⑵用Esc键退出游戏。
⑶用键变换方块⑷用键和键左右移动方块⑸用键使方块加速下移⑹用空格键使方块直接下移⑺能正确判断满行并消行、计分、定级别⑻能正确计时⑼设定游戏为不同级别,级别越高难度越大重点:*游戏面包的数据结构:二维数组*7种形状方块的数据结构:结构体保存每种形状方块的坐标、颜色三、程序设计:1、程序总体设计结构:首先初始化进入图形模式,进入欢迎界面,玩家按任意进入主菜单界面,按键进入游戏界面,键然后设置新的时钟中断。
开始游戏后,进入该程序最核心的部分——处理和实现进行过程中的各种事件和函数。
在处理中判断游戏是否结束,如果没有结束,则重新开始游戏,否则结束游戏。
详解如下:(1)、游戏方块预览功能。
在游戏过程中,当在游戏底板中出现一个游戏方块时,必须在游戏方块预览区域中出现下一个游戏方块,这样有利于游戏玩家控制游戏的策略。
由于在此游戏中存在19种不同的游戏方块,所以在游戏方块预览区域中需要显示随机生成的游戏方块。
(2)、游戏方块控制功能。
通过各种条件的判断,实现对游戏方块的左移、右移、快速下移、自由下落、旋转功能,以及行满消除行的功能。
否(3)、游戏显示更新功能。
在判断键值时,有左移VK_LEFT、右移VK_RIGHT、下移VK_DOWN、变形旋转VK_UP、退出VK_ESC键值的判断。
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;}。
1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,}; /*方块模板*/int shape,dir,next_shape,next_dir;struct position{int x;int y;} now_position; /*纪录现在方块的位置*/int speed_level=1;int fall_to_land,be_lined; /*判断方块是否着地的*/ /*----------------------------------------*/void clscreen();void setxy(int x,int y);void display_back();void display_interface();void display_fk(int x,int y,int shape,int dir);void init();//int getkey();/*取键盘的扫描码*/void getinput();void m_sound(int freq,int time);void eras_fk(int x,int y,int shape,int dir);/*擦除方块*/void fk_down(bool quickly = false);bool is_illegal(int x,int y,int changed_dir);/*判断方块移动后坐标是否非法,非法1,合法0*/int get_random(int n); /*生成一个0----n-1的随机数*/void check_line(); /*检查是否有行可以消去,如果有就消去*/void game_over();/*----------------------------------*/int main(){int i;init();while (true){display_back();now_position.x=10;now_position.y=2;/*复原初始坐标*/be_lined=0; /*一个方块刚出现时没有成行*/shape=next_shape;dir=next_dir;next_shape=get_random(7);next_dir=get_random(4);eras_fk(55,5,shape,dir);/*擦去前一个方块*/display_fk(55,5,next_shape,next_dir);/*显示下一个方块*/display_fk(now_position.x,now_position.y,shape,dir);/*显示目前方块*/fall_to_land=0;while (!fall_to_land){for (i=15000-1500*speed_level;i>0;i--){getinput();}/*接受键盘输入*/fk_down(); /*方块自动下落*/}//m_sound(350,500); /*块落下的声音*/ check_line(); /*检查有没有可消去的行*/if (be_lined)m_sound(250,1000);elsem_sound(350,500);}return0;}/*------------------------------------*/void init(){int i,j;for (i=0;i<20;i++)for (j=0;j<10;j++)background[i][j]=0;/*背景数组赋初值0*/next_shape=(get_random(7)+5)/7;next_dir=(get_random(4)+2)/4;/*预先产生一个方块*/display_interface();/*画界面*/}void display_interface(){clscreen();setxy(40,5);printf("The Next: ");setxy(1,1);}/*-----------------------------------------*/void display_back()/*显示背景*/{int i,j;for (i=0;i<20;i++){for (j=0;j<10;j++){setxy(2*(j+1),i+2); /*数组下标到屏幕坐标的变换*/if (!background[i][j])/*背景数组中值为0*/printf(" ");elseprintf("[]");}}}/*---------------------------------------*/void display_fk(int x,int y,int shape,int dir)/*显示方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf("[]");}}}}/*-----------------------------------*/void getinput(){if(GetAsyncKeyState(VK_LEFT)){if (!is_illegal(now_position.x-2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x-2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置左移一格*/}else if(GetAsyncKeyState(VK_RIGHT)){if (!is_illegal(now_position.x+2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x+2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置右移一格*/}else if(GetAsyncKeyState(VK_UP)){if (!is_illegal(now_position.x,now_position.y,(dir+1)%4)){eras_fk(now_position.x,now_position.y,shape,dir);dir=(dir+1)%4;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}}else if(GetAsyncKeyState(VK_DOWN)){fk_down(true);}else if(GetAsyncKeyState(VK_SPACE)){game_over();}}/*------------------------------------*/void m_sound(int freq,int time){Beep(freq,time);}/*--------------------------------*/void eras_fk(int x,int y,int shape,int dir)/*擦除方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf(" ");}}}}/*----------------------------------------------------*/ void fk_down(bool quickly) /*方块下落*/{int i,j,x,y;if (!is_illegal(now_position.x,now_position.y+1,dir))/*下落没有阻碍*/{eras_fk(now_position.x,now_position.y,shape,dir);now_position.y=now_position.y+1;display_fk(now_position.x,now_position.y,shape,dir);if(quickly){Sleep(10);}else{Sleep(1000);}}else/*不可再下落了*/{/*方块并入背景*/x=now_position.x;y=now_position.y; /*x,y表示方便*/for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]==1) background[(y-2+i)][(x/2-1+j)]=1;}}fall_to_land=1; /*告诉主程序方块着地*/}}/*-----------------------------------------------------*/ bool is_illegal(int x,int y,int changed_dir){int i,j;bool illegal=false;/*先判断有没有出界,如果有x,y在界外并且此x,y处方块数组为1,就返回1*/for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&((x+j*2)>21 || (x+j*2)<2 || (y+i)>21 || (y+i)<2))illegal=true;/*再判断是否有原方块阻碍*/if (!illegal){for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&background[(y-2+i)][(x/2-1+j)]==1)illegal=true;/*有阻碍返回一*/}return illegal;}/*-----------------------------------------------------*/int get_random(int n){int x;Sleep(500);/*randomize();x=random(n);*/srand( (unsigned)time(NULL));x=rand()%n;return(x);}/*--------------------------------------------------------------*/void check_line() /*待修改*/{/*检查背景数组*/int i,j,k;int line,n;for (i=19;i>=0;i--){k=1; /*开始默认成行*/for (j=9;j>=0;j-- ){if (background[i][j]==0) /*不成行的条件*/k=0;}if (k==1) /*如果成行*/{be_lined=1; /*成行标志*/for (line=i;line>0;line--)for (n=9;n>=0;n--)background[line][n]=background[line-1][n];/*逐次下移一行*/i=i+1; /*把下一次待检的行重新设定*/}}}/*--------------------------------------------------------------*/void game_over(){clscreen();setxy(35,1);printf("GAME OVER");exit(0);}void clscreen(){system("cls");}void setxy(int x,int y){HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);COORD place;place.X = x;place.Y = y;SetConsoleCursorPosition(hConsole, place);}/* Colors defined for SetColor(int) */enum {BLACK = 0,DARK_BLUE = 1,DARK_GREEN = 2,TEAL = 3,DARK_RED = 4,DARK_PURPLE = 5,GOLD = 6,GREY = 7,DARK_WHITE = 8,BLUE = 9,GREEN = 10,CYAN = 11,RED = 12,PURPLE = 13,YELLOW = 14,WHITE = 15};void SetColor(const int foreground, const int background) {int Color = foreground + (background * 16);HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);}你把这段拿回去看哈吧,这是一个俄罗斯方块的程序,就是在控制台运行的,就是用你所说的纯数字和字符所运行,你现在只能在dos 下显示那些纯数字的东西,是因为你很多技术性的手法,你还不会,但你学习到一定程度后,你就会有所领悟,也不要太心急,当你练好内功后,修炼招数,应该会很快的!希望对你有帮助。
#include<stdio.h>#include<stdlib.h>#include<dos.h>#include<graphics.h> /*系统提供的头文件*/#define TIMER 0x1c /*定义时钟中断的中断号*/#define VK_LEFT 0x4b00/*左移键*/#define VK_RIGHT 0x4d00/*右移键*/#define VK_DOWN 0x5000 /*加速键*/#define VK_UP 0x4800 /*变形键*/#define VK_SPACE 0x3920 /*变形键*/#define VK_END 0x4f00 /*暂停键*/#define VK_ESC 0x011b#define VK_ENTER 0x1c0d#define BSIZE 16 /*方块的边长是16个象素*/#define MAX_SHAPE 19 /*总共有19种各形态的方块*/#define BOARD_WIDTH 10 /*游戏面板的宽度,以方块的宽度为单位*/#define BOARD_HEIGHT 20/*游戏面板的高度,以方块的宽度为单位*/#define BGCOLOR BLACK /*背景色*/#define FORECOLOR WHITE /*前景色*/#define FALSE 0#define TRUE 1#define EMPTY 0#define FILLED 1#define BOARD_LEFT_X 10 /*游戏面板左上角的横坐标*/#define BOARD_LEFT_Y 5 /*游戏面板左上角的纵坐标*//*定义全局变量*/extern int Gameboard[BOARD_WIDTH+2][BOARD_HEIGHT+2];extern int nCurrent_block_index ; /*当前下落的方块的索引号*/ extern int nNext_block_index ; /*下一个方块的索引号*/extern int nSpeed, nScore; /*速度和得分*/extern int nSpeedUpScore; /*第一次要加速需达到的分数*/extern int bAccel, bOver;extern int nOriginX, nOriginY;/*某一形状的原点的绝对坐标*/ extern unsigned int TimerCounter; /* 计时变量,每秒钟增加18 */struct block{int arrXY[8];int nColor;int nNext;}; /*保存某一形状信息的结构体*/typedef struct block BLOCK;extern BLOCK arrayBlock[19];void interrupt newtimer(void);void SetTimer(void interrupt(*IntProc)(void));void KillTimer();void InitializeGraph();void InitializeGameboard() ;void DrawSquare(int x, int y);void DrawBlock(int BlockIndex, int sx, int sy,int color); int IsConflict(int BlockIndex, int x, int y);void HandleLeft(int BlockIndex,int *x, int *y);void HandleRight(int BlockIndex,int *x, int *y);void HandleUp(int *BlockIndex,int *x, int *y);int HandleDown(int BlockIndex,int *x, int *y);int IsLineFull(int y);void KillLine(int y);int KillLines(int y);int IsGameOver();int GameOver();void StartGame();void ProcessInGame();void game();void win();void help();void design();void show_win();void main(){win();menu();}void help(){clrscr();help();textcolor(WHITE);gotoxy(20,4);cprintf("\xDB\xDB\xDB\xDB\xB2 HELP ABOUT THE Game \xB2\xDB\xDB\xDB\xDB"); gotoxy(4,6);cprintf(" [ 1 ] - Metamorphose : Press the left key square moves left "); gotoxy(30,8);cprintf("Press the left key square move to the right");gotoxy(30,10);cprintf("Press down key square accelerate whereabouts");gotoxy(4,12);cprintf(" [ 2 ] - Speed up : Press the button oblong rotating ");gotoxy(4,14);cprintf(" [ 3 ] - Game Start : Press Enter to button to start the game"); gotoxy(4,16);cprintf(" [ 4 ] - Game Over : Press the ESC key to quit the game");gotoxy(30,18);cprintf("YOU WANT TO BE HELPFUL");gotoxy(6,23);printf("Press any key to go to the MAIN MENU ........");getche();}menu(){int x;do{{clrscr();design();textcolor(WHITE);cprintf("\xDB\xDB\xDB\xDB\xB2 Tetris Game \xB2\xDB\xDB\xDB\xDB");gotoxy(3,4);cprintf("--------------------------------------------------------------------------");gotoxy(35,5);cprintf("MAIN MENU");gotoxy(26,8);cprintf(" 1 - New Game ");gotoxy(26,9);cprintf(" 2 - Rank ");gotoxy(26,10);cprintf(" 3 - HELP ");gotoxy(26,11);cprintf(" 4 - The Game Explain ");gotoxy(26,12);cprintf(" 5 - EXIT ");x=toupper(getch());switch(x){case '1':game();break;case '2':cprintf("At present there is no ranking");break;case '3':help();break;case '4':cprintf("This game by LuWenJun,ChenLong,QiWei jointly compiled,Deficiencies still please forgive me");break;case '5':exit(0);break;default:clrscr();design();gotoxy(17,12);printf("\a\xDB\xB2 WRONG ENTRY : PRESS ANY KEY AND TRY AGAIN"); getche();}}}while(x!='5');return x;}void win(){int i,graphdriver,graphmode,size,page;char s1[30],s2[30];graphdriver=DETECT;initgraph(&graphdriver,&graphmode,"c:\\turboc2");cleardevice();setbkcolor(BLUE);setviewport(40,40,600,440,1);setfillstyle(1,2);setcolor(YELLOW);rectangle(0,0,560,400);floodfill(50,50,14);rectangle(20,20,540,380);setfillstyle(1,13);floodfill(21,300,14);setcolor(BLACK);settextstyle(1,0,6);outtextxy(100,60,"Welcom You");setviewport(100,200,540,380,0);setcolor(14);setfillstyle(1,12);rectangle(20,20,420,120);settextstyle(2,0,9);floodfill(21,100,14);sprintf(s1,"Let's our play Tetris Game!");setcolor(YELLOW);outtextxy(60,40,s1);sprintf(s2,"Press any key to play....");setcolor(1);settextstyle(4,0,3);outtextxy(110,80,s2);getch();closegraph();}void design(){int i;clrscr();textcolor(14);gotoxy(2,2);cprintf("\xC9");gotoxy(3,2);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,2);cprintf("\xBB");gotoxy(2,3);cprintf("\xBA");gotoxy(2,4);cprintf("\xBA");gotoxy(2,5);cprintf("\xBA");gotoxy(2,6);cprintf("\xBA");gotoxy(2,7);cprintf("\xBA");gotoxy(2,8);cprintf("\xB A");gotoxy(2,9);cprintf("\xBA");gotoxy(2,10);cprintf("\xBA");gotoxy(2,11);cprintf("\ xBA");gotoxy(2,12);cprintf("\xBA");gotoxy(2,13);cprintf("\xBA");gotoxy(2,14);cprintf("\xBA");gotoxy(2,15);cprintf(" \xBA");gotoxy(2,16);cprintf("\xBA");gotoxy(2,17);cprintf("\xBA");gotoxy(2,18);cprintf("\xBA");gotoxy(2,22);cprintf(" \xCC");gotoxy(2,19);cprintf("\xBA");gotoxy(2,20);cprintf("\xBA");gotoxy(2,21);cprintf(" \xBA");gotoxy(2,24);cprintf("\xC8");gotoxy(2,23);cprintf("\xBA");gotoxy(3,24);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,18);cprintf("\xBA");gotoxy(77,19);cprintf("\xBA");gotoxy(77,20);cprint f("\xBA");gotoxy(77,21);cprintf("\xBA");gotoxy(77,24);cprintf("\xBC");gotoxy(77,23);cprintf("\xBA");gotoxy(3,22);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,22);cprintf("\xB9");gotoxy(77,3);cprintf("\xBA");gotoxy(77,4);cprintf("\xBA");gotoxy(77,5);cprintf("\xBA");gotoxy(77,6);cprintf("\xBA");gotoxy(77,7);cprintf("\xBA");gotoxy(77,8);cprintf(" \xBA");gotoxy(77,9);cprintf("\xBA");gotoxy(77,10);cprintf("\xBA");gotoxy(77,11);cprintf ("\xBA");gotoxy(77,12);cprintf("\xBA");gotoxy(77,13);cprintf("\xBA");gotoxy(77,14);cprintf("\xBA");gotoxy(77,15);cprint f("\xBA");gotoxy(77,16);cprintf("\xBA");gotoxy(77,17);cprintf("\xBA");textcolor(RED);}void show_win(void){union REGS in, out;in.x.ax = 0x1;int86(0x33, &in, &out);}/*********************************************************** 函数原型:void InitializeGraph() * * 传入参数:无 ** 返回值:无 ** 函数功能:初始化进入图形模式***********************************************************/void InitializeGraph(){int gdriver = VGA, gmode=VGAHI, errorcode;/* 初始化图形模式*/initgraph(&gdriver, &gmode, "c:\\turboc2");/* 读取初始化结果 */errorcode = graphresult();if (errorcode != grOk) /* 错误发生 */{printf("Graphics error: %s\n", grapherrormsg(errorcode));printf("Press any key to halt:");getch();exit(1); /* 返回错误码 */}}/*********************************************************** 函数原型:void InitializeGameboard() ** 传入参数:无** 返回值:无** 函数功能:初始化游戏面板以及下一形状提示框、计分框和难度框 ***********************************************************/void InitializeGameboard(){/* 绘制游戏面板(即游戏区域)*/setfillstyle(SOLID_FILL,BGCOLOR);bar(BSIZE*BOARD_LEFT_X,BSIZE*BOARD_LEFT_Y,BSIZE*(BOARD_LEFT_X+BOARD_WIDTH),BSIZE*(BOARD_LEFT_Y+BOARD_HEIGHT));setcolor(WHITE);rectangle(BSIZE*BOARD_LEFT_X,BSIZE*BOARD_LEFT_Y,BSIZE*(BOARD_LEFT_X+BOARD_WIDTH),BSIZE*(BOARD_LEFT_Y+BOARD_HEIGHT));/*绘制下一形状提示框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(5+1), "next");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*(24.5+2), BSIZE*6, BSIZE*(24.5+2+5), BSIZE*(6+5));setcolor(YELLOW);rectangle(BSIZE*(24.5+2), BSIZE*6, BSIZE*(24.5+2+5), BSIZE*(6+5));/*绘制速度框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(12+1), "level");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1)); setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(13+1), "0");/*绘制计分框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(19+1), "score");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1)); setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(20+1), "0");}int Gameboard[BOARD_WIDTH+2][BOARD_HEIGHT+2];int nCurrent_block_index;/* 当前下落的方块的索引号*/int nNext_block_index ; /*下一个方块的索引号*/int nSpeed, nScore; /*速度和得分*/int nSpeedUpScore = 1000; /*第一次要加速需达到的分数*/int bAccel, bOver;int nOriginX=5, nOriginY=1;/*某一形状的原点的绝对坐标*/ BLOCK arrayBlock[19]={/*x1,y1,x2,y2,x3,y3,x4,y4, color, next*/{ 0,-2, 0,-1, 0, 0, 1, 0, CYAN, 1}, /* */{-1, 0, 0, 0, 1,-1, 1, 0, CYAN, 2}, /* # */{ 0,-2, 1,-2, 1,-1, 1, 0, CYAN, 3}, /* # */{-1,-1,-1, 0, 0,-1, 1,-1, CYAN, 0}, /* ## */{ 0,-2, 0,-1, 0, 0, 1,-2,MAGENTA, 5}, /* */{-1,-1,-1, 0, 0, 0, 1, 0,MAGENTA, 6}, /* ## */{ 0, 0, 1,-2, 1,-1, 1, 0,MAGENTA, 7}, /* # */{-1,-1, 0,-1, 1,-1, 1, 0,MAGENTA, 4}, /* # */{-1, 0, 0,-1, 0, 0, 1, 0,YELLOW, 9}, /* */{-1,-1, 0,-2, 0,-1, 0, 0,YELLOW, 10}, /* */{-1,-1, 0,-1, 0, 0, 1,-1,YELLOW, 11}, /* # */{ 0,-2, 0,-1, 0, 0, 1,-1,YELLOW, 8}, /* ### */{-1, 0, 0,-1, 0, 0, 1,-1, BROWN, 13}, /* ## */{ 0,-2, 0,-1, 1,-1, 1, 0, BROWN, 12}, /* ## */{-1,-1, 0,-1, 0, 0, 1, 0, WHITE, 15}, /* ## */{ 0,-1, 0, 0, 1,-2, 1,-1, WHITE, 14}, /* ## */{ 0,-3, 0,-2, 0,-1, 0, 0, RED, 17},/* # */{-1, 0, 0, 0, 1, 0, 2, 0, RED, 16},/* # *//* # *//* # */{ 0,-1, 0, 0, 1,-1, 1, 0, BLUE, 18},/* ## *//* ## */};/*********************************************************** 函数原型:void StartGame () ** 传入参数:无** 返回值:无 ** 函数功能:游戏开始时调用的函数,其中绘制界面需调用函数 ** InitializeGameboard(), 接下来需初始化游戏面板的 ** 各个方块和一些全局变量的初值 ***********************************************************/void StartGame(){int i,j;/*设置游戏面板中每个方块的初始值*/for(j=0;j<=BOARD_HEIGHT;j++)for(i=0;i<BOARD_WIDTH+2;i++){if(i==0 || i==BOARD_WIDTH+1)Gameboard[i][j] = FILLED;elseGameboard[i][j] = EMPTY;}for(i=0;i<BOARD_WIDTH+2;i++)Gameboard[i][BOARD_HEIGHT+1] = FILLED;InitializeGameboard();/*设置游戏变量的初值*/nNext_block_index = -1; /*游戏初始,没有下一个形状的索引号*/nSpeed = 0;nScore = 0;}/*********************************************************** 函数原型:void ProcessInGame() ** 传入参数:无** 返回值:无** 函数功能:核心函数,主要用于处理在游戏中的各种事件(如按下各种按键) ***********************************************************/void ProcessInGame(){int key;bioskey(0);randomize();while(1){if(nNext_block_index==-1){nCurrent_block_index = rand()%19;nNext_block_index = rand()%19;/*绘制下一个提示形状*/DrawBlock(nNext_block_index,19,6,arrayBlock[nNext_block_index].nColor );}else{nCurrent_block_index = nNext_block_index;DrawBlock(nNext_block_index, 19,6,BGCOLOR ); /* 消除原来的提示形状 */nNext_block_index = rand()%19;DrawBlock(nNext_block_index,19,6,arrayBlock[nNext_block_index].nColor ); /*绘制下一个提示形状 */}nOriginX=5, nOriginY=1;TimerCounter = 0;DrawBlock(nCurrent_block_index, nOriginX,nOriginY, arrayBlock[nCurrent_block_index].nColor );/*在面板内绘制当前形状*/while(1){if (bioskey(1))key=bioskey(0);else key=0;bAccel = FALSE;switch(key){case VK_LEFT: /* 左移 */HandleLeft(nCurrent_block_index,&nOriginX,&nOriginY );break;case VK_RIGHT: /* 右移 */HandleRight(nCurrent_block_index,&nOriginX,&nOriginY );break;case VK_UP: /* 旋转 */case VK_SPACE:HandleUp(&nCurrent_block_index, &nOriginX,&nOriginY);break;case VK_DOWN: /* 下落加速键 */bAccel=TRUE;break;case VK_END: /* 暂停*/bioskey(0);break;case VK_ESC: /* 退出游戏 */bOver=TRUE;return;}if(bAccel || TimerCounter>(20-nSpeed*2))if(HandleDown(nCurrent_block_index,&nOriginX,&nOriginY))break;if(bOver)return;}}}/*********************************************************** 函数原型:void main() ** 传入参数:无 ** 返回值:无 ** 函数功能:入口函数,包含俄罗斯方块程序的主流程 ***********************************************************/void game(){InitializeGraph();SetTimer(newtimer); /*设置新的时钟中断*/while(1){StartGame();ProcessInGame();if(GameOver())break;bOver = FALSE;}KillTimer();closegraph();}unsigned int TimerCounter=0; /* 计时变量,每秒钟增加18 *//*********************************************************** 函数原型:void interrupt (*oldtimer)(void) ** 传入参数:无** 返回值:无** 函数功能:指向原来时钟中断处理过程入口的中断处理函数指针(句柄) ***********************************************************/void interrupt (*oldtimer)(void);/*********************************************************** 函数原型:void interrupt newtimer(void) ** 传入参数:无 ** 返回值:无 ** 函数功能:新的时钟中断处理函数 ***********************************************************/void interrupt newtimer(void){(*oldtimer)();TimerCounter++;}/*********************************************************** 函数原型:void SetTimer(void interrupt(*)(void)) ** 传入参数:无 ** 返回值:无 ** 函数功能:设置新的时钟中断处理函数 ***********************************************************/void SetTimer(void interrupt(*IntProc)(void)){oldtimer=getvect(TIMER);disable();setvect(TIMER,IntProc);enable();}/*********************************************************** 函数原型:void KillTimer() ** 传入参数:无 ** 返回值:无 ** 函数功能:恢复原先的时钟中断处理函数 ***********************************************************/void KillTimer(){disable();setvect(TIMER,oldtimer);enable();}/*********************************************************** 函数原型:void DrawSquare(int x, int y) ** 传入参数:游戏面板中的横坐标x,纵坐标y ** 返回值:无 ** 函数功能:在坐标(x, y)处绘制方块 ***********************************************************/void DrawSquare(int x, int y){if(y<1)return;bar(BSIZE*(x+9)+1,BSIZE*(y+4)+1,BSIZE*(x+10)-1,BSIZE*(y+5)-1);}/*********************************************************** 函数原型:void DrawBlock(int BlockIndex, int sx, int sy,int color) ** 传入参数:形状的索引BlockIndex,绝对横坐标x,绝对纵坐标y,颜色color ** 返回值:无** 函数功能:在坐标(sx, sy)处绘制颜色为color的形状***********************************************************/void DrawBlock(int BlockIndex, int sx, int sy,int color){int i,c;setfillstyle(SOLID_FILL, color);for(i=0;i<7;i+=2)DrawSquare(arrayBlock[BlockIndex].arrXY[i]+sx,arrayBlock[BlockIndex].arrXY[i+1]+sy);}/*********************************************************** 函数原型:int IsConflict(int BlockIndex, int x, int y) ** 传入参数:形状的索引BlockIndex,绝对横坐标x,绝对纵坐标y ** 返回值:无冲突返回0,有冲突返回1 ** 函数功能:判断形状是否能存在于坐标(x, y)处 * **********************************************************/int IsConflict(int BlockIndex, int x, int y){int i;for (i=0;i<=7;i++,i++){if (arrayBlock[BlockIndex].arrXY[i]+x<1 || arrayBlock[BlockIndex].arrXY[i]+x>10)return TRUE;if (arrayBlock[BlockIndex].arrXY[i+1]+y<1)continue;if(Gameboard[arrayBlock[BlockIndex].arrXY[i]+x][arrayBlock[BlockIndex].arrXY[i+1]+ y])return TRUE;}return FALSE;}/*********************************************************** 函数原型:int HandleLeft(int BlockIndex,int *x, int *y) * * 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下左方向键时的处理函数***********************************************************/void HandleLeft(int BlockIndex,int *x, int *y) /*按下左方向键时的处理函数*/{if(!IsConflict(BlockIndex,*x-1,*y)){DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*x)--;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleRight(int BlockIndex,int *x, int *y) ** 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下右方向键时的处理函数***********************************************************/void HandleRight(int BlockIndex,int *x, int *y)/*按下右方向键时的处理函数*/{if(!IsConflict(BlockIndex,*x+1,*y)){DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*x)++;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleUp(int BlockIndex,int *x, int *y) ** 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下上方向键(旋转键)时的处理函数***********************************************************/void HandleUp(int *BlockIndex,int *x, int *y) /*按下旋转键时的处理函数*/{int NextBlockIndex, i;static int arrayOffset[5]={0,-1,1,-2,2};NextBlockIndex = arrayBlock[*BlockIndex].nNext;for(i=0;i<5;i++)if(!IsConflict(NextBlockIndex, *x+arrayOffset[i],*y)){DrawBlock(*BlockIndex, *x, *y, BGCOLOR); /*擦除原先的形状*/*BlockIndex = arrayBlock[*BlockIndex].nNext;(*x) += arrayOffset[i];DrawBlock(*BlockIndex, *x, *y, arrayBlock[*BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleDown(int BlockIndex,int *x, int *y) * * 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:仍在自由下落返回0,无法下落了返回1 ** 函数功能:按下向下方向键或自由下落时的处理函数***********************************************************/int HandleDown(int BlockIndex,int *x, int *y)/*按下下方向键或自由下落时的处理函数*/{char ScoreBuffer[10]={0},SpeedBuffer[10]={0};int i;int NumLinesKilled=0;/*if(TimerCounter>(20-nSpeed*2))*/{TimerCounter = 0; /*重置时钟中断*/if(!IsConflict(BlockIndex,*x,*y+1)) /*仍在下落*/{DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*y)++;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/return FALSE;/*仍在下落返回FALSE*/}else /*无法再下落了*/{DrawBlock(BlockIndex,*x,*y,FORECOLOR);for (i=0;i<=7;i++,i++){if ((*y)+arrayBlock[BlockIndex].arrXY[i+1]<1)continue;Gameboard[(*x)+arrayBlock[BlockIndex].arrXY[i]][(*y)+arrayBlock[BlockIndex].arrX Y[i+1]]=1;}NumLinesKilled = KillLines(*y);if(NumLinesKilled>0){switch(NumLinesKilled){case 1:nScore+=100;case 2:nScore+=300;case 3:nScore+=500;case 4:nScore+=800;}/*重绘计分框*/setfillstyle(SOLID_FILL,BLACK);bar(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));itoa(nScore,ScoreBuffer, 10);setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(20+1), ScoreBuffer);if(nScore > nSpeedUpScore){nSpeed++;nSpeedUpScore+= nSpeed*1000;/*重绘速度框*/setfillstyle(SOLID_FILL,BLACK);bar(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1)); itoa(nSpeed,SpeedBuffer,10);setcolor(YELLOW);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(13+1), SpeedBuffer);}if(IsGameOver())bOver = TRUE;return TRUE; /*下落到底返回TRUE*/}}}/*********************************************************** 函数原型:int IsLineFull(int y) ** 传入参数:纵坐标y ** 返回值:填满返回1,否则返回0 ** 函数功能:判断第y行是否已被填满***********************************************************/int IsLineFull(int y){int i;for(i=1;i<=10;i++)if(!Gameboard[i][y])return FALSE;return TRUE;}/*********************************************************** void KillLine(int y) ** 传入参数:纵坐标y ** 返回值:无 ** 函数功能:消去第y行***********************************************************/void KillLine(int y){int i,j;for(j=y;j>=2;j--)for(i=1;i<=10;i++){if(Gameboard[i][j]==Gameboard[i][j-1])continue;if(Gameboard[i][j-1]==FILLED){Gameboard[i][j]=FILLED;setfillstyle(SOLID_FILL,FORECOLOR);}else /*Gameboard[i][j-1]==EMPTY*/Gameboard[i][j] = EMPTY;setfillstyle(SOLID_FILL,BGCOLOR);}DrawSquare(i,j);}}/*********************************************************** 函数原型:int KillLines(int y) ** 传入参数:纵坐标y ** 返回值:消去的行数 ** 函数功能:消去第y行以及与第y行连续的上面被填满的行 ***********************************************************/int KillLines(int y){int i, j, LinesKilled=0;for(i=0;i<4;i++){while(IsLineFull(y)){KillLine(y);LinesKilled++;i++;}y--;if(y<1)break;}return LinesKilled;}/*********************************************************** 函数原型:int IsGameOver() ** 传入参数:无 ** 返回值:游戏结束返回1,否则返回0 ** 函数功能:判断游戏是否结束***********************************************************/int IsGameOver(){int i;for(i=1;i<=10;i++)if(Gameboard[i][1])return TRUE;return FALSE;}/*********************************************************** 函数原型:int GameOver() ** 传入参数:无** 返回值:退出游戏返回1,否则返回0 ** 函数功能:在界面上输出游戏结束信息,并根据用户按键选择决定是否退出游戏***********************************************************/int GameOver(){int key;settextjustify(CENTER_TEXT,TOP_TEXT);/* 输出游戏结束信息 */setcolor(RED);outtextxy(BSIZE*15,BSIZE*12,"Game Over");setcolor(GREEN);outtextxy(BSIZE*15,BSIZE*14,"Enter : New Game");outtextxy(BSIZE*15,BSIZE*15,"Esc : Exit");for(;;){while(!bioskey(1));key=bioskey(0);if (key==VK_ENTER)return FALSE; /* 按下回车键,重新开始游戏 */if (key==VK_ESC)return TRUE; /* 按下ESC键,退出游戏 */}}。
C语言小游戏源代码《俄罗斯方块》#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+Shu*(Wid+2)+2);rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Shu*(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);}。
其中的主要逻辑有:(1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。
(2)得分越高,方块下降速度越快(每200分为单位)。
(3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。
初试分数为100分。
游戏控制:up-旋转;空格-下落到底;左右下方向键-控制方向。
P-开始或暂停游戏。
ESC-退出。
特点:(1)由于tc不支持中文,所以基本都是英文注释。
(2)函数命名尽可能规范的表达其内部处理目的和过程。
(3)代码加上注释仅有577行。
(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。
(4)除了消除空格时算法比较复杂,其他算法都比较简单易读。
(5)绘图效率和局部代码效率扔有待提高。
(6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。
俄罗斯方块源于大约9年前上大一时的一个梦,我们在学习c语言时,我的同寝室友邀请我合作一起完成俄罗斯方块(课外作业性质),但是当时限于我们的水平比较菜和学习状态比较懒散,我们没有完成。
大一的时候我在机房里无意发现别人留下的俄罗斯方块程序,运行,老师发现后激动的问我是我写的吗,我惭愧的摇摇头。
那时看到别人做c的大程序深感羡慕(自己只是写几十行的程序)。
数年后我仍然看到有不同样式的实现,但是我一直没有实现它,知道今天忽然有这个想法去做,算是弥补多年前的遗憾和心愿吧。
---------------------------------------------Q&A:----------------------------------------------Q:我编译时出现错误:fatal error C1083: Cannot open include file: 'bios.h': Nosuch file or directory,该如何解决?A:正文中的代码,是使用Borland公司的TC2.0编译的,编译结果运行在Windows的16位虚拟机上。
bi os.h是属于TC的头文件,在VC或者其他编译器中可能没有这个头文件。
因此会产生这个错误。
解决办法:(1)可以下载附件中的压缩包,是使用VC6.0进行编译的版本,编译结果是Windows程序,运行在wind ows 32系统上。
两者之间的算法完全一致,区别仅仅是绘图时采用的接口不同,TC下采用BGI(进入图形模式),VC下采用的是GDI(使用DC进行绘图)。
(2)下载TC2.0进行编译。
Q:使用TC3.0进行编译时,提示未能初始化图形模式,请使用initgraph函数。
A:这是因为TC3.0的BGI文件的路径和TC2.0有所不同。
TC2.0的BGI文件位于TC路径下。
而TC3.0的BGI文件位于BGI文件夹中。
请把initgame函数中的initgraph函数中的第三个参数设置为正确的路径。
例如:initgraph(&..,&..,"C:\\TC\\BGI");Q:编译后运行时,弹出错误对话框报告16位虚拟机遇到不可执行的指令,点击确定后退出。
A:该问题在某些环境中出现,可能是基于软件或者硬件环境造成,具体原因暂时未知。
为避免该问题,请加载附件中的压缩包VC6.0版本。
-----------------------------------------------------------------TC2.0的代码如下(VC6.0版本代码见附件):程序代码:/************************************* Desc: 俄罗斯方块游戏* By: hoodlum1980* Email: jinfd@* Date: 2008.03.12 22:30************************************/#include <stdio.h>#include <bios.h>#include <dos.h>#include <graphics.h>#include <string.h>#include <stdlib.h>#define true 1#define false 0#define BoardWidth 12#define BoardHeight 23#define _INNER_HELPER /*inner helper method *//*Scan Codes Define*/enum KEYCODES{K_ESC =0x011b,K_UP =0x4800, /* upward arrow */K_LEFT =0x4b00,K_DOWN =0x5000,K_RIGHT =0x4d00,K_SPACE =0x3920,K_P =0x1970};/* the data structure of the block */typedef struct tagBlock{char c[4][4]; /* cell fill info array, 0-empty, 1-filled */ int x; /* block position cx [ 0,BoardWidht -1] */ int y; /* block position cy [-4,BoardHeight-1] */ char color; /* block color */char size; /* block max size in width or height */char name; /* block name (the block's shape) */} Block;/* game's global info */int FrameTime= 1300;int CellSize= 18;int BoardLeft= 30;int BoardTop= 30;/* next block grid */int NBBoardLeft= 300;int NBBoardTop= 30;int NBCellSize= 10;/* score board position */int ScoreBoardLeft= 300;int ScoreBoardTop=100;int ScoreBoardWidth=200;int ScoreBoardHeight=35;int ScoreColor=LIGHTCYAN;/* infor text postion */int InfoLeft=300;int InfoTop=200;int InfoColor=YELLOW;int BorderColor=DARKGRAY;int BkGndColor=BLACK;int GameRunning=true;int TopLine=BoardHeight-1; /* top empty line */int TotalScore=100;char info_score[20];char info_help[255];char info_common[255];/* our board, Board[x][y][0]-isFilled, Board[x][y][1]-fillColor */ unsigned char Board[BoardWidth][BoardHeight][2];char BufferCells[4][4]; /* used to judge if can rotate block */ Block curBlock; /* current moving block */Block nextBlock; /* next Block to appear *//* function list */int GetKeyCode();int CanMove(int dx,int dy);int CanRotate();int RotateBlock(Block *block);int MoveBlock(Block *block,int dx,int dy);void DrawBlock(Block *block,int,int,int);void EraseBlock(Block *block,int,int,int);void DisplayScore();void DisplayInfo(char* text);void GenerateBlock(Block *block);void NextBlock();void InitGame();int PauseGame();void QuitGame();/*Get Key Code */int _INNER_HELPER GetKeyCode(){int key=0;if(bioskey(1)){key=bioskey(0);}return key;}/* display text! */void _INNER_HELPER DisplayInfo(char *text){setcolor(BkGndColor);outtextxy(InfoLeft,InfoTop,info_common);strcpy(info_common,text);setcolor(InfoColor);outtextxy(InfoLeft,InfoTop,info_common);}/* create a new block by key number,* the block anchor to the top-left corner of 4*4 cells*/void _INNER_HELPER GenerateBlock(Block *block){int key=(random(13)*random(17)+random(1000)+random(3000))%7; block->size=3;/* because most blocks' size=3 */memset(block->c,0,16);switch(key){case 0:block->name='T';block->c[1][0]=1;block->c[1][1]=1, block->c[2][1]=1; block->c[1][2]=1;break;case 1:block->name='L';block->color=YELLOW;block->c[1][0]=1;block->c[1][1]=1;block->c[1][2]=1, block->c[2][2]=1; break;case 2:block->name='J';block->color=LIGHTGRAY;block->c[1][0]=1;block->c[1][1]=1;block->c[1][2]=1, block->c[0][2]=1; break;case 3:block->name='z';block->color=CYAN;block->c[0][0]=1, block->c[1][0]=1; block->c[1][1]=1, block->c[2][1]=1; break;case 4:block->name='5';block->color=LIGHTBLUE;block->c[1][0]=1, block->c[2][0]=1; block->c[0][1]=1, block->c[1][1]=1; break;case 5:block->name='o';block->color=BLUE;block->size=2;block->c[0][0]=1, block->c[1][0]=1; block->c[0][1]=1, block->c[1][1]=1; break;case 6:block->name='I';block->color=GREEN;block->size=4;block->c[1][0]=1;block->c[1][1]=1;block->c[1][3]=1;break;}}/* get next block! */void NextBlock(){/* copy the nextBlock to curBlock */curBlock.size=nextBlock.size;curBlock.color=nextBlock.color;curBlock.x=(BoardWidth-4)/2;curBlock.y=-curBlock.size;memcpy(curBlock.c,nextBlock.c,16);/* generate nextBlock and show it */EraseBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);GenerateBlock(&nextBlock);nextBlock.x=1,nextBlock.y=0;DrawBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);}/* rotate the block, update the block struct data */int _INNER_HELPER RotateCells(char c[4][4],char blockSize){char temp,i,j;switch(blockSize){case 3:temp=c[0][0];c[0][0]=c[2][0], c[2][0]=c[2][2], c[2][2]=c[0][2], c[0][2]=temp; temp=c[0][1];c[0][1]=c[1][0], c[1][0]=c[2][1], c[2][1]=c[1][2], c[1][2]=temp; break;case 4: /* only 'I' block arived here! */c[1][0]=1-c[1][0], c[1][2]=1-c[1][2], c[1][3]=1-c[1][3];c[0][1]=1-c[0][1], c[2][1]=1-c[2][1], c[3][1]=1-c[3][1];break;}}/* judge if the block can move toward the direction */int CanMove(int dx,int dy){int i,j,tempX,tempY;for(i=0;i<curBlock.size;i++){for(j=0;j<curBlock.size;j++){if(curBlock.c[i][j]){/* cannot move leftward or rightward */tempX = curBlock.x + i + dx;if(tempX<0 || tempX>(BoardWidth-1)) return false; /* make sure x is valid! *//* cannot move downward */tempY = curBlock.y + j + dy;if(tempY>(BoardHeight-1)) return false; /* y is only checked lower bound, maybe negative!!!! *//* the cell already filled, we must check Y's upper bound before check cell ! */if(tempY>=0 && Board[tempX][tempY][0]) return false;}}}return true;}/* judge if the block can rotate */int CanRotate(){int i,j,tempX,tempY;/* update buffer */memcpy(BufferCells, curBlock.c, 16);RotateCells(BufferCells,curBlock.size);for(i=0;i<curBlock.size;i++){for(j=0;j<curBlock.size;j++){if(BufferCells[i][j]){tempX=curBlock.x+i;tempY=curBlock.y+j;if(tempX<0 || tempX>(BoardWidth-1))return false;if(tempY>(BoardHeight-1))return false;if(tempY>=0 && Board[tempX][tempY][0])return false;}}}return true;}/* draw the block */void _INNER_HELPER DrawBlock(Block *block,int bdLeft,int bdTop,int cellSize) {int i,j;setfillstyle(SOLID_FILL,block->color);for(i=0;i<block->size;i++){for(j=0;j<block->size;j++){if(block->c[i][j] && (block->y+j)>=0){floodfill(bdLeft+cellSize*(i+block->x)+cellSize/2,bdTop+cellSize*(j+block->y)+cellSize/2,BorderColor);}}}}/* Rotate the block, if success, return true */int RotateBlock(Block *block){char temp,i,j;int b_success;if(block->size==2)return true;if(( b_success=CanRotate())){EraseBlock(block,BoardLeft,BoardTop,CellSize);memcpy(curBlock.c,BufferCells,16);DrawBlock(block,BoardLeft,BoardTop,CellSize);}return b_success;}/* erase a block, only fill the filled cell with background color */void _INNER_HELPER EraseBlock(Block *block,int bdLeft,int bdTop,int cellSize)int i,j;setfillstyle(SOLID_FILL,BkGndColor);for(i=0;i<block->size;i++){for(j=0;j<block->size;j++){if(block->c[i][j] && (block->y+j>=0)){floodfill(bdLeft+cellSize*(i+block->x)+cellSize/2,bdTop+cellSize*(j+block->y)+cellSize/2,BorderColor);}}}}/* move by the direction if can, donothing if cannot* return value: true - success, false - cannot move toward this direction */int MoveBlock(Block *block,int dx,int dy){int b_canmove=CanMove(dx,dy);if(b_canmove){EraseBlock(block,BoardLeft,BoardTop,CellSize);curBlock.x+=dx;curBlock.y+=dy;DrawBlock(block,BoardLeft,BoardTop,CellSize);}return b_canmove;}/* drop the block to the bottom! */int DropBlock(Block *block){EraseBlock(block,BoardLeft,BoardTop,CellSize);while(CanMove(0,1)){curBlock.y++;}DrawBlock(block,BoardLeft,BoardTop,CellSize);return 0;/* return value is assign to the block's alive *//* init the graphics mode, draw the board grid */void InitGame(){int i,j,gdriver=DETECT,gmode;struct time sysTime;/* draw board cells */memset(Board,0,BoardWidth*BoardHeight*2);memset(nextBlock.c,0,16);strcpy(info_help,"P: Pause Game. --by hoodlum1980");initgraph(&gdriver,&gmode,"");setcolor(BorderColor);for(i=0;i<=BoardWidth;i++){line(BoardLeft+i*CellSize, BoardTop, BoardLeft+i*CellSize, BoardTop+ BoardHeight*CellSize);}for(i=0;i<=BoardHeight;i++){line(BoardLeft, BoardTop+i*CellSize, BoardLeft+BoardWidth*CellSize, BoardTop+ i*CellSize);}/* draw board outer border rect */rectangle(BoardLeft-CellSize/4, BoardTop-CellSize/4,BoardLeft+BoardWidth*CellSize+CellSize/4,BoardTop+BoardHeight*CellSize+CellSize/4);/* draw next block grids */for(i=0;i<=4;i++){line(NBBoardLeft+i*NBCellSize, NBBoardTop, NBBoardLeft+i*NBCellSize, NBBoardTop+4*NBCellSiz e);line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+4*NBCellSize, NBBoardTop+ i*NBCellS ize);}/* draw score rect */rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHei ght);DisplayScore();/* set new seed! */gettime(&sysTime);srand(sysTime.ti_hour*3600+sysTime.ti_min*60+sysTime.ti_sec);GenerateBlock(&nextBlock);NextBlock(); /* create first block */setcolor(DARKGRAY);outtextxy(InfoLeft,InfoTop+20,"Up -rotate Space-drop");outtextxy(InfoLeft,InfoTop+35,"Left-left Right-right");outtextxy(InfoLeft,InfoTop+50,"Esc -exit");DisplayInfo(info_help);}/* set the isFilled and fillcolor data to the board */void _INNER_HELPER FillBoardData(){int i,j;for(i=0;i<curBlock.size;i++){for(j=0;j<curBlock.size;j++){if(curBlock.c[i][j] && (curBlock.y+j)>=0){Board[curBlock.x+i][curBlock.y+j][0]=1;Board[curBlock.x+i][curBlock.y+j][1]=curBlock.color;}}}}/* draw one line of the board */void _INNER_HELPER PaintBoard(){int i,j,fillcolor;for(j=max((TopLine-4),0);j<BoardHeight;j++){for(i=0;i<BoardWidth;i++){fillcolor=Board[i][j][0]? Board[i][j][1]:BkGndColor;setfillstyle(SOLID_FILL,fillcolor);floodfill(BoardLeft+i*CellSize+CellSize/2,BoardTop+j*CellSize+CellSize/2,BorderColor); }}}/* check if one line if filled full and increase the totalScore! */void _INNER_HELPER CheckBoard()int i,j,k,score=10,sum=0,topy,lines=0;/* we find the top empty line! */j=topy=BoardHeight-1;do{sum=0;for(i=0;i< BoardWidth; i++){sum+=Board[i][topy][0];}topy--;} while(sum>0 && topy>0);/* remove the full filled line (max remove lines count = 4) */do{sum=0;for(i=0;i< BoardWidth; i++)sum+=Board[i][j][0];if(sum==BoardWidth)/* we find this line is full filled, remove it! */ {/* move the cells data down one line */for(k=j; k > topy;k--){for(i=0;i<BoardWidth;i++){Board[i][k][0]=Board[i][k-1][0];Board[i][k][1]=Board[i][k-1][1];}}/*make the top line empty! */for(i=0;i<BoardWidth;i++){Board[i][topy][0]=0;Board[i][topy][1]=0;}topy++; /* move the topline downward one line! */lines++; /* lines <=4 */TotalScore+=score;score*=2; /* adding: 10, 30, 70, 150 */}elsej--;} while(sum>0 && j>topy && lines<4);/* speed up the game when score is high, minimum is 400 */FrameTime=max(1200-100*(TotalScore/200), 400);TopLine=topy;/* update the top line *//* if no lines remove, only add 1: */if(lines==0)TotalScore++;}/* display the score */void _INNER_HELPER DisplayScore(){setcolor(BkGndColor);outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);setcolor(ScoreColor);sprintf(info_score,"Score: %d",TotalScore);outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);}/* we call this function when a block is inactive. */void UpdateBoard(){FillBoardData();CheckBoard();PaintBoard();DisplayScore();}/* pause the game, and timer handler stop move down the block! */ int PauseGame(){int key=0;DisplayInfo("Press P to Start or Resume!");while(key!=K_P && key!=K_ESC){while(!(key=GetKeyCode())){}}DisplayInfo(info_help);return key;}/* quit the game and do cleaning work. */void QuitGame(){closegraph();}/* the entry point function. */void main(){int i,flag=1,j,key=0,tick=0;InitGame();if(PauseGame()==K_ESC)goto GameOver;/* wait until a key pressed */while(key!=K_ESC){/* wait until a key pressed */while(!(key=GetKeyCode())){tick++;if(tick>=FrameTime){/* our block has dead! (can't move down), we get next block */ if(!MoveBlock(&curBlock,0,1)){UpdateBoard();NextBlock();if(!CanMove(0,1))goto GameOver;}tick=0;}delay(100);}switch(key){case K_LEFT:MoveBlock(&curBlock,-1,0);break;case K_RIGHT:MoveBlock(&curBlock,1,0);break;case K_DOWN:MoveBlock(&curBlock,0,1);break;case K_UP:RotateBlock(&curBlock);break;case K_SPACE:DropBlock(&curBlock);break;case K_P:PauseGame();break;}}GameOver:DisplayInfo("GAME OVER! Press any key to exit!"); getch(); /* wait the user Press any key. */QuitGame();}。