计算机图形学课程设计——扫雷游戏程序设计_第1页
计算机图形学课程设计——扫雷游戏程序设计_第2页
计算机图形学课程设计——扫雷游戏程序设计_第3页
计算机图形学课程设计——扫雷游戏程序设计_第4页
计算机图形学课程设计——扫雷游戏程序设计_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算机图形学课程设计报告VC+扫雷游戏的程序设计专业班级:小组成员: 指导老师:日 期:2012年12月24日1、需求分析本课程设计实现类似于Windows XP操作系统自带的扫雷游戏。该设计以Visual C+ 6.0为开发环境, Windows 7/XP为程序运行平台。在程序设计中,把整个雷区看成一个二维数组,把雷方块定义为具有所在雷区二维数组的行和列、当前状态、方块属性、历史状态的结构体,采用了MFC机制解决问题的方法。整个游戏程序包括了布雷、扫雷过程和结果三个阶段,在处理鼠标响应事件中伴随着GDI绘图。程序通过调试运行,实现简单的设计目标,满足扫雷游戏初学者的需要。 通过本课程设计,以

2、便更好的巩固计算机图形学相关知识,掌握课程设计基本的方法和技巧,同时增加同学之间的团队合作精神以及培养分析问题、解决问题的能力。2.总体设计2.1 功能概述扫雷游戏的游戏界面如图1所示。在这个界面中,由众多面积均等的小方块所组成的区域称之为雷区,雷区的大小由用户设置的游戏等级决定。玩家标定地雷周围雷数提示未知雷区玩家标定未知雷图1 游戏开始时,系统会在雷区中随机布下若干个地雷。安放地雷的小方块称之为雷方块,其他的称之为非雷方块。部署完毕后,系统会在其他非雷方块中填充一些数字。某一个具体数字表示与其紧邻的8个方块中有多少雷方块。玩家可以根据这些信息去判断是否可以鼠标点击方块,并把认为是地雷的方块

3、打上标识。当玩家将所有地雷找出后,其余的非雷方块区域都已打开,此时游戏结束。在游戏过程中,一旦错误地打开了雷方块则立即失败,游戏结束。 游戏规则总结: 开始:按左键开始游戏,按按钮或菜单重新开始。左键:按下时,是雷则结束,非雷则显示数字。数字:代表此数字周围一圈八格中雷的个数。右键:奇次按下表示雷,偶数按下表示对上次的否定。结束:左键按到雷结束,找出全部雷结束。在游戏开始后,雷区上方有两个计数器。右边的计数器显示用户扫雷所花费的总时间,以秒为单位;左边的计数器显示当前还剩余多少个雷方块。2.2 设计流程图开始初始化游戏绘制雷区绘制笑脸绘制计数器鼠标右键触发动作鼠标左键触发动作图13.详细设计3

4、.1界面设置在vc+运行环境下编写程序并调试,最终实现的游戏界面为图2所示,点击鼠标可开始游戏。图23.2功能设计3.2.1 布雷随即获取一个状态为非雷的点,将它的属性标志为雷,重复这样的工作,直到布下足够的雷为止,其流程图如图3所示。开始生成随机的雷方块的坐标(x,y)判断(x,y)区域是否已经布下雷在(x,y)区域布雷,修改状态数据判断是否布下所有雷结束否是是否图3在CMineWnd类中添加游戏的布雷模块的处理函数,其具体实现代码如下所示。void CMineWnd:LayMines(UINT row, UINT col)/埋下随机种子srand( (unsigned)time( NULL

5、 ) );UINT i, j;for(UINT index = 0; index < m_uMineNum;) /取随即数i = rand() % m_uYNum;j = rand() % m_uXNum;if (i = row && j = col) continue;if(m_pMinesij.uAttrib != ATTRIB_MINE) m_pMinesij.uAttrib = ATTRIB_MINE;/修改属性为雷 index+;3.2.2扫雷3.2.2.1鼠标左击事件其流程如图4所示。开始在雷区雷方块定位游戏结束胜利失败处理显示结束继续处理打开区域拓展最大的可

