C++俄罗斯方块源码完整功能版.docx
- 文档编号:6315570
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:24
- 大小:216.42KB
C++俄罗斯方块源码完整功能版.docx
《C++俄罗斯方块源码完整功能版.docx》由会员分享,可在线阅读,更多相关《C++俄罗斯方块源码完整功能版.docx(24页珍藏版)》请在冰豆网上搜索。
C++俄罗斯方块源码完整功能版
先是效果图:
主菜单:
游戏:
设置:
错误处理:
627行,代码如下:
#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 { for(j=0;j { set(i,j,NO); } } guide=0;//分数清零 return; } int get(int x,int y) { if(y<0)//上方虚拟为空 return NO; if(x>=0&&x return *(map+y*gameset.xs+x);//提取数据 else return SQR;//虚拟地图侧面和底部有方块 } void set(int x,int y,int date) { if(x>=0&&x *(map+y*gameset.xs+x)=date;//写入 return; } bool newsqr(){ int i,j; for(i=0;i<4;i++)//检查下一个方块要出现的地方是否有方块 if(get(gameset.xs/2+i,0)==SQR) return false;//有方块,创建失败 int which=rand()%7;//随机选择形状 for(i=0;i<4;i++) { for(j=0;j<4;j++) { now[i][j]=shap[which][i][j];//复制形状 } } for(i=rand()%4;i>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 { whole=true;//假设是整行 for(i=0;i { if(get(i,j)==NO) whole=false;//有空,不是整行 } if(whole) return j;//是整行,返回 } return -1;//没找到整行,返回 } void deleteline(int which){ int i,j; guide+=1000;//消方块,奖励分数 for(i=which;i>=0;i--) { for(j=0;j { set(j,i,get(j,i-1));//移动上面的所有方块,覆盖这一行。 最上面虚拟成了空,不必特殊处理 } } return; } void endup(){ delete map;//清理内存 system("cls"); while(kbhit())//清除所有未处理的按键 getchar(); showmenu("游戏结束,请输入您的姓名: "); char name[50]="noname"; scanf("%s",&name[0]);//输入 char word[1000];//储存格式化以后的字符串 sprintf(&word[0],"游戏结束! \n\n您(%s)的积分是: %d\n\n%s\n\n请按任意键继续···\n",name,guide,((addscores(guide,name))? "你进入了排行榜": "你没有进入排行榜")); showmenu(&word[0]); getch(); highscores();//显示排行榜 savehs();//保存排行榜 return; } void show(){ int i,j; SetConsoleCursorPosition(hout,curpos);//system("cls");//光标移至左上角,覆盖之前的图案 printf("当前积分: %d\n",guide); for(i=0;i printf(gameset.frame); printf("\n"); for(j=0;j { printf(gameset.frame);//左边框 for(i=0;i { if(i>=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 printf(gameset.frame); printf("\n"); return; } void showmenu(char* menu) { int i,j; char output[100];//储存本行的文字 system("cls"); for(i=0;i
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 俄罗斯方块 源码 完整 功能