扫雷游戏课程设计报告

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

(一)需求分析题目:32、实现一个N*M的扫雷游戏设计要求:能够实现一个N*M的扫雷游戏a、能够打开一个方格(由于做的是静态显示,故在控制台上方格用‘—’代替),已打开的方格不能关闭b、能够标记一个方格,标记方格的含义是对该方格有雷的预测(并不表示真的一定有雷)c、能够给出游戏结果:输、赢d、N和M可由玩家自己设置系统功能需求分析:一个数字和一个雷(boom)。你可以打开(open)一个方格,如果你打开的是一个boom,那么就失败;否则就会打开一个数字,该数字是位于[0,8]的一个整数,该数字表示其所有邻居方格所包含的雷数,应用该信息可以帮助你扫雷。点击到了某区域发现其周围没有雷,那么显而易见应该点开周围的区域,拓展空白区域(二)概要设计由于知识储备不足,VC中的MFC应用程序又过于复杂,故退而求其次,不再采用动态显示和界面图形化,采用静态显示来实现扫雷游戏中的主要功能。用键盘上的‘1’键代替鼠标左击,即打开一个方格查看其属性,已打开的方格不能在关闭;用键盘上的‘2’键代替鼠标右击,即标记一个方格,标记方格的含义是对该方格有雷的预测(并不表示真的一定有雷)用键盘上的‘↑’‘↓’‘←’‘→’四个键来实现光标在控制台上的自由移动,相当于用鼠标实现光标在图形界面的移动游戏区域的高度与宽度及总雷数可由玩家自己设定应题目要求设计了一个基类:Base和一个继承类:Game。基类Base主要实现一些基本功能:游戏结束时输出游戏的结果:输赢;返回控制台上光标的位置返回按下键时所对应的按键控制符基类Base:类名成员类别类型成员名描述Base方法staticintOutput(constchar*)在当前位置上输出一串字符staticintGotoXY(int,int);取得控制台上光标的坐标位置并返回staticintGetKey();等待按下键,并返回所对应的按键控制符继承类Game是本程序的主要内容,也是实现扫雷游戏的关键部分。主要实现的功能:初始化图形界面,把游戏区域在控制台上显示出来;利用随机函数进行随机布雷,以保证玩家每次玩游戏时雷的分布位置均不同;得到一个坐标位置周围的雷数,并把数值返回;在一个坐标点上(x,y)点击,在该位置上显示其周围的雷数或拓展空白区域或失败;如果一个坐标点的周围没有雷,则拓展空白区域,并递归拓展;其中saolei()函数是类Game里的关键函数体,用来判断玩家按下了哪个键,并作出相应反应(上下左右四个方向的移动,打开一个方格,标记一个方格),并判断游戏的输与赢继承类Game:类名成员类别类型成员名描述Game属性intcurX,curY光标位置intpoolWidth,poolHeight游戏区域的高度与宽度intpool[GAME_MAX_HEIGHT+1][GAME_MAX_WIDTH+1]用二维数组来存储雷的相关属性conststaticintGMARK_BOOM;GMARK_EMPTYGMARK_MARK;雷的属性:雷(*),空,标记(#)方法intinitpool(int,int,int)初始布雷IntMoveCursor()移动光标inthuatu(int)在控制台上把扫雷区域显示出来inttryopen(int,int)在一个坐标点上(x,y)点击,在该位置上显示其周围的雷数或拓展空白区域或失败intshownum(int,int)得到一个坐标位置周围的雷数,并把数值返回inttuozhan(int,int)如果一个坐标点的周围没有雷,则拓展空白区域,并递归拓展intsaolei()扫雷并判断输赢(三)详细设计核心算法:(1)布雷函数:初始化时把数组里的值全部置为0,然后利用srand(),rand()随机机制产生随机数,分别对列和行取模,便产生了雷的随机位置。但是布雷前,先要判断此随机位置是否已经布上了雷。intGame::initpool(intwidth,intheight,intnum){poolWidth=width;poolHeight=height;if(num0||num=width*height||widthGAME_MAX_HEIGHT||width=0||height=0||heightGAME_MAX_HEIGHT)return1;//初始是把游戏区域也即是数组里的值全都置为0for(inty=0;y=height+1;y++){for(intx=0;x=width+1;x++){pool[y][x]=0;}}//利用伪随机函数进行随机布雷,以保证每次点击游戏时雷的分布位置不同srand(time(NULL));while(num!=0){intx=rand()%width+1;inty=rand()%height+1;if(pool[y][x]==0){pool[y][x]=GMARK_BOOM;num--;//num为设置的总雷数}}//初始化光标位置curX=1;curY=1;MoveCursor();return0;}(2)打开方格,查看方格的属性//在该位置上显示其周围的雷数或拓展空白区域或失败intGame::tryopen(intx,inty){intm=0;if(pool[y][x]&GMARK_BOOM)m=-1;else{intcount=shownum(x,y);if(count==0)tuozhan(x,y);//拓展空白区域elsepool[y][x]=count;}returnm;}(3)获得周围雷的数目扫描其周围的所有相邻方格,记录雷数,并把值返回;扫描前要选择合理的起始点intGame::shownum(intx,inty){intcount=0;for(intY=-1;Y=1;Y++)for(intX=-1;X=1;X++){if(pool[y+Y][x+X]&GMARK_BOOM)count++;}returncount;}(4)展拓空白区域展拓原因:当玩家点击的方块周围无雷时,此方块会被绘为空白,此时没有必要让玩家将其周围一一点开,应直接打开展拓条件:周围雷数为零函数inttuozhan(intx,inty)参数:x,y所点击的方块位置算法:递归递归结束条件:某一个方块不需要拓展就是因为其周围的雷数不是零intGame::tuozhan(intx,inty){if((x0&&x=poolWidth)&&(y0&&y=poolHeight)&&(pool[y][x]==0)){intcount=shownum(x,y);if(count==0){pool[y][x]=GMARK_EMPTY;for(intY=-1;Y=1;Y++)for(intX=-1;X=1;X++){tuozhan(x+X,y+Y);}}elsepool[y][x]=count;}return0;}(5)在控制台上把扫雷区域显示出来在还未按键时,调用huatu()函数把游戏界面在控制台上显示出来,即全部显示为方格。以后每按键一次。刷新一次界面intGame::huatu(intn=0){for(inty=1;y=poolHeight;y++){Base::GotoXY(1,y);for(intx=1;x=poolWidth;x++){if(pool[y][x]==0)putchar('.');elseif(pool[y][x]==GMARK_EMPTY)putchar('');elseif(pool[y][x]0&&pool[y][x]=8)putchar('0'+pool[y][x]);elseif(n==0&&(pool[y][x]&GMARK_MARK))putchar('#');elseif(pool[y][x]&GMARK_BOOM){if(n!=0)putchar('*');elseputchar('.');}}}return0;}(6)判断是否胜利判断游戏是否胜利的条件在saolei()函数体内,在主函数里调用saolei()进行循环,直到戏赢了或输了才退出循环,并在控制台上输出结果;游戏赢了返回1,按下ESC键退出游戏返回-1,记为输,扫到雷也是返回-1判断是否赢了游戏:按下键‘1’后,对整个游戏区域进行检测,如果检测不到值为0的方格,即所有的雷已被扫出,则返回1,游戏胜利;按下ESC键退出游戏和扫到雷均为输,返回-1if(Key==KEY_1)//判断是否赢了游戏{inty=1;for(;y=poolHeight;++y){intx=1;for(;x=poolWidth;++x){if(pool[y][x]==0)break;}if(x=poolWidth)break;}if(!(y=poolHeight)){m=1;}}(四)调试分析及测试(1)由玩家设置游戏区域的高度与宽度,并设置总雷数按下回车键后界面如下:按下键‘1’开始扫雷,扫雷过程部分界面如下:…………游戏输时显示的结果:(2)直接按下ESC键时输掉游戏:然后按下回车键后,直接按下ESC键,结果如下:(3)为了使快速赢得游戏,减少雷的数目:游戏运行过程部分界面如下:按下键‘2’对怀疑有雷的区域进行标记游戏胜利时显示的界面:(五)源程序附录源程序:#includeiostream#includeiostream.h#includectime//包含伪随机数发生函数#includewindows.h//包含返回一个字符在控制台屏幕上坐标的文件#includeconio.h//包含getch()库函数:从控制台读取一个字符,但不显示在屏幕上//#define定义的一些宏变量//键盘上上、下、左、右四个键及一些按键对应的ASCII编码#defineKEY_UP0xE048#defineKEY_DOWN0xE050#defineKEY_LEFT0xE04B#defineKEY_RIGHT0xE04D#defineKEY_ESC0x001B#defineKEY_1'1'#defineKEY_2'2'//设置游戏区域的最大长度与高度#defineGAME_MAX_WIDTH100#defineGAME_MAX_HEIGHT100//游戏初始时在控制台上输出的游戏提示#defineGAMETITLEArrowKey:MoveCursorKEY1:OpenKey2:Mark//当游戏结束时输出的字符#defineGAMEWINCongratulations!YouWin!Thankyouforplaying!\n#defineGAMEOVERSorry,youlose!thankyouforplaying!\n#defineGAMEENDPressESCtoexit\n//基类//BaseclassclassBase{public:staticintOutput(constchar*);staticintGotoXY(int,int);staticintGetKey();};intBase::GetKey()//等待按下键,并返回所对应的按键控制符{intnkey=getch(),nk=0;if(nkey=128||nkey==0)nk=getch();//等待你按下任意键后,把该键字符所对应的ASCII符付给nk后,在执行下面语句returnnk0?nkey*256+nk:nkey;}intBase::GotoXY(intx,inty)//取得控制台上光标的坐标位置并返回{COORDcd;cd.X=x;cd.Y=y;returnSetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cd);}intBase::Output(constchar*pstr)//在当前位置上输出一串字符{for(;*pstr;pstr++)putchar(*pstr);//函数向标准输出设备输出一个变量的字符形式return0;}//继承classGame:publicBase

1 / 20
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功