本文实例为大家分享了C++实现俄罗斯方块的具体代码,供大家参考,具体内容如下
先是效果图:
主菜单:
游戏:
设置:
错误处理:
代码:
#include#include #include #include #include #include #include #pragma comment( lib,"winmm.lib" ) //定义 //方块 #define NO 0 #define SQR 1 //碰撞检测 #define OK 0 #define CANTMOVE 1 //方向 #define UP 0 #define DOWN 1 #define LEFT 2 #define RIGHT 3 //错误码 #define no_enough_memory 0 #define set_no_found 1 #define dat_no_found 2 #define error_argument 3 //函数声明 //模块 void play();//开始游戏 void sets();//设置 void highscores();//排行榜 void copyright();//作者 //功能 void mapsetup();//准备地图 bool newsqr();//放置方块,返回是否游戏结束 int move(int direction);//移动方块,返回定义表 void movetomap();//把当前方块移动到地图上 int wholeline();//检查是否组成了一层,返回层数,-1表示没有 void deleteline(int which);//删除一行 void endup();//结束游戏,清理内存 //显示 void show();//刷新画面 void showmenu(char* menu);//显示菜单 //文件 void loadset();//加载设置 void saveset();//保存设置 void loadhs();//加载排行榜 bool addscores(int score,char name[50]);//增加一个分数,返回是否是高分 void savehs();//保存排行榜 //坐标变换 int get(int x,int y); void set(int x,int y,int date); //结构 //设置 struct{ int xs,ys;//屏幕大小 int speed;//速度 char sqr[3],no[3],frame[3];//方块、空白处、边框的样式 }gameset; //排行榜 struct{ char name[50]; int score; }rating[10]; //全局变量 //变量 int* map=NULL;//地图 bool now[4][4];//当前方块 int xnow,ynow;//当前位置 int guide;//分数 //常量 const bool shap[7][4][4]={//形状 {\ 0,0,0,0,\ 0,0,0,0,\ 1,1,1,1,\ 0,0,0,0,\ },\ {\ 0,0,0,0,\ 0,1,1,0,\ 0,1,1,0,\ 0,0,0,0,\ },\ {\ 0,0,0,0,\ 0,1,1,1,\ 0,0,1,0,\ 0,0,0,0,\ },\ {\ 0,0,0,0,\ 1,0,0,0,\ 1,1,1,0,\ 0,0,0,0,\ },\ {\ 0,0,0,0,\ 0,0,0,1,\ 0,1,1,1,\ 0,0,0,0,\ },\ {\ 0,1,0,0,\ 0,1,1,0,\ 0,0,1,0,\ 0,0,0,0,\ },\ {\ 0,0,1,0,\ 0,1,1,0,\ 0,1,0,0,\ 0,0,0,0,\ }\ }; const char errword[4][50]={"程序没能取得足够的内存","无法打开或找不到设置文件set.ini","无法打开或找不到排行榜数据highscore.dat","您设置的参数太大或者太小"}; //控制台 HANDLE hout;//控制台句柄 COORD curpos={0,0};//光标坐标 //主函数 int main() { start1: try { hout = GetStdHandle(STD_OUTPUT_HANDLE);//获取控制台句柄,以便移动光标 srand(time(0));//用当前时间初始化随机数生成器 loadset();//加载 loadhs(); start2: while(1) { showmenu("俄罗斯方块\n请选择菜单:\n1.开始游戏\n2.设置\n3.排行榜\n4.帮助\n5.保存并退出\n"); switch(getch()) { case '1': system("cls");//play函数覆盖界面而不是清屏,所以需要先清屏 play(); break; case '2': sets(); break; case '3': highscores(); break; case '4': copyright(); break; case '5': savehs();//保存数据 saveset(); return 0; } } } catch(int errnum)//错误处理 { system("cls"); printf("o(>﹏<)o 出错啦!\n程序收到了一条错误信息,错误码是:%d(%s)\n您可以联系我们解决这个问题。\n",errnum,errword[errnum]); printf("\n你可以选择以下操作:\n1.重启程序\n2.以默认设置重启程序\n3.向设置和数据文件写入默认设置然后重启\n4.退出\n"); switch(getch()) { case '1': goto start1; case '2': gameset.xs=20; gameset.ys=20; gameset.speed=100; strcpy(gameset.sqr,"[]");//无法直接给数组复制数据 strcpy(gameset.no," "); strcpy(gameset.frame,"::"); int i; for(i=0;i<10;i++) strcpy(rating[i].name,"未命名"),rating[i].score=0; goto start2; case '3': { ofstream fout; fout.open("set.ini"); fout<<"20\n20\n100[]\n \n::\n"; fout.close(); fout.clear(); fout.open("highscore.dat"); int j; for(j=0;j<10;j++) fout<<"未命名\n0\n"; goto start1; } default: return -1;//返回异常退出 } } return 0; } void play() { mapsetup();//初始化 /*for(int i=0;i<20;i++) set(i,19,SQR);*/ while(newsqr())//不断新建方块,直到返回NO { while(move(DOWN)!=CANTMOVE)//每次向下移动方块,直到不能移动 { guide+=1;//向下移动一次加1分 show();//显示 while(kbhit())//不断处理键盘,直到没有按键 { switch(getch())//获取按键 { case 'w': move(UP); break; case 's': move(DOWN); break; case 'a': move(LEFT); break; case 'd': move(RIGHT); break; } } Sleep(gameset.speed);//延时 } movetomap();//退出循环时无法向下移动,把当前方块移动到地图上 int line; while((line=wholeline())!=-1);//不断检查是否出现整行,直到没有 deleteline(line);//删除整行 } endup();//无法新建方块,游戏结束 return;//结束 } //函数定义 void mapsetup() { map=new int[gameset.xs*gameset.ys];//申请内存 if(!map)//如果申请到0 throw no_enough_memory;//抛出异常 //初始化地图 int i,j; for(i=0;i =0&&x =0&&y =0&&x =0&&y 0&&x 0&&y 0;i--)//旋转随机0-3次 move(UP); xnow=gameset.xs/2;//设置坐标 ynow=-4; return true; } int move(int direction){ int x,y;//储存坐标偏移量 int i,j; switch(direction) { case UP://上键是旋转 bool newshap[4][4];//储存旋转后的图形 for(i=0;i<4;i++) { for(j=0;j<4;j++) { newshap[i][j]=now[j][3-i];//坐标变换 } } for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(newshap[i][j]==true&&get(xnow+i,ynow+j)==SQR)//对新图形碰撞检测 return CANTMOVE;//不能旋转 } } for(i=0;i<4;i++) { for(j=0;j<4;j++) { now[i][j]=newshap[i][j];//检测完毕,复制形状 } } return OK; case DOWN://先记录坐标的偏移量,确定没有碰撞以后移动 x=0,y=1; break; case LEFT: x=-1;y=0; break; case RIGHT: x=1,y=0; break; } for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(now[i][j]==true&&get(i+x+xnow,j+y+ynow)==SQR)//如果和地图上的方块重合(边缘以外get函数也返回SQR,不必单独处理)//if(get(i+x,j+y)==SQR)//if(now[i+x][j+y]==SQR) { return CANTMOVE;//无法移动 } } } xnow+=x;//检测完毕,更改坐标 ynow+=y; return OK; } void movetomap(){ guide+=10;//成功放置方块,加10分 int i,j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(now[i][j]==true) set(xnow+i,ynow+j,SQR);//复制方块到地图 } } return; } int wholeline(){ int i,j; bool whole;//储存是否是整行 for(j=0;j =0;i--) { for(j=0;j =xnow&&i<(xnow+4)&&j>=ynow&&j<(ynow+4))//if(i>=xnow&&i<(xnow+1)&&j>=ynow&&j<(ynow+1))//在当前方块范围内 { if(now[i-xnow][j-ynow]==true)//如果有方块 printf(gameset.sqr); else if(get(i,j)==SQR)//如果地图有方块 printf(gameset.sqr); else//否则,空白 printf(gameset.no); } else//不在当前方块范围内,输出地图 { if(get(i,j)==SQR)//有方块 printf(gameset.sqr); else//否则,没方块 printf(gameset.no); } } printf("::\n");//右边框和换行 } for(i=0;i 70) throw error_argument; break; case '2': scanf("%d",&gameset.ys); if(gameset.ys<15||gameset.ys>70) throw error_argument; break; case '3': scanf("%d",&gameset.speed); if(gameset.speed<0) throw error_argument; break; case '4': cin.getline(&gameset.sqr[0],3);//scanf("%s",&gameset.sqr[0]); cout< >gameset.xs>>gameset.ys>>gameset.speed; fin.getline(gameset.sqr,4);//获取整行,因为可能有空格 fin.getline(gameset.no,4); fin.getline(gameset.frame,4); return; } void saveset() { ofstream fout;//输出文件流 fout.open("set.ini",ifstream::out|ios::nocreate); if(!fout) throw set_no_found; fout< >rating[i].name>>rating[i].score; return; } bool addscores(int score,char name[50]) { int i,j; for(i=0;i<10;i++)//枚举 { if(rating[i].score i;j--)//移动数据空出位置 { for(int k=0;k<50;k++) rating[j].name[k]=rating[j-1].name[k]; rating[j].score=rating[j-1].score; } rating[i].score=score;//插入数据 strcpy(rating[i].name,name); return true;//返回进入排行 } } return false;//返回没有进入 } void savehs() { int i; ofstream fout; fout.open("highscore.dat",ifstream::out|ios::nocreate); if(!fout) throw dat_no_found; for(i=0;i<10;i++) fout<
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。