6、能显示范围其他区域处理胜利处理否是是否否图4当鼠标左键点击雷区域,并且该区域不是雷方块,需要进行打开以及拓展工作。流程如图5所示。开始获取该区域周围雷的数目numNum = 0拓展该区域修改标志,打开显示该区域结束否是图5鼠标左键点击事件的关键代码详见附录2所示。在函数体的开始部分,先用rcBtn和rcMineArea两个矩形变量存储游戏的用户提示区域位置中的笑脸图区域以及雷区域的位置。利用接口函数PtInRect()判断当前鼠标的位置(由参数point携带鼠标当前位置信息)是否在这两个区域内,如果检测到鼠标左键点击并释放在笑脸图的按钮区域rcBtn上,则调用初始化函数重新开始游戏,如果检测到

7、鼠标左键点击并释放在雷区域rcMineArea,假若当前游戏状态处于已初始化完成但尚未开始的状态GS_WAIT时,则打开计时器,并且调用LayMines()函数进行布雷,然后修改游戏状态为GS_RUN进入游戏。接着判断点击在小方块的状态是否被用于通过右键标记(可以标记为雷或者未知,此时游戏规则规定左键点击不生效),如果未标记,该状态为普通状态STATE_NORMAL时,先通过IsMine()检测是否点中地雷而失败地结束游戏,如果是,则调用函数Dead()来进行失败后的工作处理,反之对它进行打开显示与拓展操作。先通过GetAroundNum()函数获取当前小方块相邻的8个位置的雷数。如果当前小方

8、块相邻区域的雷数为0,则可以向8个方向进行拓展,并显示该方块区域,直到不可拓展为止;如果当前小方块相邻区域的雷数不为0,则显示该方块区域的相邻雷数,用作提供用户对其他位置的信息判断的提示。拓展操作的实现代码见附录2。经过打开或拓展后,最后通过Victory()判断游戏是否已经胜利结束,如果是则作胜利处理。3.2.1.2鼠标右击事件其流程如图6所示。开始雷方块定位判断历史属性以及相关状态修改相关状态显示结束图6其实现代码详见附录3所示。3.2.3 绘图界面的设计3.2.3.1雷区、笑脸模块的绘制添加三个位图资源如图7所示。 图7ID分别为ID_BTN_COLOR、ID_MINE_COLOR、ID

9、_NUM_COLOR,并分别添加三个位图类型的变量,然后调用LoadBitmap(UINT nIDResource)函数来实现位图资源与变量的关联并添加函数DrawButton()、DrawMineArea()、DrawNumber()分别实现笑脸按钮、雷区、数字图像(计时器数字和剩余雷数数字)的绘图。绘制雷区的函数DrawMineArea()的实现代码见附录4所示。绘制笑脸按钮的函数实现类似。3.2.3.2数字模块的绘制数字图像的绘制不是由鼠标事件触发的,而是由系统时间触发的。首先在CMineWnd类中添加定时器标识的成员变量m_uTimer和一个记录游戏开始直到目前所花费的时间的成员变量m

10、_uSpendTime。接着在游戏的开始函数布下时间种子,时间间隔为1000us,然后选择到预定时间间隔后发送Windows命令消息函数WM_TIMER。接着在CMineWnd类中找到对应的消息WM_TIMER,并为其添加重写函数OnTimer(),该函数首先判断这次的WM_TIMER命令是否为所布下的时间种子到时而产生的,如果是则让使用的时间变量m_uSpendTime自增,然后通知系统重绘图像。数字图像的绘制完成后,最终游戏界面显示如图8所示。图8雷区、笑脸按钮、3D效果外壳和数字图像的绘制都是在OnPaint()函数中实现的。其函数代码见附录5所示。5 测试运行调试运行结果,直接点击鼠标

11、左键开始游戏,踩中地雷是的界面显示如图9所示;图9未踩中地雷并扫完所有的雷时的界面显示如图10所示。图106 结论及分析随着扫雷游戏的开发完成,本游戏中预期的主要功能也基本实现。本论文阐述了扫雷游戏的分析与设计的全过程,并在论文中相应的位置插入了图片、流程图以及一些具有技巧性的程序代码,更加清晰的描述了该游戏是如何实现的。扫雷游戏是一款益智类游戏,该游戏与那些网络游戏和3D游戏相比,它有编写简单容易上手等特点,非常适合人们在完成工作的时候适当的娱乐要求。这些小游戏大都是以益智和娱乐为目的,不仅给紧张工作的人们以放松,还可以让人们的大脑得到开发。通过这次课程设计收获很多,尤其是加深了对计算机图形

