计算机图形学课程设计——扫雷游戏程序设计文档格式.doc
《计算机图形学课程设计——扫雷游戏程序设计文档格式.doc》由会员分享,可在线阅读,更多相关《计算机图形学课程设计——扫雷游戏程序设计文档格式.doc(18页珍藏版)》请在冰豆网上搜索。
玩家标定地雷
周围雷数提示
未知雷区
玩家标定未知雷
图1
游戏开始时,系统会在雷区中随机布下若干个地雷。
安放地雷的小方块称之为雷方块,其他的称之为非雷方块。
部署完毕后,系统会在其他非雷方块中填充一些数字。
某一个具体数字表示与其紧邻的8个方块中有多少雷方块。
玩家可以根据这些信息去判断是否可以鼠标点击方块,并把认为是地雷的方块打上标识。
当玩家将所有地雷找出后,其余的非雷方块区域都已打开,此时游戏结束。
在游戏过程中,一旦错误地打开了雷方块则立即失败,游戏结束。
游戏规则总结:
● 开始:
按左键开始游戏,按按钮或菜单重新开始。
● 左键:
按下时,是雷则结束,非雷则显示数字。
● 数字:
代表此数字周围一圈八格中雷的个数。
● 右键:
奇次按下表示雷,偶数按下表示对上次的否定。
● 结束:
左键按到雷结束,找出全部雷结束。
在游戏开始后,雷区上方有两个计数器。
右边的计数器显示用户扫雷所花费的总时间,以秒为单位;
左边的计数器显示当前还剩余多少个雷方块。
2.2设计流程图
开始
初始化游戏
绘制雷区
绘制笑脸
绘制计数器
鼠标右键触发动作
鼠标左键触发动作
图1
3.详细设计
3.1界面设置
在vc++运行环境下编写程序并调试,最终实现的游戏界面为图2所示,点击鼠标可开始游戏。
图2
3.2功能设计
3.2.1布雷
随即获取一个状态为非雷的点,将它的属性标志为雷,重复这样的工作,直到布下足够的雷为止,其流程图如图3所示。
生成随机的雷方块的坐标(x,y)
判断(x,y)区域是否已经布下雷
在(x,y)区域布雷,修改状态数据
判断是否布下所有雷
结束
否
是
图3
在CMineWnd类中添加游戏的布雷模块的处理函数,其具体实现代码如下所示。
voidCMineWnd:
:
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(m_pMines[i][j].uAttrib!
=ATTRIB_MINE)
{ m_pMines[i][j].uAttrib=ATTRIB_MINE;
//修改属性为雷
index++;
}
}
3.2.2扫雷
3.2.2.1鼠标左击事件
其流程如图4所示。
在雷区
雷方块定位
游戏结束
胜利
失败处理
显示
继续处理
打开区域
拓展最大的可能
显示范围
其他区域处理
胜利处理
图4
当鼠标左键点击雷区域,并且该区域不是雷方块,需要进行打开以及拓展工作。
流程如图5所示。
获取该区域周围雷
的数目num
Num=0
拓展该区域
修改标志,打开显示该区域
图5
鼠标左键点击事件的关键代码详见附录2所示。
在函数体的开始部分,先用rcBtn和rcMineArea两个矩形变量存储游戏的用户提示区域位置中的笑脸图区域以及雷区域的位置。
利用接口函数PtInRect()判断当前鼠标的位置(由参数point携带鼠标当前位置信息)是否在这两个区域内,如果检测到鼠标左键点击并释放在笑脸图的按钮区域rcBtn上,则调用初始化函数重新开始游戏,如果检测到鼠标左键点击并释放在雷区域rcMineArea,假若当前游戏状态处于已初始化完成但尚未开始的状态GS_WAIT时,则打开计时器,并且调用LayMines()函数进行布雷,然后修改游戏状态为GS_RUN进入游戏。
接着判断点击在小方块的状态是否被用于通过右键标记(可以标记为雷或者未知,此时游戏规则规定左键点击不生效),如果未标记,该状态为普通状态STATE_NORMAL时,先通过IsMine()检测是否点中地雷而失败地结束游戏,如果是,则调用函数Dead()来进行失败后的工作处理,反之对它进行打开显示与拓展操作。
先通过GetAroundNum()函数获取当前小方块相邻的8个位置的雷数。
如果当前小方块相邻区域的雷数为0,则可以向8个方向进行拓展,并显示该方块区域,直到不可拓展为止;
如果当前小方块相邻区域的雷数不为0,则显示该方块区域的相邻雷数,用作提供用户对其他位置的信息判断的提示。
拓展操作的实现代码见附录2。
经过打开或拓展后,最后通过Victory()判断游戏是否已经胜利结束,如果是则作胜利处理。
3.2.1.2鼠标右击事件
其流程如图6所示。
判断历史属性以及相关状态
修改相关状态
图6
其实现代码详见附录3所示。
3.2.3绘图界面的设计
3.2.3.1雷区、笑脸模块的绘制
添加三个位图资源如图7所示。
图7
ID分别为ID_BTN_COLOR、ID_MINE_COLOR、ID_NUM_COLOR,并分别添加三个位图类型的变量,然后调用LoadBitmap(UINTnIDResource)函数来实现位图资源与变量的关联并添加函数DrawButton()、DrawMineArea()、DrawNumber()分别实现笑脸按钮、雷区、数字图像(计时器数字和剩余雷数数字)的绘图。
绘制雷区的函数DrawMineArea()的实现代码见附录4所示。
绘制笑脸按钮的函数实现类似。
3.2.3.2数字模块的绘制
数字图像的绘制不是由鼠标事件触发的,而是由系统时间触发的。
首先在CMineWnd类中添加定时器标识的成员变量m_uTimer和一个记录游戏开始直到目前所花费的时间的成员变量m_uSpendTime。
接着在游戏的开始函数布下时间种子,时间间隔为1000us,然后选择到预定时间间隔后发送Windows命令消息函数WM_TIMER。
接着在CMineWnd类中找到对应的消息WM_TIMER,并为其添加重写函数OnTimer(),该函数首先判断这次的WM_TIMER命令是否为所布下的时间种子到时而产生的,如果是则让使用的时间变量m_uSpendTime自增,然后通知系统重绘图像。
数字图像的绘制完成后,最终游戏界面显示如图8所示。
图8
雷区、笑脸按钮、3D效果外壳和数字图像的绘制都是在OnPaint()函数中实现的。
其函数代码见附录5所示。
5测试运行
调试运行结果,直接点击鼠标左键开始游戏,踩中地雷是的界面显示如图9所示;
图9
未踩中地雷并扫完所有的雷时的界面显示如图10所示。
图10
6结论及分析
随着扫雷游戏的开发完成,本游戏中预期的主要功能也基本实现。
本论文阐述了扫雷游戏的分析与设计的全过程,并在论文中相应的位置插入了图片、流程图以及一些具有技巧性的程序代码,更加清晰的描述了该游戏是如何实现的。
扫雷游戏是一款益智类游戏,该游戏与那些网络游戏和3D游戏相比,它有编写简单容易上手等特点,非常适合人们在完成工作的时候适当的娱乐要求。
这些小游戏大都是以益智和娱乐为目的,不仅给紧张工作的人们以放松,还可以让人们的大脑得到开发。
通过这次课程设计收获很多,尤其是加深了对计算机图形学知识和递归算法以及VC的理解,将课堂上所学的理论知识应用到了实际中。
但是由于我们对VisualC++6.0的掌握程度不够好,其中的很多知识还没有理解,所以在课程设计过程中,遇到了很多问题,我们小组利用图书馆和网上查阅相关资料,以及周围同学的帮助,最终大部分问题得到解决。
设计所实现的功能是windowsxp系统自带扫雷游戏的简化,相比之下,功能不够齐全,比如声音、用户自定义以及玩家成绩的排名等都未能实现。
但是通过不断上机实验,调试程序,总结经验,动手实践能力和解决问题的能力有很大提高。
希望在以后的工作和学习中不断的充实自己的知识结构,把扫雷游戏的功能进一步完善,使它成为一个更具有实用价值的游戏软件。
参考文献
[1]杨钦等.计算机图形学. 清华大学出版社,2005
[2]BenSawyer.游戏软件设计与开发指南[M].北京:
人民邮电出版社,1998.8~46
[3]陈志泊等.VisualC++程序设计.中国铁道出版社.2005.7
[4]钦科技.VisualC++游戏设计[M].北京:
科海电子出版社,2003.1~211
[5]杨正华等.VisualC++游戏编程导学[M].北京:
清华大学出版社,2003.206~268
附录
附录1:
扫雷的处理函数
//鼠标左键点击事件代码
OnLButtonUp(UINTnFlags,CPointpoint)
//笑脸图按钮所在的区域
CRectrcBtn(m_uBtnRect[1],15,m_uBtnRect[2],39);
//雷区所在的区域
CRectrcMineArea(MINE_AREA_LEFT,MINE_AREA_TOP,
MINE_AREA_LEFT+m_uXNum*MINE_WIDTH,
MINE_AREA_TOP+m_uYNum*MINE_HEIGHT);
if(rcBtn.PtInRect(point))
{//点击笑脸图
Invalidate();
InitGame();
elseif(rcMineArea.PtInRect(point))
{//点击雷区域
CStringvalue;
UINTaround=0;
//根据不同的游戏状态作处理
switch(m_uGameState)
{ //游戏进行状态
caseGS_WAIT:
caseGS_RUN:
//firstgettheMINEWNDwhichifpushingdown
m_pOldMine=GetMine(point.x,point.y);
if(!
m_pOldMine)