资源描述
^`
湖南涉外经济学院
扫 雷 游 戏
课程设计报告
学 院:
信息科学与工程学院
专业名称:
计算机科学与技术
课程名称:
程序设计实训
设计题目:
扫雷游戏
学生姓名:
唐 杰
指导教师:
邹 竞
时 间:
2012年12月
^`
摘 要
在计算机逐步渗入社会生活各个层面的今天,计算机已经成为人们日常生活不可或缺的一部分,越来越多的人使用计算机办公、娱乐、购物等等。游戏行业发展一日千里,该行业极大的影响和改变了人们的生活和娱乐方式,游戏为消费者提供丰富多彩的虚拟空间,使消费者可以自由自在的享受虚拟世界的乐趣,实现自己在现实生活着那个可能永远不能实现的梦想,满足了消费者的心理和精神需求。
扫雷游戏是Windows操作系统自带的一款小游戏,在过去的几年里,Windows操作系统历经数次换代更新,变得越来越庞大、复杂,功能也越来越强大,但是这款小游戏依然保持原来的容貌,可见这款小游戏受到越来越多人的喜爱。扫雷游戏是比较经典的一款小游戏,实现它的方法很多,可以用很多不同算法设计和语言实现,如C,C++,VB,JAVA等。我利用Microsoft Visual C++ 6.0编写了与它功能相似的扫雷游戏,寓学于乐。
程序的功能是随机生成地雷数,通过鼠标操作玩游戏,不接受键盘,按任意键结束程序。单击屏幕上的笑脸可以重新开始游戏。所有地雷标出后胜利,当鼠标左键单击到地雷时提示游戏失败。其功能类似于Windows操作系统自带的扫雷游戏。论文首先介绍了进行该游戏课程设计的目的,然后是任务描述和设计的相关要求,最后是最重要的需求分析和设计方案。重点介绍了在游戏过程中各事件的处理,其中又以鼠标事件和清除未靠近地雷区方块这两方面最为最要,鼠标事件是利用鼠标所发出的信息了解用户的意图,进而做出相对应的动作。清除未靠近地雷区的方块较为复杂。
关键词:扫雷游戏;算法设计;事件;Microsoft Visual C++ 6.0
^`
^`
目 录
摘 要 I
一、课程设计目的 1
二、课程设计题目任务描述和要求 2
2.1 任务描述 2
2.2 设计要求 3
三、需求分析 4
3.1功能描述 4
3.2功能需求 5
3.3 功能模块 6
3.4系统需求分析总结 6
四、设计方案 7
4.1 总体设计 7
4.1.1 系统基本功能 7
4.1.2 系统流程 8
4.1.3 主要功能模块 9
4.2 详细设计 10
4.2.1部分功能函数定义 10
4.2.2运行界面分析 16
五、心得体会 19
六、参考资料 20
一、课程设计目的
本课程设计是计算机科学与技术专业重要的实践性环节之一,是对本课程学习后进行的一次全面而综合的练习,也为后续各门计算机课程的学习和毕业设计打下基础。本次课程设计的目的主要有:
(1)巩固和加深学生对C和C++语言的基本知识的理解与掌握;
(2)掌握C和C++语言编程和调试的基本技能;
(3)运用C和C++语言对程序的简单设计;
(4)让学生掌握较为简单的算法分析能力;
(5)提高与运用C和C++语言解决能实际问题的能力。
(6)更深入地理解和掌握该课程中的有关基本概念,程序设计思想和方法。
(7)对掌握知识的深度、运用理论去处理问题的能力、实验能力、课程设计能力进行考核。
(8)培养综合运用所学知识独立完成课题的能力。
(9)掌握程序设计说明文档的能力与技巧;
二、课程设计题目任务描述和要求
2.1 任务描述
随着人们工作压力变得越来越大,现如今更多的人开始通过玩游戏来排解内心的压力,而各种各样的游戏也排入市场,一些大型网络游戏更是一些年轻用户的最爱,所有扫雷游戏面对市场的竞争压力还是非常大的。
分析Windows系统自带的扫雷游戏,查找规则并对主要功能进行模仿程序实现,对于实现过程中出现的bug进行调试解决。
经过对游戏的初步分析,扫雷游戏含有如下规则:
根据用户执行的鼠标事件,做出相应的挖雷操作,插旗、疑问标记、自动蔓延开挖等。挖雷过程由计时器计时,由一个计数器统计插旗后雷的剩余个数。如果选择了标记功能,那么单击右键会依次对未知点进行插旗,标记,取消插旗与标记。如果点击到了未插旗子的雷区,如果是雷,则判定游戏失败,之后对雷区的点击进行屏蔽,不予响应。如果是疑问标记则像正常区域对待。如何判断胜利,如果所有的雷都被插旗或者点击后剩余的雷区。
具体任务如下:
(1)需要为Windows操作系统的用户设计完成一款扫雷游戏,这是一个根据某种算法自动布雷,有用户扫雷的小软件;
(2)本游戏在难度设置上,分为初、中、高三个难度等级,三个等级的雷数不同;
(3)本游戏由每个学生单独完成,完成时间大概7周时间,开发成本低,易于完成;
(4)设计过程中,前两周,对整个游戏所实现的功能进行详细的设计以及对存在的问题及解决办法进行最终确定;3-5周完成游戏的程序编写,并优化;最后两周,写出设计本游戏的详细文档说明,并作课程设计汇报。
整个扫雷游戏课程设计实现流程图如图2-1所示:
制定规则
设计算法
算法实现
调试 测试
数据分析
完成设计报告
图2-1 课程实现流程图
图2-1清晰明了的描述了整个课程设计的实现流程。前期工作是制定规则和设计算法,这一阶段主要任务是搜集相关资料,然后根据搜集到的资料结合自己所学知识制定系统实现算法;中期工作是算法实现和调试系统,这一阶段主要任务是完成算法的实现,然后进行调试和优化系统;后期工作是对数据结果进行分析,然后完成课程设计报告。
2.2 设计要求
(1)系统需求分析,对系统的各种功能需要进行总结;
(2)采用结构化、模块化程序设计方法设计;
(3)理解扫雷玩法的特点,并分析玩法的实现功能
(4)设计雷区和非雷区的判断算法。
(5)进行概念设计和逻辑结构设计,以便使系统实现进展顺利;
(6)进行详细的设计方案,包括总体设计和详细设计,这包括程序设计代码的分析和系统运行界面截图的分析;
(7)要求人机交互性较强;界面较美观;
(8)设计方案和执行结果的分析总结。
三、需求分析
需求分析的主要任务即详细的找出程序所需要的各种功能实现,是对系统功能进一步分析和抽象,以确定系统应当做什么的问题,从而完成系统的逻辑设计。本程序为扫雷游戏的实现,首先是要实现扫雷游戏的基本功能,根据扫雷游戏的玩法,设计程序,实现程序功能。本系统需求分析分为四个部分:功能描述、功能需求、功能模块和系统需求分析报告。
3.1功能描述
按功能将游戏区域分成两个区域:雷区和提示区。提示区包括计雷器、计时器和一个笑脸的按键操作。游戏过程中,当用户用鼠标点击相应的方块,程序就会作出相应的鼠标事件,而鼠标事件的处理都是由扫雷程序实现的。
游戏开始时,系统会在雷区的某些小方块中随机布下若干个地雷。安放地雷的方块称为雷方块,其他的称为非雷方块。布完雷后,系统会在其他非雷方块中填充一些数字。某一个具体数字表示与其紧邻的8个方块中有多少个雷。用户可以根据这些数字判断是否可以打开某些方块,并把认为有地雷的方块标识地图。如果某个数字方块周围的地雷全都标记完,可以单击鼠标左键,将其周围剩下的方块挖开。
如果数字周围地雷没有全部标记,在同时单击鼠标左右键时,其他隐藏或未标记的方块将被按下一次。当用户将所有地雷挖出后,其余的非雷方块区域都已打开,此时游戏胜利。在游戏过程中,一旦错误地打开了雷方块则游戏失败,游戏结束;当用户标识的地雷数超过程序设定,虽然打开了全部其余方块,游戏仍然不会结束。
游戏中相关图例下三图所示
图3-1数字和地雷标识 图3-2提示器数字 图3-3表情变化
图3-1是数字和地雷标识。数字1到8表示在此数字周围的八个方向有多少个地雷;是地雷表示,右击小方块即标识地雷;表示不确定是否为地雷,两次右击小方块;表示踩到了地雷,游戏结束;表示标识错地雷,即不是地雷的小方块插上了地图标识;表示游戏结束时,显示有地雷的小方块。是雷区凸起的小方块,即没有展开的雷区;是雷区的凹下的小方块,其周围没有地雷。
图3-2 是提示器数字标识,用于提示区计时器和计雷器的数字变化。
图3-3 是游戏过程中提示区表情按钮的状态。(凸起的笑脸)是游戏初始化状态下的表情,即游戏开始前的状态; 是游戏胜利时的表情,替代凸起的笑脸; 是踩到了地雷,游戏结束时的表情状态; 是单击左键按下和左右键同时按下时的表情,即用户没有完成一次鼠标事件时的状态;(凹下的笑脸)是游戏中的表情,游戏没有结束。
3.2功能需求
(1)本游戏结构较为简单,设置三个难度等级为:初级(9*9,10个雷)、中级(16*16,40个雷)、高级(16*30,99个雷);
(2)提示区左侧显示总雷数,并减去被标明有雷区域的数目;
(3)提示区中间位置显示笑脸按钮用于开局和显示鼠标动作的结果;
(4)提示区右侧显示扫雷所用的时间;
(5)单击鼠标左键于未知区域,如果未知区域有雷,游戏结束,显示所有的地雷;如果没有雷,则显示周围雷数,如果周围没雷,则再查看周围八个区域是否有雷直到有雷为止,并显示周围雷的数目;
(6)单击鼠标右键于未知区域,则显示小红旗,将其标识有雷。在该位置再次单击右键则视为不确定,显示问号,单击第三次,取消设置,问号消失;
(7)如果该数字方块周围地雷已经完全标识出,双击该数字所在方块,将快速翻开所有周围不是地雷的方块,并显示,直到有雷为止;
(8)将雷全部扫完后,会出现一个提示框,显示游戏胜利,用户还可以将自己的扫雷成绩保存起来。
3.3 功能模块
(1)游戏界面
(2)布雷
(3)鼠标事件
(4)地雷判断
(5)游戏胜利(结束)
(6)游戏失败(结束)
(7)游戏设置(等级)
3.4系统需求分析总结
通过对现行扫雷系统的调查与分析,本系统的结构基本合理,系统功能基本能够达到Windows扫雷游戏的要求。本系统的输入边界是用户进行鼠标事件操作,输入边界时扫雷结束,并且游戏胜利。
通过对扫雷游戏规则以及相关算法的分析,本系统总的数据量较小,规模不是很大,适合于在普通微机或小型机上运行。
四、设计方案
设计方案是对一个系统进行详细而具体的设计,本系统的设计方案主要分为总体设计和详细设计两部分。总体设计是对整个系统结构化的设计,包括系统的大致框架和各个函数以及类的说明;详细设计是对各个类和函数进行定义和具体实施。
4.1 总体设计
在不打开任何埋有地雷的小方块情况下,以最快的速度找出所有的地雷。如果在打开方块的过程中,不小心踩到藏有地雷的方块,则游戏结束,只有将所有不含地雷的方块打开,则游戏成功。
游戏的操作方面主要以鼠标为主,当鼠标左键单击方块时即表示打开方块,当鼠标右键单击方块时即表示标识或疑似地雷,反复单击右键则方块会以“未标识→标识→疑似”三者关系不断循环。游戏者可以通过地雷区内的数字提示了解以数字为中心的其周边八个方格内所含的地雷数,假若打开的方块显示数字“3”,则表示以其为中心的周边方块内藏有3个地雷。
当打开的方块不是地雷,且周边八个方块也都没有地雷时,方块会以被打开方块的八个方向将空白方块打开。
系统的总体设计是对整个系统的结构化设计,包括系统基本功能的设计、系统流程的设计和各个功能模块的设计等。
4.1.1 系统基本功能
本系统与Windows系统自带的扫雷游戏相比较简单,只具有扫雷游戏的基本功能,逻辑设计方面也只有简单的级别选择(即游戏选关)、计雷和计时。
系统基本功能如图4-1所示
扫雷游戏
游戏开始
游戏选关
游戏计雷
游戏计时
图4-1 系统基本功能图
图4-1是整个扫雷游戏的系统基本功能图,从图中可以看出系统分为四大功能模块,即游戏开始、游戏选关、游戏计雷、游戏计时。
4.1.2 系统流程
系统流程是对系统进行大概分析后得出的系统各功能的流动情况以及各个操作之间的关系,上一步操作都与下一步操作有着紧密的联系,即下一步操作都是由上一步操作所决定的。系统流程主要是对系统流程图的分析,系统流程图清晰的地反映出了系统的运行情况和走向。
系统详细运行流程如图4-2所示
图4-2 运行流程图
图4-2是游戏详细的运行流程图,图中清晰地描述了系统的执行过程,即根据不同的事件,游戏状态的转换。过程为:游戏开始,等待事件,发出鼠标事件,根据用户发出的命令,判断是左键命令还是右键命令,若是右键命令则是标出地图,若是左键命令则是调用扫雷的相关逻辑算法,进行下一部操作;如果点到雷,则游戏结束,调用菜单事件,重新开局;如果没有点到雷,则继续判断,直到点完数字,则游戏胜利,调用菜单事件,重新开局。
4.1.3 主要功能模块
void CMineWnd::LayMines(UINT row, UINT col) //布雷
void CMineWnd::ExpandMines(UINT row, UINT col) //雷方块拓展(对于周围无雷的空白区域)
UINT CMineWnd::GetAroundNum(UINT row, UINT col) //获取某个小方块区域相邻8个区域的雷个数
UINT CMineWnd::GetAroundFlags(UINT row, UINT col) //获取某个小方块区域相邻8个区域的已标志状态数
BOOL CMineWnd::IsMine(UINT row, UINT col) //判断是否为雷
BOOL CMineWnd::IsInMineArea(UINT row, UINT col) //判断是否在雷区域
void CMineWnd::Dead(UINT row, UINT col) //失败处理
BOOL CMineWnd::Victory() //胜利判断并处理
void CMineWnd::OnLRBtnDown(UINT row, UINT col) //鼠标右键,根据原先不同的标记作状态循环修改,以便用户可以修改其原先标志
void CMineWnd::DrawButton(CPaintDC &dc) //绘制笑脸按钮图
void CMineWnd::DrawNumber(CPaintDC &dc) //绘制数字
void CMineWnd::DrawMineArea(CPaintDC &dc) //绘制雷区
void CMineWnd::DrawDownNum(MINEWND* mine, UINT num) //绘制按下扫雷后的数字
void CMineWnd::DrawSpecialMine(UINT row, UINT col) //重新绘制雷区域的某个方块
void CMineWnd::OnLButtonDown(UINT nFlags, CPoint point) //单击左键
void CMineWnd::OnLButtonUp(UINT nFlags, CPoint point) //左键弹上
void CMineWnd::OnRButtonDown(UINT nFlags, CPoint point) //单击右键
void CMineWnd::OnRButtonUp(UINT nFlags, CPoint point) //右键弹上
void CMineWnd::OnMouseMove(UINT nFlags, CPoint point) //鼠标移动操作
void CMineWnd::OnMemuStart() //开局
void CMineWnd::OnMemuPrimary() //初级
void CMineWnd::OnMemuSecond() //中级
void CMineWnd::OnMemuAdvance() //高级
void CMineWnd::OnMemuExit() //退出
4.2 详细设计
总体设计是对整个系统的结构化和模块化设计,包括各功能模块的设计和各个功能函数的说明。详细设计则是对各个类和功能函数进行具体的定义和实施。下面是对系统中几个较为重要的函数进行描述。
4.2.1部分功能函数定义
(1)布雷
void CMineWnd::LayMines(UINT row, UINT col)
{ //埋下随机种子
srand( (unsigned)time( NULL ) );
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_pMines[i][j].uAttrib != ATTRIB_MINE)
{ m_pMines[i][j].uAttrib = ATTRIB_MINE;//修改属性为雷
index++;
}
}
}
(2)获取某个小方块区域相邻8个区域的地雷个数
UINT CMineWnd::GetAroundNum(UINT row, UINT col)
{
UINT i, j;
UINT around = 0;
UINT minRow = (row == 0) ? 0 : row - 1;
UINT maxRow = row + 2;
UINT minCol = (col == 0) ? 0 : col - 1;
UINT maxCol = col + 2;
for (i = minRow; i < maxRow; i++)
{ for (j = minCol; j < maxCol; j++)
{ if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uAttrib == ATTRIB_MINE) around++;
}
}
return around;
}
(3)鼠标右键,根据原先不同的标记作状态循环修改,以便用户可以修改其原先标志
void CMineWnd::OnLRBtnDown(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;
for (i = minRow; i < maxRow; i++)
{ for (j = minCol; j < maxCol; j++)
{ if (!IsInMineArea(i, j)) continue;
if (m_pMines[i][j].uState == STATE_NORMAL)
{ m_pMines[i][j].uState = STATE_EMPTY; }
else
if (m_pMines[i][j].uState == STATE_DICEY)
{ m_pMines[i][j].uState = STATE_DICEY_DOWN;
}
}
}
}
(4)失败处理
void CMineWnd::Dead(UINT row, UINT col)
{ //按钮所在的区域
CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
//雷区所在的区域
CRect rcMineArea(MINE_AREA_LEFT, MINE_AREA_TOP,
MINE_AREA_LEFT + m_uXNum * MINE_WIDTH,
MINE_AREA_TOP + m_uYNum * MINE_HEIGHT);
UINT i, j;
if (m_pMines[row][col].uAttrib == ATTRIB_MINE)
{ //失败--踩到雷
for (i = 0; i < m_uYNum; i++)
{ for (j = 0; j < m_uXNum; j++)
{ m_pMines[row][col].uState = STATE_BLAST;
m_pMines[row][col].uOldState = STATE_BLAST;
if(m_pMines[i][j].uAttrib==ATTRIB_MINE&& m_pMines[i][j].uState != STATE_FLAG)
{ m_pMines[i][j].uState = STATE_MINE;
m_pMines[i][j].uOldState = STATE_MINE;
}
}
}
}
else //失败--错误雷
{ for (i = 0; i < m_uYNum; i++)
{ for (j = 0; j < m_uXNum; j++)
{ m_pMines[row][col].uState = STATE_ERROR;
m_pMines[row][col].uOldState = STATE_ERROR;
if (m_pMines[i][j].uAttrib == ATTRIB_MINE
&& m_pMines[i][j].uState != STATE_FLAG)
{
m_pMines[i][j].uState = STATE_MINE;
m_pMines[i][j].uOldState = STATE_MINE;
}
}
}
}
//失败处理
InvalidateRect(rcMineArea);
m_uBtnState = BUTTON_DEAD;
InvalidateRect(rcBtn);
m_uGameState = GS_DEAD;
if (m_uTimer != 0)
{ //将定时器去激活
KillTimer(ID_TIMER_EVENT);
m_uTimer = 0;
}
}
(5)胜利判断并处理
BOOL CMineWnd::Victory()
{ UINT i, j;
CRect rcBtn(m_uBtnRect[1], 15, m_uBtnRect[2], 39);
// 检测是否胜利
for (i = 0; i < m_uYNum; i++)
{ for (j = 0; j < m_uXNum; j++)
{
if (m_pMines[i][j].uState == STATE_NORMAL) return FALSE;
if (m_pMines[i][j].uState == STATE_DICEY) return FALSE;
}
}
//胜利则作胜利处理
m_uBtnState = BUTTON_VICTORY;
m_uGameState = GS_VICTORY;
Invalidate();
if (m_uTimer != 0)
{ //将定时器去激活
KillTimer(ID_TIMER_EVENT);
m_uTimer = 0;
}
return TRUE;
}
(6)绘制雷区
void CMineWnd::DrawMineArea(CPaintDC &dc)
{ CDC dcMemory; //用作内存设备
dcMemory.CreateCompatibleDC(&dc); //使得这个设备与dc兼容
dcMemory.SelectObject(m_bmpMine); //将内存设备与位图资源关联
for (UINT i = 0; iuState = 15 - num;
mine->uOldState = 15 - num;
CRect rcMine(mine->uCol * 16, mine->uRow * 16, (mine->uCol+1) *16, (mine->uRow+1) * 16);
InvalidateRect(rcMine);
}
(8)重新绘制雷区域的某个方块
void CMineWnd::DrawSpecialMine(UINT row, UINT col)
{
CRect rcMine(col * 16, row * 16, (col+1) * 16, (row+1) * 16);
InvalidateRect(rcMine);
}
4.2.2运行界面分析
系统界面分析这一部分主要是系统的运行与维护等,在这里展出了系统的部分运行效果图,并对这些界面进行了分析。
(1)游戏初级是9*9的雷区,共10个地雷,如图4-3所示
图4-3 游戏初级
(2)游戏中级是16*16的雷区,共40个地雷,如图4-4所示
图4-4游戏中级
(3)游戏高级是16*30的雷区,共99个地雷,如图4-5所示
图4-5游戏高级
(4)游戏进行中,此时鼠标可以进行任何操作,如图4-6所示
图4-6游戏进行中
(5)游戏失败,此时鼠标不能在雷区进行操作,提示区的表情变成“哭脸”,用户可以点击表情按钮或者“游戏”菜单中的“开局”,重新开局,如图4-7所示
图4-7游戏失败
(6)“游戏”菜单,在此菜单中用户可以选择游戏难度和退出游戏,还可以点击右上角的“关闭按钮”来退出游戏,如图4-8所示
图4-8“游戏”菜单
五、心得体会
首先感谢老师给我们一次实训的机会。通过这次课程设计,让我充分体会到了理论与实践相结合的重要性。通过我们所学过的知识,老师给我们详细讲解并带领我们做这个扫雷游戏,在这个过程中我们学到了很多书本上学不到的东西,我在写程序的时候也遇到了很多问题,不过在自己的努力和老师的指导下完成了任务。在这次课程设计中,我不断的上网查资料以及翻阅相关书籍,通过不断的摸索、测试、发现问题、解决问题,在老师的帮助下这些问题都一一得到了解决,使得程序能够正常运行。
在此游戏的设计过程中,遇到了很多问题,有些问题比较简单但就是不知道错在哪里,有些大问题知道错在哪里但就是不知道怎么办,后来经过自己的不断修改和调试,这些问题都得到了解决。经过这次课程设计,我认识到应该注意的细节问题,虽然是很小的问题,但可以提高自己编程的能力,而且还可以培养自己编程的严谨性,同时还可以为以后的编程积累经验。编写完这个扫雷游戏,我发现自己有很多不足的地方,感触最深的就是我真的要扎扎实实的打基础。并且我感觉到只要肯下功夫学习,我也可以做出很好的东西,深深明白,只有自己的东西才是最珍贵的。
总之,通过这次课程设计,我学到了很多,也收获了很多,这包括学习上的和生活中的。尽管可能这个系统中还存在一些问题,但我觉得还是很高兴,因为是自己的最重要。
六、参考资料
[1] 王晓东,《计算机算法设计与分析(第3版)》,北京:电子工业出版社,2007
[2] 谭浩强,《C程序设计(第3版)》,北京:清华大学出版社,2005
[3] 郑阿奇,《Visual C++实用教程(第3版)》,北京:电子工业出版社,2007
[4] 谭浩强,《C++程序设计》,北京:清华大学出版社,2004
[5] 严蔚敏,吴伟民,《数据结构(C语言版)》,北京:清华大学出版社,1997
展开阅读全文
相关搜索