基于C++的扫雷游戏设计与实现Word格式文档下载.docx
《基于C++的扫雷游戏设计与实现Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《基于C++的扫雷游戏设计与实现Word格式文档下载.docx(25页珍藏版)》请在冰豆网上搜索。
扫雷游戏的游戏界面如图1所示。
在这个界面中,由众多面积均等的小方块所组成的区域称之为雷区,雷区的大小由用户设置的游戏等级决定。
图1初级雷区
游戏开始时,系统会在雷区的某些小方块中随机布下若干个地雷。
安放好地雷的小方块称之为雷方块,其他的称之为非雷方块。
部署完毕后,系统会在其他非雷方块中填充一些数字。
某一个具体数字表示与其紧邻的8个方块中有多少雷方块。
玩家可以根据这些信息去判断是否可以打开某些方块,并把认为是地雷的方块打上标识。
如果某个数字方块周围的地雷全都标记完,可以指向该方块并同时点击鼠标左右键,将其周围剩下的方块挖开。
如果编号方块周围地雷没有全部标记,在同时点击鼠标左右键时,其他隐藏或未标记的方块将被按下一次(即闪烁一下)。
当玩家将所有地雷找出后,其余的非雷方块区域都已打开,此时游戏结束。
在游戏过程中,一旦错误地打开了雷方块则立即失败,游戏结束;
当玩家标识的地雷数超过程序设定,虽然打开了全部其余方块,游戏仍然不会结束。
在游戏开始后,雷区上方有两个计数器。
右边的计数器显示用户扫雷所花费的总时间,以秒为单位;
左边的计数器显示当前还剩余多少个雷方块。
2.2功能需求分析
游戏需要提供一个菜单栏,上面有不同的相关选项,如游戏的开始、难度设置、退出等。
按功能将游戏区域分成两个区域:
雷区和提示区。
提示区包括两个计数器和
一个按键操作结果图像提示。
游戏过程中,当玩家用鼠标点击相应的方块,程序就会作出相应的鼠标响应事件,并伴随着GDI绘图,而众多鼠标事件的处理,都是围绕着实现扫雷程序的算法而衍生的。
3总体设计
3.1游戏框架的搭建
(1)工程项目的创建
利用应用程序向导创建一个名称为Mine的工程项目。
由于不需要诸如工具栏、状态栏等功能,并且扫雷游戏的框架是不允许改变窗口大小的,所以在向导的第四步里面把所有的选项置空,然后点击“Advanced”按钮,在弹出的对话框中选中“Windows
Styles”选项卡,将“Maximizebox”项置空,其他均使用默认设置。
(2)框架的改造
通过类向导添加一个继承于CFrameWnd的类,命名为 CMineWnd,删除
CMineDoc、CMineView和CAboutDlg类,将CMineWnd类代替CFrameWnd,让程序启动的时候以此窗口为主窗口予以显示。
结果如图2所示。
3.2菜单的制作
图2框架的改造
参考Windows自带的扫雷游戏,创建出“游戏”和“帮助”菜单,然后通过菜单资源编辑器设定菜单的功能选项,包括难度级别的选择、颜色和音效是否开启、扫雷英雄榜、使用手册、关于软件的信息等。
具体的菜单选项如图3所示。
图3游戏菜单
(1)难度级别的选择
不同的难度级别有不同的雷区大小和不同的布雷数目,所以通过宏定义预定义不同级别的横向方块数目、纵向方块数目和雷数。
并将该宏定义放入新建的头文件
“MineDefs.h”中。
窗口除了雷区外至少还包括蓝色窗口边缘 Frame_wide、白色的视觉效果区
line_wide、3D的外壳边框3D_line_wide、雷区mine_area_wide等。
于是还需要定义关于位置的宏变量。
由于难度级别的不同,窗口大小也会随之改变,因此通过在CMineWnd类增加一个改变窗口大小的函数SizeWindow()去实现。
通过ClassWizard分别选择“初级”、“中级”和“高级”菜单资源ID,为它们添加处理函数 OnMenuPrimary()、OnMenuSecond() 、OnMenuAdvance()。
OnMenuAdvance()的实现如下,另外两个类似。
voidCMineWnd:
:
OnMenuAdvance()
{
m_uLevel=LEVEL_ADVANCE;
m_uXNum=ADVANCE_XNUM;
m_uYNum=ADVANCE_YNUM;
m_uMineNum=ADVANCE_MINENUM;
SetCheckedLevel();
InitGame();
Invalidate();
SizeWindow();
}
(2)雷区大小的自定义实现
首先新建一个自定义雷区对话框资源(IDD_DLG_CUSTOM),然后添加高度、宽度、雷数三个静态文本控件和三个对应的(IDC_HEIGHT)、(IDC_WIDTH)、
(IDC_NUMBER)编辑框控件,最后将OK和Cancel按钮分别改名为“确定”和“取消”。
结果如图4。
图4自定义雷区
接着为该对话框创建CDlgCustom类,然后为三个编辑控件分别添加关联变量
m_uHeight、m_uNumber、m_uWidth,最后为OK按钮创建命令消息处理函数OnOK(),代码如下所示。
voidCDlgCustom:
OnOK()
UpdateData();
if(m_uWidth<
9)m_uWidth=9;
if(m_uWidth>
30)m_uWidth=30;
if(m_uHeight<
9)m_uHeight=9;
if(m_uHeight>
24)m_uHeight=24;
if(m_uNumber<
10)m_uNumber=10;
if(m_uNumber>
m_uWidth*m_uHeight)m_uNumber=m_uWidth*m_uHeight-1;
CMineWnd*pMine=(CMineWnd*)AfxGetMainWnd();
pMine->
SetCustom(m_uWidth, m_uHeight, m_uNumber);
// TODO:
Add extravalidationhere
CDialog:
OnOK();
(3)使用帮助的实现
由于Windows自带有扫雷游戏,所以直接调用它的使用手。
为“使用帮助”菜单选项创建命令消息处理函数OnMemuHelpUse(),代码如下所示。
显示结果如图5所示。
OnMemuHelpUse()
ShellExecute(NULL,"
open"
"
1.txt"
NULL,NULL,SW_SHOW);
图5使用帮助
(4)以往的记录
每一次游戏破记录则将有关信息保存下来。
显示结果如图6所示。
图6以往记录
(5)扫雷英雄榜的实现
首先创建两个对话框模板,一个用作当用户胜利结束游戏并打破历史记录后弹出的签名记录对话框模板IDD_DLG_NEWRECORD,另外一个是用以显示以往最高的游戏记录的对话框模板IDD_DLG_HERO。
如图7和图8所示。
图7记录对话框
图8排行榜
然后为IDD_DLG_HERO对话框模板创建CDlgHero类,分别为编辑框控件添加关联变量m_szBHolder、m_szBRecord、m_szEHolder、m_szERecord、m_szIHolder、m_szIRecord,并将Cancel按钮的ID和标题分别改为IDC_RESET和重新计分,三个静态文本标题设置为初级记录、中级记录、高级记录,最后为重新计分按钮创建命令消息处理函数OnReset()和其他成员函数。
对IDD_DLG_NEWRECORD对话框模板类似处理。
3.3布雷,扫雷核心算法的设计与实现
(1)算法的设计
把整个雷区看成一个二维数组,a[i][j]周围的雷个数是由如下8个雷区决定的(如果超出边界,应该再加以判断):
a[i-1][j-1], a[i-1][j], a[i-1][j+1],a[i][], a[i][j+1],
a[i+1][j-1],a[i+1][j], a[i+1][j+1],
在被展开时,检查周围的雷数是否与周围标示出来的雷数相等,如果相等则展开周围未标示的雷区。
这样新的雷区展开又触发这个事件,就这样递归下去,一直蔓延到不可展开的雷区。
(2)核心算法的实现
整个游戏程序包含3个阶段:
布雷、扫雷过程和结果(并不是操作结果展示,而是在扫雷过程中,玩家通过与游戏交互后的操作结果展示)。
首先定义雷方块的数据结构,具体描述如下所示。
typedefstruct
UINTuRow;
//所在雷区二维数组的行
UINTuCol;
//所在雷区二位数组的列
UINTuState;
//当前状态
UINTuAttrib;
//方块属性
UINTuOldState;
//历史状态
}MINEWND;
//雷方块结构体
然后定义雷方块的状态类别和属性类别。
A布雷
随即获取一个状态为非雷的点,将它的属性标志为雷,重复这样的工作,直到布下足够的雷为止,其流程如图9所示。
开始
生成随机的雷方块的坐标(x,y)
判断(x,y)区域是
否已经布下雷
是
否
在(x,y)区域布雷,修改状态数据
判断是否布下
所有雷
结束
图9布雷流程
在CMineWnd类中添加游戏的布雷模块的处理函数,该函数的实现如下。
LayMines(UINTrow,UINTcol)
//埋下随机种子
srand((unsigned)time(NULL));
UINTi,j;
for(UINTindex=0;
index<
m_uMineNum;
)
//取随即数
i=rand()%m_uYNum;
j=rand()%m_uXNum;
if(i==row&
&
j==col)continue;
if(