扫雷游戏课程设计报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(一)需求分析

题目:

32、实现一个N*M 的扫雷游戏

设计要求:

能够实现一个N*M 的扫雷游戏

a、能够打开一个方格(由于做的是静态显示,故在控制台上方格用‘—’代替),已打开的方格不能关闭

b、能够标记一个方格,标记方格的含义是对该方格有雷的预测(并不表示真的一定有雷)

c、能够给出游戏结果:输、赢

d、N和M可由玩家自己设置

系统功能需求分析:

一个数字和一个雷(boom)。你可以打开(open)一个方格,如果你打开的是一个boom,那么就失败;否则就会打开一个数字,该数字是位于[0,8]的一个整数,该数字表示其所有邻居方格所包含的雷数,应用该信息可以帮助你扫雷。点击到了某区域发现其周围没有雷,那么显而易见应该点开周围的区域,拓展空白区域

(二)概要设计

由于知识储备不足,VC中的MFC应用程序又过于复杂,故退而求其次,不再采用动态显示和界面图形化,采用静态显示来实现扫雷游戏中的主要功能。

用键盘上的‘1’键代替鼠标左击,即打开一个方格查看其属性,已打开的方格不能在关闭;用键盘上的‘2’键代替鼠标右击,即标记一个方格,标记方格的含义是对该方格有雷的预测(并不表示真的一定有雷)

用键盘上的‘↑’‘↓’‘←’‘→’四个键来实现光标在控制台上的自由移动,

相当于用鼠标实现光标在图形界面的移动

游戏区域的高度与宽度及总雷数可由玩家自己设定

应题目要求设计了一个基类:Base和一个继承类:Game。

基类Base主要实现一些基本功能:游戏结束时输出游戏的结果:输赢;

返回控制台上光标的位置返回按下键时所对应的按键控制符

基类Base:

继承类Game是本程序的主要内容,也是实现扫雷游戏的关键部分。

主要实现的功能:初始化图形界面,把游戏区域在控制台上显示出来;利用随机函数进行随机布雷,以保证玩家每次玩游戏时雷的分布位置均不同;得到一个坐标位置周围的雷数,并把数值返回;在一个坐标点上(x,y)点击,在该位置上显示其周围的雷数或拓展空白区域或失败;如果一个坐标点的周围没有雷,则拓展空白区域,并递归拓展;其中saolei()函数是类Game里的关键函数体,用来判断玩家按下了哪个键,并作出相应反应(上下左右四个方向的移动,打开一个方格,标记一个方格),并判断游戏的输与赢

继承类Game:

(三)详细设计

核心算法:

(1)布雷函数:

初始化时把数组里的值全部置为0,然后利用srand(),rand()随机机制产生随机数,分别对列和行取模,便产生了雷的随机位置。但是布雷前,先要判断此随机位置是否已经布上了雷。

int Game::initpool(int width,int height,int num)

{ poolWidth=width;

poolHeight=height;

if(num<0||num>=width*height||width>GAME_MAX_HEIGHT||width<=0||height<=0||hei ght>GAME_MAX_HEIGHT) return 1;

//初始是把游戏区域也即是数组里的值全都置为0

for(int y=0;y<=height+1;y++)

{for(int x=0;x<=width+1;x++)

{pool[y][x]=0;}

}

//利用伪随机函数进行随机布雷,以保证每次点击游戏时雷的分布位置不同

srand(time(NULL));

while(num!=0){

int x=rand()%width+1;

int y=rand()%height+1;

if(pool[y][x]==0){

pool[y][x]=GMARK_BOOM;

num--;//num为设置的总雷数}

}

//初始化光标位置

curX=1;curY=1;

MoveCursor();

return 0;

}

(2)打开方格,查看方格的属性

//在该位置上显示其周围的雷数或拓展空白区域或失败

int Game::tryopen(int x,int y){

int m=0;

if(pool[y][x] & GMARK_BOOM)m=-1;

else{

int count=shownum(x,y);

if(count==0)tuozhan(x,y);//拓展空白区域

else pool[y][x]=count;}

return m; }

(3)获得周围雷的数目

扫描其周围的所有相邻方格,记录雷数,并把值返回;扫描前要选择合理的起始点

int Game::shownum(int x,int y){

int count=0;

for(int Y=-1;Y<=1;Y++)

for(int X=-1;X<=1;X++){

if(pool[y+Y][x+X]&GMARK_BOOM)

count++;}

return count; }

(4)展拓空白区域

展拓原因:当玩家点击的方块周围无雷时,此方块会被绘为空白,此时没有必要让玩家将其周围一一点开,应直接打开展拓条件:周围雷数为零

函数int tuozhan(intx,inty)

参数:x,y所点击的方块位置

算法:递归

递归结束条件:某一个方块不需要拓展就是因为其周围的雷数不是零int Game::tuozhan(int x,int y){

if((x>0&&x<=poolWidth)&&(y>0&&y<=poolHeight)&&(pool[y][x]==0)){

int count=shownum(x,y);

if(count==0){

pool[y][x]=GMARK_EMPTY;

for(int Y=-1;Y<=1;Y++)

for(int X=-1;X<=1;X++)

{tuozhan(x+X,y+Y);}

}

else pool[y][x]=count;}

return 0;}

(5)在控制台上把扫雷区域显示出来

在还未按键时,调用huatu()函数把游戏界面在控制台上显示出来,即全部显示为方格。以后每按键一次。刷新一次界面

int Game::huatu(int n=0)

{for(int y=1;y<=poolHeight;y++)

{Base::GotoXY(1,y);

for(int x=1;x<=poolWidth;x++)

{if(pool[y][x]==0)

putchar('.');

else if(pool[y][x]==GMARK_EMPTY)

putchar(' ');

else if(pool[y][x]>0 && pool[y][x]<=8)

putchar('0'+pool[y][x]);

else if(n==0 && (pool[y][x]& GMARK_MARK) )

putchar('#');

else if(pool[y][x]& GMARK_BOOM)

{if(n!=0)putchar('*');

else putchar('.');}

相关文档
最新文档