C++扫雷课程设计文档格式.docx
《C++扫雷课程设计文档格式.docx》由会员分享,可在线阅读,更多相关《C++扫雷课程设计文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
(1)真正的面向对象编程,使开发人员不用加入太多的代码,加快了系统开发的速度。
(2)可视化的编程方法以及向导的功能,使开发人员不用加入太多的代码就可以开发出标准的Windows程序。
(3)数据访问的特性,允许对包括MicrosoftSQLServer和其他企业数据库在内的大部分数据库格式建立数据库和前端应用程序,以及可调整的服务器端部件等。
(4)通过ActiveX技术可使用其他应用程序提供的功能,例如MicrosoftWord字处理器、MicrosoftExcel电子数据表及其他Windows应用程序,甚至可直接使用VisualBasic创建的应用程序和对象。
(5)Internet功能强大,使用户很容易在应用程序内通过Internet或企业内部网(Intranet)访问文档和应用程序,或者创建Internet服务器应用程序。
(6)已完成的应用程序是真正的.exe文件,您可以自由发布。
1.3关于本课题
随着世界经济的长足发展和计算机技术的日益成熟,计算机被应用到人类活动的各个领域,各种应用软件也相继问世,这其中有相当一部分是游戏软件。
使用游戏软件自然是为了满足人们对娱乐性的要求,而有些软件大都采用3D设计对系统配置的要求较高。
在众多游戏软件中,也不乏一些小游戏的身影,它们对系统的配置要求较低。
能够满足人们对娱乐性的需求,是人们在完成工作娱乐时候的最好选择。
现在越来越多的人投入到这种小游戏的开发当中,它已经成为一类必不可少的游戏软件。
在各种操作系统中都附带了一些小的游戏,而这些游戏也成为电脑用户软件中不可或缺的一部分。
作为本系统的开发工具,MicrosoftVisualC++6.0成为首选。
它具有可视化的编程界面、详细的提示、以及完善的帮助文档,使得软件开发人员感到无比的亲切感。
第二章游戏的总体分析与设计
2.1游戏功能简介
当前各种游戏软件层出不穷。
因为游戏的开发成本非常大,所以游戏的开发具有一定的风险性,但是一些小游戏的开发具有成本小,编写简单的优势,所以这些小游戏在游戏开发中也占有一席之地。
在这类小游戏中包括益智类游戏,它以画面精美游戏方法简单等特点得到大家的认可。
成为人们在工作之余不可或缺的好伙伴。
针对真种情况我用VC编写了扫雷这款小游戏。
下面对该游戏的功能做个简单的介绍。
扫雷游戏的基本功能:
点击鼠标左键于未知区域,如果未知区域有雷,游戏停止,显示所有的地雷。
如果没雷,则显示周围雷数,如果周围没雷,则再查看周围八个区域是否有雷直到有雷为止并显示,这其实是一个递归过程。
点击鼠标右键于未知区域,则将其置为有雷而不管是否真的有雷。
可选择初、中、高三级并可自定义雷数和区域大小。
雷区右下角显示总雷数减去被标明有雷区域的数目。
雷区右下角显示扫雷的时间。
将雷全部扫清后或失败后显示一对话框。
2.2设计构想
相信大多数使用Windows操作系统的使用者,对这款游戏都不陌生。
这款游戏不止操作简单,规则也不难,再加上游戏速度的控制机制得宜,让整个游戏在操作过程中充满了快乐与紧张的气氛。
除了游乐当中能带给使用者快乐之外,游戏的设计内容无形中也不断训练使用者的逻辑思考能力,对于依靠高度脑力工作的现代人,都可以通过这个游戏,不时的检验一下自己,所以我们不难发现,在各种可携带的电子产品上都有这款游戏的踪影。
在设计之前,我们先来了解这款游戏的规则:
在不掀开任何藏有地雷的方块情况下,以最快的速度找出所有的地雷。
如果在掀开方块的过程中,不小心翻开(踩到)藏有地雷的方块,则宣告失败(游戏结束),惟有将所有不含地雷的方块掀开,游戏才算成功。
游戏的操作方面主要以鼠标为主,当鼠标指针对准未翻开的方块按下左键时即表示翻开方块,当鼠标指针对准未翻开的方块按下右键时即表示标示或疑示地雷,反复按下右键则方块会以未标示→标示→疑似三者关系不断循环。
游戏者可以通过地雷区内的数字提示了解以数字为中心的其周边八个方格内所含的地雷数,假若翻开的方块显示数字“3”,则表示以其为中心的周边方块内藏有3个地雷。
当按下的方块不是地雷,且周边八个方块也都没有地雷时,方块会以被翻开方块的八个方向将空白方块翻开。
2.3流程规划
流程规划大致上可以分为三个部分,分别为:
画面初始、游戏者按下第一个方块和为非地雷方块时展开。
画面初始时,以游戏者最后一次设定的地雷区大小为范围画出地雷区,当游戏者按下第一个方块时产开始计时,接着就是如何判断按下的方块是非地雷时的处理,这也是整个游戏的技术核心,我们可以通过递归的观念来检查周边的方块是否含有地雷及是否继续往外翻开,直到踩到雷或者游戏胜利为止。
第三章扫雷游戏的具体实现过程
3.1扫雷游戏模块的实现
扫雷游戏的开发主要包括两大部分:
一个部分是布雷,该部分主要将雷随机布置在游戏区域内,以避免出现相同的雷区布置地图。
另一部分是扫雷,该部分包括判断鼠标左键点击某区域该区域是否是雷,如果是雷该如何操作,如果不是雷该如何操作,鼠标右键点击某区域时如果判断该区域是雷则加以标记,如果不是雷也加以标记,以及当鼠标双击某区域时,判断与该区域相邻的其它8个区域是否是雷并做一个标记。
下面首先介绍第一部分之一——扫雷主窗体创建。
3.1.1扫雷游戏主窗体的创建
启动VisualC++6.0后,选择新建工程,VisualC++6.0提供了用户可能需要的各种类型的应用程序模板。
如果是这种情况,选择MFCAppWizard(exe)项目,输入工程名称和位置,将创建一个新的工程如下:
选择基于Singledocument:
其它的默认,建立新的工程。
下面介绍一下如何创建:
1.资源视图中添加扫雷所需要的位图
2.在窗口类定义的前面添加下面两个新建的类
//创建一个雷位类
classOneMine
{public:
OneMine();
voidInitOneMine();
//初始化一个雷位
boolIsMine;
//是否是雷
boolOpened;
//是否已经打开
boolMark;
//是否已经被标记
shortAroundMines;
//周边的雷数
shortstate;
};
//显示图形号
//创建雷区类
classMines
{public:
boolGameOver;
//扫雷是否结束
shortTimes;
//扫雷所用的时间
shortRows,Cols;
//雷区的行数、列数
shortMinesCount;
//布设雷的数量
shortMarkMines;
//标对雷的数量
shortVirtualMines;
//标记为雷的数量
OneMine*pos[52][32];
//存放雷对象的数组指针
Mines();
~Mines();
voidReInitMine(shortrow,shortcol,shortmines);
//重新初始化雷区
voidLayOneMines();
//布置一个地雷
voidCalculateAroundMine(intx,inty);
//计算每个雷周边的雷数
voidShowOneMine(intx,inty);
//显示一个雷位
voidShowAllMine();
//显示所有雷位
voidOpenOneMine(intx,inty);
//打开一个雷位
voidMarkOneMine(intx,inty);
};
//标记一个雷位
3.在窗口类中添加雷区对象:
MinespMine;
4.在OnDraw(CDC*pDC)函数中添加显示雷区功能:
if(pView==NULL)pView=this;
//给窗口类指针赋值
pMine.ShowAllMine();
//显示雷区
5.在窗体类视图上单击鼠标右键,选择AddWindowsMessageHandler
单击WM_LButtonDown,然后再单击“AddHandler”按钮,添加鼠标左键处理函数
单击WM_RButtonDown,然后再单击“AddHandler”按钮,添加鼠标右键处理函数
6.在鼠标左键处理函数OnLButtonDown(UINTnFlags,CPointpoint)中添加下面代码:
intx=point.x/16+1,y=point.y/16+1;
//计算坐标
pMine.OpenOneMine(x,y);
//打开该位置地雷
7.在鼠标右键处理函数OnRButtonDown(UINTnFlags,CPointpoint)中添加下面代码:
//计算坐标
pMine.MarkOneMine(x,y);
//该位置地雷做标记
3.1.2主界面控制菜单的设计
接下来回到资源编程界面,编写菜单资源,用来控制扫雷的过程,难度选定,以及自定义难度窗口等。
(1)设置菜单包含:
开始,初级,中级,高级,自定义。
(2)帮助菜单获取该软件的版本信息。
如下:
将菜单添加到主界面,至此主窗体基本创建完毕。
运行如下:
3.2扫雷游戏核心-----布雷算法设计
再窗口代码中添加如下代码:
//雷位构造函数
OneMine:
:
OneMine()
{InitOneMine();
}
//重新初始化一个雷位
voidOneMine:
InitOneMine()
{IsMine=Opened=Mark=false;
AroundMines=0;
state=-1;
//state=-1为该雷未打开,也未标记,state=1到8为该雷位周边地雷数
//state=9为该雷位做了标记
//state=10为该雷位有疑问
//state=11为该雷位标错了地雷
//state=13为真雷}
//雷区构造函数
Mines:
Mines()
{for(inti=0;
i<
32;
i++)
for(intj=0;
j<
52;
j++)
pos[j][i]=newOneMine();
ReInitMine(12,20,30);
//雷区析构函数
~Mines()
deletepos[j][i];
//重新初始化雷区
voidMines:
ReInitMine(shortrow,shortcol,shortmines)
{inti,j;
GameOver=false;
Times=0;
Rows=row;
Cols=col;
MinesCount=mines;
MarkMines=0;
VirtualMines=0;
for(i=1;
=Rows;
i++)//把所有的雷位地雷清除
for(j=1;
=Cols;
pos[j][i]->
InitOneMine();
srand((unsigned)GetTickCount());
//初始化产生随机数函数
for(i=0;
MinesCount;
i++)
LayOneMines();
//布置地雷
i++)//计算每个雷位周边的雷数
CalculateAroundMine(j,i);
//布一个地雷
LayOneMines()
{intm,n;
do{
m=rand()%Cols+1;
n=rand()%Rows+1;
//随机产生雷位坐标
}while(pos[m][n]->
IsMine);
pos[m][n]->
IsMine=true;
当然,还得添加代码用来在游戏区域显示随机布置的雷和周边情况,在函数中添加如下代码:
//计算一个雷位周边的地雷数
CalculateAroundMine(intx,inty)
{intmines=0;
for(inti=x-1;
=x+1;
for(intj=y-1;
=y+1;
mines=mines+pos[i][j]->
IsMine;
pos[x][y]->
AroundMines=mines;
}
//显示一个雷位图
ShowOneMine(intx,inty)
{CBitmapbmp;
bmp.LoadBitmap(pos[x][y]->
state+1000);
CDCdcMemory,*dc;
dc=pView->
GetDC();
//在内存中创建一个位图兼容设备
dcMemory.CreateCompatibleDC(dc);
dcMemory.SelectObject(&
bmp);
//将图片选入兼容设备
//将兼容设备的内容copy到屏幕设备中,实现真正的Paint
dc->
BitBlt(x*16-16,y*16-16,16,16,&
dcMemory,0,0,SRCCOPY);
//显示所有雷位图
ShowAllMine()
{for(inti=1;
for(intj=1;
ShowOneMine(j,i);
3.3扫雷鼠标事件的处理
(1)首先,设计雷区和非雷区的判断算法。
扫雷时需要判断每个格子的状态,可事先为格子设定一些状态,使之对应不同的BOOL值或整数值。
在二维、三维游戏里,有一种简单的构造地图的方法,即将地图划分为m*n的规格格子,使每一个格子对应二维数组中的一项,当鼠标单击时,通过找出鼠标点击区域,找到相应的格子,判断格子状态来替换相应的位图。
具体算法思想如下:
A.在应用程序的客户区划分一块区域,将该区域划分为n*m相同大小的格子;
B.将每一个格子的状态对应到二维数组的相应项上;
C.当鼠标点击某一块区域时,首先判断是否在各种区域,然后再通过鼠标的坐标找到相应的格子;
D.查询格子的状态,从而调用相应的位图进行位图替换;
(2)鼠标左键事件的处理。
分两种情况:
A.当相应区域不是雷区时,挖开区域,并且若能据此判断周围区域也不是雷区则将周围相应区域也挖开;
B.当区域是雷区时,则界面中所有的雷区同时“炸开“:
第一步先显示一个提示框,第二部当提示框关闭时,所有非雷区显示出来。
C.鼠标在笑脸图片上,单击可以重新开始。
(3)对单击鼠标右键事件处理
第一次用右键单击某个区域时,改区域上插上一面小红旗,此时单击左键没有任何变化,第二次用右键单击时恢复原状。
(4)双击左键事件处理
在展开的区域,并且已经确定了周围的雷数,双击可以叠加展开非雷区域,以减少用户的单击操作。
基于以上的思想,在VC++6.0中进行“扫雷”的主要编码如下:
//打开一个雷位
OpenOneMine(intx,inty)
{OneMine*p=pos[x][y];
if(x>
Cols||x<
1||y>
Rows||y<
1)return;
//如果点的位置不在雷区,则返回
if(GameOver)return;
//如果扫雷结束,则返回
if(p->
Opened)return;
//如果该位置已经打开,则返回
Mark)return;
//如果该位置已经标记了,则返回
IsMine)//如果该雷位是地雷
{for(inti=1;
i++)//找出所有的地雷,并显示出来
for(intj=1;
if(pos[j][i]->
IsMine)
{pos[j][i]->
state=12;
ShowOneMine(j,i);
elseif(pos[j][i]->
state==9)
state=11;
p->
state=13;
ShowOneMine(x,y);
GameOver=true;
return;
else//如果该雷位不是地雷
{p->
Opened=true;
p->
state=p->
AroundMines;
if(p->
AroundMines==0)/*如果该雷位周边的雷数为零,打开周边的雷位,采用递归调用的方法*/
{if(x!
=1)OpenOneMine(x-1,y);
//打开左边
if(x!
=Cols)OpenOneMine(x+1,y);
//打开右边
if(y!
=1)OpenOneMine(x,y-1);
//打开上边
=Rows)OpenOneMine(x,y+1);
//打开下边
if(x!
=1&
&
y!
=1)OpenOneMine(x-1,y-1);
//打开左上
=Rows)OpenOneMine(x-1,y+1);
//打开左下
=Cols&
=1)OpenOneMine(x+1,y-1);
//打开右上
=Rows)OpenOneMine(x+1,y+1);
//打开右下}
}
//标记一个雷位
MarkOneMine(intx,inty)
//如果点的位置不在雷区,则返回
switch(p->
state)
{case-1:
{p->
state=9;
Mark=true;
VirtualMines++;
if(p->
IsMine)MarkMines++;
break;
case9:
state=10;
VirtualMines--;
IsMine)MarkMines--;
case10:
state=-1;
Mark=false;
break;
if(MarkMines==MinesCount)
{:
MessageBox(NULL,"
恭喜您,扫雷成功了!
"
"
提示信息"
MB_OK);
this->
GameOver=true;
3.4扫雷其它处理
3.4.1难度设置菜单消息处理
菜单项中包含扫雷难度设置,如初