资源描述:
扫雷4.1系统概述参阅现有的扫雷游戏,设计有良好人机交互界面的程序;鼓励用可视化的人机交互设计,如菜单、按钮,可基于MFC、Qt等开发工具。4.2系统框架结构和算法思想(记得改成多字符型)框架结构:①:一个扫雷难度选择窗口,选择后,输出扫雷的地图,如何开始进行扫雷:②:左键打开格子,右键插旗子,当打开格子后遇到雷,则输掉比赛;③:将雷除外的格子全部点卡,则胜利;④:无论输赢,系统都会提示是否继续游戏,还是结束退出游戏。算法思想:①:先进行初始化界面:先创建一个二维数组,赋值为0,头文件#include与srand(unsigned)time(NULL)用于生成随机数,运用for循环与随机数,给数组中的MineNum(就是雷的数量)个元素随机赋值为-1,当作雷;将为-1的元素的周围九宫格的元素都+1,并且还要考虑边界的问题;②:进行加载图片:先定义IMAGEimgs[12]数组以及#include头文件,在创建的项目文件夹中,加入扫雷所需图片的文件夹,设一个加载函数,设一个char类型的数组,在for循环中运用sprintf_s函数以及loadimage函数用于加载文件夹中的图片,并且将图片全部转化为相同的大小。③:绘制地图:将主函数定义的数组传入,运用for循环,将元素值为0~8的元素贴上对应的数字图,给值为-1的元素贴上雷的图,并且在主函数中,再运用initgraph函数创建一个扫雷界面的窗口;④:将上面的地图进行覆盖:即将每个元素值+20进行加密处理,即元素值变为了19~28,然后进行覆盖贴图,将数字与雷的图覆盖掉;⑤:加载鼠标点击操作:左键打开格子,即解密,将元素值-20,显示出覆盖前的图片;右键插小旗子图片,给没有左键打开的元素再+20,并且加载旗子的图片,再一次右键则-20,恢复原来的图片;⑥:使鼠标能够打开格子,插旗子:再while循环中,创建ExMessagemsg结构体,然后再用一个while循环用于获取鼠标的不断点击,即左键与右键;⑦:输出空地:先判断鼠标左键点开后的格子的元素值是否为0(即空地),如果符合,则将它周围的九宫格全部打开,并且要设一个if的判断语句。防止越界;⑧:创建一个函数用于游戏结束:如果打开覆盖的格子是雷(即元素值为-1),则返回-1;如果不是,创建一个整型变量,当点开非-1的格子都+1;运用if,判断,是否打开了全部的非雷的格子,如果是则返回1,否则返回0;在主函数的鼠标点击获取函数中,接收返回的值,运用MessageBox函数以及GetHWnd函数,用于提示游戏的胜利、失败。以及是否要继续游戏。⑨:设头文件#include与#pragmacomment(lib,”winmm.lib”)用于扫雷的声音加载,用PlaySound函数用于加载文件夹中的扫雷的声音资源,并运用于各功能模块中;⑩:最后是在扫雷窗口前再建一个窗口,用于选择扫雷的简单、中等、困难三种难度(即设置雷的数量),运用类似上面构造扫雷地图的方法,给选择难度窗口初始化界面,贴图,设置鼠标点击功能,三种难度中对应着不同的雷的数量,将这个窗口放在扫雷窗口的前面,用于开始游戏时的选择窗口,考虑到赢了或者输了游戏后,可以返回到这个窗口,则要将这个窗口弄进一个函数中,并将扫雷的窗口也加进去,利用MessageBox返回这个函数,即能返回选择窗口。4.3功能模块实现4.4系统测试,,,4.5系统设计总结通过此处扫雷游戏的设计,我学会了如何使用easyx.h来进行图片的加载与运用,来创建扫雷的难度选择菜单以及扫雷的游戏界面。以及如何初始化扫雷地图界面,运用库函数来获取鼠标左键、右键的点击功能,赋予它扫雷游戏的开格子、插旗子的能力。并且能熟练地掌握随机生成数的使用。对扫雷游戏的制作有了更加透彻的理解,也对游戏的制作与运行有了更加深刻的感慨。并且初步了解、学习了如何加载扫雷的音效,以及如何使用扫雷的各项音效。,代码#include#include#include//随机生成数#include//随机生成数可以变#include//图片usingnamespacestd;//播放音乐#include//easyx的#pragmacomment(lib,"winmm.lib")//c语言库#defineROW15#defineCOL15intMineNum=50;IMAGEimgs[12];//12张图片IMAGEimgs1[13];//是不是最后一次递归,下面点空格的声音的秒开boolisfinally=true;voidShow(intmap[][COL]);voidinit(intmap[][COL]);voidloadReasouce(intmap[][COL]);voiddraw(intmap[][COL]);voidmouseMsg(ExMessage*msg,intmap[ROW][COL]);voidBoomBlank(intmap[ROW][COL],intindex,intindey);intjudge(intmap[ROW][COL],introw,intcol);voidShow1(intmap1[10][10]);voidinit1(intmap1[10][10]);voidloadReasouce1(intmap1[10][10]);voiddraw1(intmap1[10][10]);intmouseMsg1(ExMessage*msg1,intmap1[10][10]);voidselection();intmain(){//随机种子srand((unsigned)time(NULL));selection();,initgraph(40*ROW,40*COL,EW_SHOWCONSOLE);//因为后面已经将图片全部强制转化成40×40,所以这边是400400,输入宽高控制台//删掉后面那个控制台也可以,就是只剩输出的图片//播放开始音乐,这两种都可以,但是注意空格,十分严格//mciSendString("open./扫雷图片资源/start.mp3",NULL,0,NULL);//mciSendString("play./扫雷图片资源/start.mp3",NULL,0,NULL);mciSendString("open./扫雷图片资源/start.mp3aliasbgm",NULL,0,NULL);mciSendString("playbgm",NULL,0,NULL);intmap[ROW][COL]={0};init(map);while(true){//处理消息,鼠标ExMessagemsg;//弄了个结构体while(peekmessage(&msg,EM_MOUSE))//再写一个循环,因为要一直点击{//获取鼠标的点击,左键打开格子//破密,右键插小旗子,即标记雷{switch(msg.message)//获取{caseWM_LBUTTONDOWN://左键caseWM_RBUTTONDOWN://右键mouseMsg(&msg,map);intret=judge(map,msg.y/40,msg.x/40);//printf("judge=%d
1",ret);if(ret==-1){draw(map);intselect=MessageBox(GetHWnd(),"怎么会输了呢,再来一把把","你是真的菜",MB_OKCANCEL);if(select==IDOK){init(map);}else{selection();}},elseif(ret==1){intselect=MessageBox(GetHWnd(),"你已经赢了","你是真棒",MB_OKCANCEL);if(select==IDOK){init(map);}else{exit(0);}}break;}}}draw(map);}Show(map);getchar();return0;}//初始化扫雷地图生成一个二维数组,并且全部是零。voidShow(intmap[][COL]){for(inti=0;i2');}}voidinit(intmap[][col]){loadreasouce(map);>=0&&r=0&&c=0&&map[i][k]<=8){//是什么数据就贴什么图putimage(k*40,i*40,&imgs[map[i][k]]);//因为数组第一个为0,0*40都为0,所以我们在弄坐标时,要把行列交换就可以了//就将k与i换下位置,这个不是所理解的行乘35;}//贴图,加载雷图elseif(map[i][k]==-1){putimage(k*40,i*40,&imgs[9]);}//贴完图,准备覆盖,在上面给它进行了加密20elseif(map[i][k]>=19&&map[i][k]<=28){,putimage(k*40,i*40,&imgs[10]);}//加载小旗子贴图elseif(map[i][k]>=39){putimage(k*40,i*40,&imgs[11]);}}}}//鼠标点击操作voidmouseMsg(ExMessage*msg,intmap[ROW][COL]){//先根据鼠标的点击来确定我们数组的下标intc=msg->x/40;//这就是我们的列,即横坐标除于40(每个格子的大小都是40×40)intr=msg->y/40;//这就是我们的行,即纵坐标除于40//左键打开地图格子if(msg->message==WM_LBUTTONDOWN){//什么时候打开格子,没有的打开的时候点开格子,已经点开的就不要点了if(map[r][c]>=19&&map[r][c]<=28){//左键点击声音PlaySound("./扫雷图片资源/click.wav",NULL,SND_ASYNC|SND_FILENAME);map[r][c]-=20;//刚刚加密,现在要解密BoomBlank(map,r,c);isfinally=true;//空格打开炸的声音system("cls");Show(map);//可以看出我们点了后,那些数字的变化}}//右键开始插小旗子elseif(msg->message==WM_RBUTTONDOWN){//右键插小旗子的声音PlaySound("./扫雷图片资源/rightClick.wav",NULL,SND_ASYNC|SND_FILENAME);,if(map[r][c]>=19&&map[r][c]<=28){map[r][c]+=20;system("cls");Show(map);}elseif(map[r][c]>=39)//如果把等号去掉,标记的旗子如果是雷,就取消不了{map[r][c]-=20;//取消旗子system("cls");Show(map);}}}//当点击空地的时候,炸开周围(九宫格)的空格,并且炸开数字[0~8]voidBoomBlank(intmap[ROW][COL],intindex,intindey){//先找到空地//判断鼠标(左键)所点的是否为空地if(map[index][indey]==0){for(intx=index-1;x<=index+1;x++){for(inty=indey-1;y<=indey+1;y++){//判断炸开什么//炸开空地为中心的九宫格,包括数字//还要考虑越界的问题!!!!//判定数字范围为数字[0~8],防止越界if((x>=0&&x=0&&y=19&&map[x][y]<=28){//空白格子把旁边炸开的声音PlaySound("./扫雷图片资源/search.wav",NULL,SND_ASYNC|SND_FILENAME);map[x][y]-=20;//递归BoomBlank(map,x,y);}},}}}//游戏结束条件//胜利返回1,失败返回-1,没结束返回0intjudge(intmap[ROW][COL],introw,intcol){//点完全部格子胜利,,100个格子,10个雷,要点90个格子//点到雷输了//游戏结束,返回-1if(map[row][col]==-1){return-1;}//游戏胜利返回1,cnt用于记录点击了多少个格子intcnt=0;for(inti=0;i=0&&map[i][k]<=8){cnt++;}}}if(cnt==90){return1;}return0;}voidShow1(intmap1[10][10]){for(inti=0;i<10;i++){for(intk=0;k<10;k++){cout<<""<x/35;//这就是我们的列,即横坐标除于35(每个格子的大小都是35)intr=msg1->y/35;//这就是我们的行,即纵坐标除于35//左键打开地图格子if(msg1->message==WM_LBUTTONDOWN){//什么时候打开格子,没有的打开的时候点开格子,已经点开的就不要点了if(map1[r][c]>=-4&&map1[r][c]<=-1){//左键点击声音PlaySound("./扫雷图片资源/click.wav",NULL,SND_ASYNC|SND_FILENAME);MineNum=30;tt++;}if(map1[r][c]>=-8&&map1[r][c]<=-5){//左键点击声音PlaySound("./扫雷图片资源/click.wav",NULL,SND_ASYNC|SND_FILENAME);MineNum=40;tt++;}if(map1[r][c]>=-12&&map1[r][c]<=-9){//左键点击声音PlaySound("./扫雷图片资源/click.wav",NULL,SND_ASYNC|SND_FILENAME);,MineNum=50;tt++;}}//右键开始插小旗子elseif(msg1->message==WM_RBUTTONDOWN){//右键插小旗子的声音PlaySound("./扫雷图片资源/rightClick.wav",NULL,SND_ASYNC|SND_FILENAME);if(map1[r][c]>=-4&&map1[r][c]<=-1){//右键插小旗子的声音PlaySound("./扫雷图片资源/rightClick.wav",NULL,SND_ASYNC|SND_FILENAME);MineNum=30;}if(map1[r][c]>=-8&&map1[r][c]<=-5){//右键插小旗子的声音PlaySound("./扫雷图片资源/rightClick.wav",NULL,SND_ASYNC|SND_FILENAME);MineNum=40;}if(map1[r][c]>=-12&&map1[r][c]<=-9){//右键插小旗子的声音PlaySound("./扫雷图片资源/rightClick.wav",NULL,SND_ASYNC|SND_FILENAME);MineNum=50;}}returntt;}voidselection(){initgraph(350,350,EW_SHOWCONSOLE);intrr=0;,intmap1[10][10]={0};init1(map1);while(true){ExMessagemsg1;while(peekmessage(&msg1,EM_MOUSE)){//获取鼠标点击(左右键)switch(msg1.message){caseWM_LBUTTONDOWN://鼠标左键caseWM_RBUTTONDOWN://鼠标右键rr=mouseMsg1(&msg1,map1);break;}if(rr>0){break;}}draw1(map1);if(rr>0){break;}}Show1(map1);initgraph(40*ROW,40*COL,EW_SHOWCONSOLE);//因为后面已经将图片全部强制转化成40×40,所以这边是400400,输入宽高控制台//删掉后面那个控制台也可以,就是只剩输出的图片//播放开始音乐,这两种都可以,但是注意空格,十分严格//mciSendString("open./扫雷图片资源/start.mp3",NULL,0,NULL);//mciSendString("play./扫雷图片资源/start.mp3",NULL,0,NULL);mciSendString("open./扫雷图片资源/start.mp3aliasbgm",NULL,0,NULL);mciSendString("playbgm",NULL,0,NULL);intmap[ROW][COL]={0};,init(map);while(true){//处理消息,鼠标ExMessagemsg;//弄了个结构体while(peekmessage(&msg,EM_MOUSE))//再写一个循环,因为要一直点击{//获取鼠标的点击,左键打开格子//破密,右键插小旗子,即标记雷{switch(msg.message)//获取{caseWM_LBUTTONDOWN://左键caseWM_RBUTTONDOWN://右键mouseMsg(&msg,map);intret=judge(map,msg.y/40,msg.x/40);//printf("judge=%d
3",ret);if(ret==-1){draw(map);intselect=MessageBox(GetHWnd(),"怎么会输了呢,再来一把把","你是真的菜",MB_OKCANCEL);if(select==IDOK){init(map);}else{selection();}}elseif(ret==1){intselect=MessageBox(GetHWnd(),"你已经赢了","你是真棒",MB_OKCANCEL);if(select==IDOK){init(map);}else{exit(0);,}}break;}}}draw(map);}Show(map);getchar();}
|
4');}}voidinit(intmap[][col]){loadreasouce(map);>