




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、编程实现一个扫雷机器人一、课题内容和要求在一个20*20的地图上,分布着81颗地雷,扫雷机器人走到其中一个方格上,如果是地雷,它将被炸死,如果不是,它可以探测到它周围的八个方格中有几个地雷。现在你拥有10个扫雷机器人(10次错误机会),请你将这片雷区中的所有地雷标出来。二、需求分析(1)规则描述 游戏开始时,系统会在雷区的某些小方块中随机布下81颗雷,部署完毕后,系统会在其他非雷方块中填充一些数字,某一个具体数字表示预期紧邻的8个方块中有多少雷方块,玩家可以可以根据这些信息去判断是否可以打开某些方块,并把认为是地雷的方块打上标记,当玩家将所有地雷找出后,其余的非雷方块区域都已打开,此时游戏胜利
2、结束,在游戏过程中,一旦错误地打开了雷方块10次以上,游戏结束。(2)功能需求分析此扫雷机器人游戏是一个交互式的游戏,它的开发需满足的要求包括以下几个部分:一部分是此游戏界面需要在20*20的界面上实现,并规定雷数为81颗,第二部分是实现扫雷要求,即扫雷机器人走到其中一个方格上,如果是地雷,它将被炸死,如果不是,它可以探测到它周围的八个方格中有几个地雷,该部分包括进行某种操作判断某区域是否是雷,如果是雷该如何操作,如果不是雷该如何操作,判断某区域是雷则如何加以标记,以及点击某区域时,判断与该区域相邻的其它8个区域是否是雷并做一个标记。第三部分是此扫雷机器人有10次错误机会。(3)功能模块需求分
3、析程序设计过程中涉及到的功能模块函数:1函数:static int TextOut(const char* pstr ); 功能要求:在当前位置输出字符串,本程序根据各种操作,定义的字符串分别为"ArrowKey:MoveCursor Key1:Open Key2:Mark Key3:OpenNeighbors"代表程序标题、Congratulations! You Win! Thank you for playing!代表游戏获胜、Game Over, thank you for playing!代表游戏失败、Presented by 1803 . Press ESC t
4、o exit代表退出。2函数: static int GotoXY(int x , int y );功能要求:光标移至(x,y)处并得到此光标位置。3函数:static int CharOut(int x, int y, const int pstr);功能要求:在(x,y)处输出一字符。4函数:static int TextOut(int x, int y, const char* pstr);功能要求:由任意位置移到(x,y)并在当前位置输出字符串5函数:static int GetKey(); 功能要求:等待键1、2、3的输入并返回此值。6函数:int InitPool(in
5、t Width, int Height, int nBoom);功能要求:初始化游戏环境。 7函数:int DrawPool(int bDrawBoom = 0);功能要求:根据各区域内容输出字符串 、 *、 #、 .。8. 函数:int WaitMessage( );功能要求:根据各种输入KEY_UP、 KEY_DOWN、 KEY_LEFT、 KEY_RIGHT、 KEY_1、 KEY_2 、KEY_3、 KEY_ESC执行操作,通过返回的nRT来判断失败、胜利或未结束。9. 函数:int GetShowNum(int x, int y);功能要求:确定认一点(x,y)和它周围8个方向的总雷
6、数,并把雷的数目显示出来。10. 函数:int TryOpen(int x, int y); 功能要求:打开点(x,y)并显示雷数号码,必须实现10次机会错误这一功能要求,若超出10次而未找出全部雷数,则将游戏界面上的所有雷显示出来(即返回EOF)。11. 函数:int DFSShowNum(int x, int y);功能要求:在游戏界面范围内,先通过调用函数int GetShowNum(int x, int y)获得任意一点周围的总雷数,若为0,则通过递归调用直至将获得的雷数显示出来。 四、概要设计整体游戏流程图:游戏开始执行操作雷区GAME OVER判断非雷区程序使用了面向对象
7、的方法,首先创建工程项目,本程序基于Win32 Console Application.程序定义了窗口类class CConsoleWnd和类模块class CSLGame , 类中成员变量和成员函数原型声明分别如下:(1).class CConsoleWnd public: static int TextOut(const char*); static int GotoXY(int, int); static int CharOut(int, int, const int); static int TextOut(int, int, const char*); static int GetK
8、ey(); ;(2).class CSLGame:public CConsoleWnd private: int curX,curY; int poolWidth,poolHeight; int bm_gamepoolGAME_MAX_HEIGHT+2GAME_MAX_WIDTH+2; public: CSLGame():curX(0),curY(0)poolWidth=poolHeight=0; int InitPool(int, int, int); int MoveCursor()return CConsoleWnd:GotoXY(curX, curY); int DrawPool(in
9、t); int WaitMessage(); int GetShowNum(int, int); int TryOpen(int, int); private: int DFSShowNum(int, int); private: const static int GMARK_BOOM; const static int GMARK_EMPTY; const static int GMARK_MARK;const int CSLGame:GMARK_BOOM = 0x10;const int CSLGame:GMARK_EMPTY= 0x100;const int CSLGame:GMARK_
10、MARK = 0x200;#define KEY_UP 0xE048#define KEY_DOWN 0xE050#define KEY_LEFT 0xE04B#define KEY_RIGHT 0xE04D#define KEY_ESC 0x001B#define KEY_1 '1'#define KEY_2 '2'#define KEY_3 '3'#define GAME_MAX_WIDTH 100#define GAME_MAX_HEIGHT 100算法设计包括:1 随机布雷可以随即获取一个状态为非雷的点,将它的属性标志为雷,重复这样的工作
11、直到将81颗雷布完。流程图如下:是开始生成随机的雷方块的坐标(x,y)判断(x,y)区域是否已经布下雷在(x,y)区域布雷,修改状态数据判断是否布下所有雷结束否否是设数组bm_gamepoolyx为地雷标志数组,若此数组恒为0,则标志为雷,Windows的API有这样的一种机制,可以生成随机函数。先用strand()函数产生并返回随机种子,可以利用系统的时间作为随机数产生的种子,而产生的随机数实际上是伪随机数,它的产生是根据递推公式计算的一组数组,即int x = rand()%Width + 1, y = rand()%Height + 1,当序列长度满足81时,这组数值近似满足均匀分布。2
12、. 做雷阵,即雷数目的计算和显示在没有雷的地方点击后就会显示一个数字表示它周围有几个雷,这是怎么实现的呢?我们可以把整个雷区看成一个二维数组bm_gamepoolyx,假如雷区: 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27 28 31 32 33 34 35 36 37
13、 38 41 42 43 44 45 46 47 48 51 52 53 54 55 56 57 58我要知道a34周围有几个雷,就只有去检测 a23,a24,a25 a33, a35 a43,a44,a45这8个雷区是否放上了雷,仔细观察它们成在数学关系,抽象出来就是:ai,j的雷的个数就是由
14、160;ai-1,j-1,ai-1,j,ai-1,j+1 a i ,j-1, a i ,j+1 ai+1,j-1,ai+1,j,ai+1,j+1 这样的8个雷区决定的。对于任意一点(x,y)执行循环语句:for(int Y=-1;Y<=1;+Y) for(int X=-1;X<=1;+X) if(bm_gamepooly+Yx+X & GMARK_BOOM)+nCount; 观察并计算它周围8个方向雷区的总雷数。3.
15、 雷方块拓展接着上面的例子,假如a3,4周围雷数为1,a2,3已被标示为地雷,那么a24,a25,a33,a35,a43,a44,a45将被展开,一直波及到不可确定的雷区。这也是实现的关键。我们可以把数组的元素设定为一个类对象,它们所属的类设定这样的一个事件:在被展开时,检查周围的雷数是否与周围标示出来的雷数相等,如果相等则展开周围未标示的雷区。这样新的雷区展开又触发这个事件,就这样递归下去,一直蔓延到不可展开的雷区。4. KEY_1事件在雷区键1的时候,光标所在的方块将显示提示信息,即它周围8个方向的雷区总雷数。(1) 判断鼠标点击的雷区位置,计算出当前打开的小方块坐标。(2) 检测小方块的
16、状态,判断能否打开,是则跳到无雷状态处理。(3) 检测小方块的状态,判断是否为雷,是则跳到雷状态处理。(4) 继续状态处理,打开小方块,并拓展最大可能显示范围。KEY_1事件流程图如下:KEY_1事件游戏结束雷方块定位继续处理打开区域拓展最大的可能显示范围胜利失败处理胜利处理显示结束否是否是5. KEY_2事件对雷区域中某个小方块的属性做出判断后,可以键2做出相应的属性标记,当键2时,可以根据以前该雷方块标识的状态去计算出应该显示的下一状态,并标识对该雷方块的推测属性,人啊背后予以显示,其实现步骤如下:(1)光标所在的雷区位置。(2)历史标志状态。(3)使状态修改为即将显示的状态。(4)显示。
17、 KEY_2的流程分析如下图:KEY_2事件雷方块定位判断历史属性以及相关状态修改相关状态显示结束6. KEY_3事件对雷区域中某个小方块的属性做出判断后,可以键3做出相应的雷区拓展,首先显示该区域的方块状态,然后判断该方块周围8个方向的方块中是否有雷,如果没有,则在此方块键3,将会打开这8个方块中无雷的区域。实现步骤如下:(1) 光标所在雷区显示的数字。(2) 相邻8个方向的区域状态。(3) 进行判断,并做相应操作。(4) 结果显示。 KEY_3流程分析如下图:KEY_3事件雷方块定位判断其属性以及周围方块状态打开其周围非雷区显示结束 五、详细设计1.二维数组初始化我开的是一个22
18、*22的数组,而实际使用的雷区是20*20的数组,周围一圈是空的,这样对雷区的边界,我也可以简单的将它周围8个点的雷数相加,而不会发生数组越界的情况,但在编程的时候,仍应该认为雷区是一个简单的20*20的数组,可以利用的应该是0,19. #define GAME_MAX_WIDTH 100#define GAME_MAX_HEIGHT 100int bm_gamepoolGAME_MAX_HEIGHT+2GAME_MAX_WIDTH+2;while(nBoom) int x = rand()%Width + 1, y = rand()%Height + 1; if(bm_gamep
19、oolyx=0) bm_gamepoolyx = GMARK_BOOM; -nBoom; 2.判断一个区域是否是雷方块int CSLGame:DrawPool(int bDrawBoom = 0)if(bm_gamepoolyx & GMARK_BOOM) if(bDrawBoom) putchar('*'); else putchar('.'); 3.相邻区域的雷数获取/ return ShowNum at (x, y) int CSLGame:GetShowNum(int x, int y) int nCount = 0; for(int Y=-1;
20、Y<=1;+Y) for(int X=-1;X<=1;+X) if(bm_gamepooly+Yx+X & GMARK_BOOM)+nCount; return nCount; 4.根据玩家的操作和雷区的分布,在游戏界面上显示 各字符串 用来表示空、 *用来表示为雷、 #表示此区域标志为雷、 .表示未确定区域或雷数,即任意一点周围8个方向的总雷数。/ Draw game pool to Console windowint CSLGame:DrawPool(int bDrawBoom = 0) for(int y=1;y<=poolHeight;+y) CConsole
21、Wnd:GotoXY(1, y); for(int x=1;x<=poolWidth;+x) if(bm_gamepoolyx=0) putchar('.'); else if(bm_gamepoolyx=GMARK_EMPTY) putchar(' '); else if(bm_gamepoolyx>0 && bm_gamepoolyx<=8) putchar('0'+bm_gamepoolyx); Else if(bDrawBoom=0&&(bm_gamepoolyx GMARK_MARK)
22、putchar('#'); else if(bm_gamepoolyx & GMARK_BOOM) if(bDrawBoom) putchar('*'); else putchar('.'); return 0;5扫雷机器人有10次错误机会,执行以下循环函数if(bm_gamepoolyx & GMARK_BOOM) i+; if(i=10)nRT = EOF; 6.雷方块的拓展int CSLGame:DFSShowNum(int x, int y) if(0<x && x<=poolWidth) &a
23、mp;&(0<y && y<=poolHeight) && (bm_gamepoolyx=0) int nCount = GetShowNum(x, y); if(nCount=0) bm_gamepoolyx = GMARK_EMPTY; for(int Y=-1;Y<=1;+Y) for(int X=-1;X<=1;+X) DFSShowNum(x+X,y+Y); else bm_gamepoolyx = nCount; return 0; 7. 胜利的判断与相应处理,根据各种输入KEY_UP、 KEY_DOWN、 KEY_L
24、EFT、 KEY_RIGHT、 KEY_1、 KEY_2 、KEY_3、 KEY_ESC执行操作,通过返回的nRT来判断失败、胜利或未结束。/ Game loop, wait and process an input message/ return: 0: not end; 1: Win; otherwise: Lose int CSLGame:WaitMessage() int nKey = CConsoleWnd:GetKey(); int nRT = 0, nArrow = 0; switch (nKey) case KEY_UP: if(curY>1)-curY; nArrow=
25、1; break; case KEY_DOWN: if(curY<poolHeight) +curY; nArrow=1; break; case KEY_LEFT: if(curX>1)-curX; nArrow=1; break; case KEY_RIGHT: if(curX<poolWidth)+curX; nArrow=1; break; case KEY_1: nRT = TryOpen(curX, curY); break; case KEY_2: if(bm_gamepoolcurYcurX & (GMARK_MARK|GMARK_BOOM)=0) b
26、m_gamepoolcurYcurX = GMARK_MARK; break; case KEY_3: if(bm_gamepoolcurYcurX & 0xF) int nb = bm_gamepoolcurYcurX & 0xF; for(int y=-1;y<=1;+y) for(int x=-1;x<=1;+x) if(bm_gamepoolcurY+ycurX+x&GMARK_MARK) -nb; if(nb=0) for(int y=-1;y<=1;+y) for(int x=-1;x<=1;+x) if(bm_gamepoolcur
27、Y+ycurX+x & (0xF|GMARK_MARK) = 0) nRT |= TryOpen(curX+x, curY+y); break; case KEY_ESC: nRT = EOF; break; if(nKey = KEY_1 | nKey = KEY_3) int y=1; for(;y<=poolHeight;+y) int x=1; for(;x<=poolWidth; +x) if(bm_gamepoolyx=0)break; if(x<=poolWidth) break; if(! (y<=poolHeight) nRT = 1; if(
28、nArrow=0) DrawPool(); MoveCursor(); return nRT; 六、测试数据及其结果分析游戏开始页面如下:在10次错误机会内未获得游戏胜利,运行结果如下:分析:(1)键1,打开光标所在区域并显示其相邻8个方向的总雷数。 (2)判断某方块的状态,若确定其为雷,键2,则在此方块上标记,表示此为雷。 (3)判断已打开方块相邻8个方向的方块状态,若已显示的雷数与此方块显示的数字相等,则在此方块键3,将其相邻方向未打开区域打开。(4)有10次错误机会,在10内错误将不显示游戏失败信息,只有超过10次才会出现游戏失败的提示信息。七、调试过程中的问题1.问题:在布雷时,如何实现随机分布。解决为题:通过
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 年产20万吨氟化系列产品生产项目实施方案(参考模板)
- 锂电池回收利用项目可行性研究报告
- 《傲慢与偏见》读书心得 15篇
- 光伏装配示范复合项目可行性研究报告(参考范文)
- 河北省部分高中2023-2024学年高三上学期12月期末考语文含解析
- 安徽省名校联盟2023-2024学年高三上学期实验班12月大联考英语含解析
- 江苏航运职业技术学院《建筑与装饰工程施工》2023-2024学年第二学期期末试卷
- 喀什理工职业技术学院《城乡生态与环境规划》2023-2024学年第二学期期末试卷
- 安徽广播影视职业技术学院《纺织品实验与设计》2023-2024学年第二学期期末试卷
- 湖南工业大学《机械控制工程基础》2023-2024学年第二学期期末试卷
- 普惠金融专员试题及答案
- 《心电图机操作与应用》课件
- 西部计划考试考题及答案
- 《中国溃疡性结肠炎诊治指南(2023年)》解读
- 物质安全数据表(MSDS)(车用尿素溶液)
- 华北电力大学ppt模板
- 清朝治理新疆地区系统性治理课件(16ppt+视频)2022年新疆地方史读本(中学版)
- 综合教学楼建筑结构设计
- 员工分红合作协议书54559
- 国家自然科学基金项目评审打分表.xls
- 公开课评分表
评论
0/150
提交评论