12、学知识和递归算法以及VC的理解,将课堂上所学的理论知识应用到了实际中。但是由于我们对Visual C+ 6.0的掌握程度不够好,其中的很多知识还没有理解,所以在课程设计过程中,遇到了很多问题,我们小组利用图书馆和网上查阅相关资料,以及周围同学的帮助,最终大部分问题得到解决。设计所实现的功能是windows xp系统自带扫雷游戏的简化,相比之下,功能不够齐全,比如声音、用户自定义以及玩家成绩的排名等都未能实现。但是通过不断上机实验,调试程序,总结经验,动手实践能力和解决问题的能力有很大提高。希望在以后的工作和学习中不断的充实自己的知识结构,把扫雷游戏的功能进一步完善,使它成为一个更具有实用价值的

13、游戏软件。参考文献1杨钦等.计算机图形学.清华大学出版社,20052Ben Sawyer.游戏软件设计与开发指南M.北京:人民邮电出版社,1998.8463陈志泊等.Visual C+程序设计. 中国铁道出版社.2005.74钦科技.Visual C+游戏设计M. 北京:科海电子出版社,2003.12115杨正华等.Visual C+游戏编程导学M.北京:清华大学出版社,2003.206268附 录附录1:扫雷的处理函数/鼠标左键点击事件代码void CMineWnd:OnLButtonUp(UINT nFlags, CPoint point) /笑脸图按钮所在的区域CRect rcBtn(m

14、_uBtnRect1, 15, m_uBtnRect2, 39);/雷区所在的区域CRect rcMineArea(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();else if (rcMineArea.PtInRect(point) /点击雷区域CString value;UINT around = 0;/根据不

15、同的游戏状态作处理switch(m_uGameState) /游戏进行状态case GS_WAIT: case GS_RUN:/ first get the MINEWND which if pushing downm_pOldMine = GetMine(point.x, point.y);if (!m_pOldMine) ReleaseCapture(); return;/检测判断当前状态是否为左鼠标同时按下if (m_bLRBtnDown) m_bLRBtnDown = FALSE;OnLRBtnUp(m_pOldMine->uRow, m_pOldMine->uCol);i

16、f (m_uGameState = GS_WAIT)m_uBtnState = BUTTON_NORMAL;Invalidate();ReleaseCapture();return;/假若周围已经标识的雷周围真正的雷数,拓展if (m_pOldMine->uState != STATE_FLAG)OpenAround(m_pOldMine->uRow, m_pOldMine->uCol);if (ErrorAroundFlag(m_pOldMine->uRow, m_pOldMine->uCol)Dead(m_pOldMine->uRow, m_pOldMi

17、ne->uCol);ReleaseCapture();return;else /如果游戏尚未开始,点击左键启动游戏if (m_uGameState = GS_WAIT) if (m_uTimer)KillTimer(ID_TIMER_EVENT);m_uTimer = 0;m_uSpendTime = 1;Invalidate();if (m_bSoundful) sndPlaySound(LPCTSTR)LockResource(m_pSndClock), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);/启动定时器m_uTimer = SetTimer

18、(ID_TIMER_EVENT, 1000, NULL);/布雷LayMines(m_pOldMine->uRow, m_pOldMine->uCol);/改变游戏状态为"运行/GS_RUN"m_uGameState = GS_RUN;if (m_pOldMine->uOldState = STATE_NORMAL)/当该雷区域为正常未作标记才打开/如果该区域为雷,则死亡if (IsMine(m_pOldMine->uRow, m_pOldMine->uCol) Dead(m_pOldMine->uRow, m_pOldMine->

19、uCol);ReleaseCapture();return;/不是雷的时候,获取其周围的雷数目around = GetAroundNum(m_pOldMine->uRow, m_pOldMine->uCol);/ 如果为空白区域,拓展,否则打开该区域(显示周围有多少雷数)if (around = 0) ExpandMines(m_pOldMine->uRow, m_pOldMine->uCol);else DrawDownNum(m_pOldMine, around);else if (m_pOldMine->uOldState = STATE_DICEY) /标

20、志为“?”问号的时候m_pOldMine->uState = STATE_DICEY;/判断是否为胜利if (Victory()Invalidate();ReleaseCapture();return;break;case GS_VICTORY:case GS_DEAD:ReleaseCapture();return;default :break;m_uBtnState = BUTTON_NORMAL;Invalidate();else /点击非雷区域if (m_uGameState = GS_WAIT | m_uGameState = GS_RUN)m_uBtnState = BUTT

21、ON_NORMAL;InvalidateRect(rcBtn);ReleaseCapture();CWnd:OnLButtonUp(nFlags, point);/拓展操作的实现代码void CMineWnd:ExpandMines(UINT row, UINT col)UINT i, j;UINT minRow = (row = 0) ? 0 : row - 1;UINT maxRow = row + 2;UINT minCol = (col = 0) ? 0 : col - 1;UINT maxCol = col + 2;UINT around = GetAroundNum(row, co

22、l);/显示该区域的方块状态m_pMinesrowcol.uState = 15 - around;m_pMinesrowcol.uOldState = 15 - around;/ “打开”该区域,重绘DrawSpecialMine(row, col);/对周围一个雷都没有的空白区域if (around = 0)for (i = minRow; i < maxRow; i+) for (j = minCol; j < maxCol; j+) /对于周围可以拓展的区域进行的规拓展if (!(i = row && j = col) && m_pMines

23、ij.uState = STATE_NORMAL&& m_pMinesij.uAttrib != ATTRIB_MINE) if (!IsInMineArea(i, j) continue;ExpandMines(i, j);/ 递归拓展操作附录2:鼠标右键点击事件代码void CMineWnd:OnRButtonDown(UINT nFlags, CPoint point) /笑脸图按钮所在的区域CRect rcBtn(m_uBtnRect1, 15, m_uBtnRect2, 39);/雷区所在的区域CRect rcMineArea(MINE_AREA_LEFT, MINE

24、_AREA_TOP, MINE_AREA_LEFT + m_uXNum * MINE_WIDTH, MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);m_bLRBtnDown = FALSE;if (rcMineArea.PtInRect(point) /点击雷区域if (m_uGameState = GS_WAIT | m_uGameState = GS_RUN) m_pNewMine = GetMine(point.x, point.y);if (!m_pNewMine) return;/检测判断当前状态是否为左右鼠标同时按下if (nFlags = (MK_L

25、BUTTON | MK_RBUTTON)m_bLRBtnDown = TRUE; OnLRBtnDown(m_pNewMine->uRow, m_pNewMine->uCol);elseswitch(m_pNewMine->uState) /普通状态case STATE_NORMAL:m_pNewMine->uState = STATE_FLAG;m_pNewMine->uOldState = STATE_FLAG;m_nLeaveNum-;break;/标记状态case STATE_FLAG:m_pNewMine->uState = STATE_DICEY

26、;m_pNewMine->uOldState = STATE_DICEY;m_nLeaveNum+;break;/未知状态case STATE_DICEY:m_pNewMine->uState = STATE_NORMAL;m_pNewMine->uOldState = STATE_NORMAL;break;default: break;Invalidate();CWnd:OnRButtonDown(nFlags, point);附录3:绘制雷区的函数代码void CMineWnd:DrawMineArea(CPaintDC &dc)CDC dcMemory; /用作内存设备 /源设备dcMemory.CreateCompatibleDC(&dc); /使得这个设备与dc兼容 /dc是目标设备dcMemory.SelectObject(m_bmpMine); /将内存设备与位图资源关联for (UINT i = 0; i<m_uYNum; i+) for (UINT j = 0; j<m_uXNum; j+) /根据ij区域的雷方块状态拷贝相应的图像到ij雷区的特定区域dc.Stretch

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论