C++扫雷程序输出报告材料.docx
《C++扫雷程序输出报告材料.docx》由会员分享,可在线阅读,更多相关《C++扫雷程序输出报告材料.docx(20页珍藏版)》请在冰豆网上搜索。
![C++扫雷程序输出报告材料.docx](https://file1.bdocx.com/fileroot1/2023-2/10/5080f764-b8e5-4cf4-b632-d4205e95bbb8/5080f764-b8e5-4cf4-b632-d4205e95bbb81.gif)
C++扫雷程序输出报告材料
程序输出报告
程序设计时使用环境----Win10VS2015
1程序设计思路
模块化设计一个扫雷游戏。
要实现埋雷,计算一个格子周围雷数,打开雷位,显示雷区几个功能.
需要以下几个主要数据,判断雷位的雷是否存在,雷位周围的雷数,是否已经被打开,游戏是否结束,雷区大小,布雷量(本程序中非必须保存于类中数据)
2功能的具体实现
为了方便计算和理解先分出类
classOneMine
{
OneMine();//雷位构造函数
voidInitOneMine();//初始化一个雷位
boolIsMine;//是否是雷
boolOpened;//是否已经打开
shortAroundMines;//周边的雷数
friendclassOperation;
friendclassMines;
};
classMines//创建雷区类
{
boolGameOver;//扫雷是否结束
shortRows;//雷区的行数
shortCols;//雷区的列数
shortMinesCount;//布设雷的数量
OneMine*pos[50][50];//存放雷对象的数组指针
public:
Mines();//雷区类构造函数
~Mines();//析构函数
friendclassOperation;
};
classOperation:
publicMines//操作类
{
public:
voidReInitMine(shortrow,shortcol,shortmines);//重新初始化雷区
voidLayOneMines();//布置一个地雷
voidCalculateAroundMine(intx,inty);//计算每个雷周边的雷数
voidShowOneMine(intx,inty);//触雷时的执行函数
voidShowMine();//显示未触雷时的雷区情况
voidShowAllMine();//触雷时的触发函数
voidOpenOneMine(intx,inty);//打开一个雷位
};
实现埋雷
//布一个地雷
voidOperation:
:
LayOneMines()//布一个地雷
{
intm,n;
do{
m=rand()%Cols+1;n=rand()%Rows+1;//随机产生雷位坐标
}while(pos[m][n]->IsMine);
pos[m][n]->IsMine=true;
}
PS:
rand()函数的输出是依赖于默认输入数据的,需要使用windows.h中的GetTickCount()函数来初始化
实现计算格子周围雷数
voidOperation:
:
CalculateAroundMine(intx,inty)//计算雷位周边雷数
{
intmines=0;
for(inti=x-1;i<=x+1;i++)
for(intj=y-1;j<=y+1;j++)
mines=mines+pos[i][j]->IsMine;//利用IsMine数据的特性计算周围雷数
pos[x][y]->AroundMines=mines;
}
实现打开雷位
voidOperation:
:
OpenOneMine(intx,inty)//打开一个雷位
{
if(x>Cols||x<1||y>Rows||y<1)return;//如果点的位置不在雷区,则返回
if(GameOver)return;//如果扫雷结束,则返回
if(pos[x][y]->Opened)return;//如果该位置已经打开,则返回
if(pos[x][y]->IsMine)//如果该雷位是地雷
{
ShowAllMine();//找出所有的地雷,并显示出来
cout<<"BOOM!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
";
GameOver=true;
return;
}
else//如果该雷位不是地雷
{
pos[x][y]->Opened=true;
if(pos[x][y]->AroundMines==0)//如果该雷位周边的雷数为零,打开周边的雷位,采用递归调用的方法
{
if(x!
=1)OpenOneMine(x-1,y);//打开左边
if(x!
=Cols)OpenOneMine(x+1,y);//打开右边
if(y!
=1)OpenOneMine(x,y-1);//打开上边
if(y!
=Rows)OpenOneMine(x,y+1);//打开下边
if(x!
=1&&y!
=1)OpenOneMine(x-1,y-1);//打开左上
if(x!
=1&&y!
=Rows)OpenOneMine(x-1,y+1);//打开左下
if(x!
=Cols&&y!
=1)OpenOneMine(x+1,y-1);//打开右上
if(x!
=Cols&&y!
=Rows)OpenOneMine(x+1,y+1);//打开右下}
}
}
}
实现输出未触雷的雷区
voidOperation:
:
ShowMine()//显示雷区
{
intk=0;//换行判定变量
if(GameOver==false)
{
if(Rows>=10)
{
cout<<"";
}
cout<<"";
for(inti=1;i<=Cols;i++)//输出横坐标
{
cout<
if(Cols>=10&&i<10)
{
cout<<"";
}
}
for(inti=1;i<=Rows;i++)
for(intj=1;j<=Cols;j++)
{
if(k%Cols==0)
{
cout<if(i<10&&Rows>=10)
cout<<"";
}
if(Rows>=10)
cout<<"";
if(pos[j][i]->Opened)
{
cout<AroundMines<<"";
k++;
}
else
{
cout<<"H";
k++;
}
}cout<}
}
实现触雷后的雷区显示
voidOperation:
:
ShowOneMine(intx,inty)//触发雷后显示一个雷
{
inti=x;
intj=y;
if(pos[i][j]->IsMine)//right
{
cout<<"M";
}
else
{
cout<AroundMines<<"";
}
}
voidOperation:
:
ShowAllMine()//触发雷后显示所有雷
{
intk=0;//换行判定变量
if(Rows>=10)
{
cout<<"";
}
cout<<"";
for(inti=1;i<=Cols;i++)//输出横坐标
{
cout<
if(Cols>=10&&i<10)
{
cout<<"";
}
}
for(inti=1;i<=Rows;i++)
for(intj=1;j<=Cols;j++,k++)
{
if(k%Cols==0)
{
cout<if(i<10&&Rows>=10)
cout<<"";
}
if(Rows>=10)
cout<<"";
ShowOneMine(j,i);
}cout<}
3程序运行结果
4程序分析
由于不是鼠标操作,加一道标记操作显得过于繁琐,所以没有加入标记地雷功能,也因此该地雷游戏其实没有完整的胜利途径.
没有将雷区框架(即X-Y轴)输出函数化
5程序改进思路
加入标记地雷功能,使用条件判断,每次输入打开行列坐标前,请求输入Y/N是否进行标记操作.
对类进行详细分类,分别封装是否存雷类,是否打开类,是否结束游戏类….
6附:
完整源代码
//ConsoleApplication1.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include"windows.h"
usingnamespacestd;
classOneMine
{
OneMine();//雷位构造函数
voidInitOneMine();//初始化一个雷位
boolIsMine;//是否是雷
boolOpened;//是否已经打开
shortAroundMines;//周边的雷数
friendclassOperation;
friendclassMines;
};
classMines//创建雷区类
{
boolGameOver;//扫雷是否结束
shortRows;//雷区的行数
shortCols;//雷区的列数
shortMinesCount;//布设雷的数量
OneMine*pos[50][50];//存放雷对象的数组指针
public:
Mines();//雷区类构造函数
~Mines();//析构函数
friendclassOperation;
};
classOperation:
publicMines//操作类
{
public:
voidReInitMine(shortrow,shortcol,shortmines);//重新初始化雷区
voidLayOneMines();//布置一个地雷
voidCalculateAroundMine(intx,inty);//计算每个雷周边的雷数
voidShowOneMine(intx,inty);//触雷时的执行函数
voidShowMine();//显示未触雷时的雷区情况
voidShowAllMine();//触雷时的触发函数
voidOpenOneMine(intx,inty);//打开一个雷位
};
OneMine:
:
OneMine()//雷位构造函数
{
InitOneMine();
}
voidOneMine:
:
InitOneMine()//重新初始化一个雷位
{
IsMine=false;//雷位默认无雷
Opened=0;//雷位默认未打开
AroundMines=0;//雷位周围雷数默认为无
}
Mines:
:
Mines()//雷区构造函数
{
for(inti=0;i<50;i++)
for(intj=0;j<50;j++)
pos[j][i]=newOneMine();
}
Mines:
:
~Mines()//雷区析构函数
{
for(inti=0;i<50;i++)
for(intj=0;j<50;j++)
deletepos[j][i];
}
voidOperation:
:
ReInitMine(shortrow,shortcol,shortmines)//重新初始化雷区
{
inti,j;
GameOver=false;//游戏默认为未结束
Rows=row;Cols=col;//行数列数
MinesCount=mines;//初始雷数
for(i=1;i<=Rows;i++)//把所有的雷位地雷清除
for(j=1;j<=Cols;j++)
pos[j][i]->InitOneMine();//InitOneMine()为初始化雷位函数
srand((unsigned)GetTickCount());//初始化产生随机数函数
for(i=0;iLayOneMines();
for(i=1;i<=Rows;i++)//计算每个雷位周边的雷数
for(j=1;j<=Cols;j++)
CalculateAroundMine(j,i);
}
voidOperation:
:
LayOneMines()//布一个地雷
{
intm,n;
do{
m=rand()%Cols+1;n=rand()%Rows+1;//随机产生雷位坐标
}while(pos[m][n]->IsMine);
pos[m][n]->IsMine=true;
}
voidOperation:
:
CalculateAroundMine(intx,inty)//计算雷位周边雷数
{
intmines=0;
for(inti=x-1;i<=x+1;i++)
for(intj=y-1;j<=y+1;j++)
mines=mines+pos[i][j]->IsMine;//利用IsMine数据的特性计算周围雷数
pos[x][y]->AroundMines=mines;
}
voidOperation:
:
ShowOneMine(intx,inty)//触发雷后显示一个雷
{
inti=x;
intj=y;
if(pos[i][j]->IsMine)//right
{
cout<<"M";//雷显示为"M"
}
else
{
cout<AroundMines<<"";//非雷被打开后显示周围雷数
}
}
voidOperation:
:
ShowAllMine()//触发雷后显示所有雷
{
intk=0;//换行判定变量
if(Rows>=10)//适当输出空格使得雷区不至于变形(以下输出空格均属于此功能)
{
cout<<"";
}
cout<<"";
for(inti=1;i<=Cols;i++)//输出横坐标
{
cout<
if(Cols>=10&&i<10)
{
cout<<"";
}
}
for(inti=1;i<=Rows;i++)
for(intj=1;j<=Cols;j++,k++)
{
if(k%Cols==0)
{
cout<if(i<10&&Rows>=10)
cout<<"";
}
if(Rows>=10)
cout<<"";
ShowOneMine(j,i);
}cout<}
voidOperation:
:
ShowMine()//显示雷区
{
intk=0;//换行判定变量
if(GameOver==false)
{
if(Rows>=10)
{
cout<<"";
}
cout<<"";
for(inti=1;i<=Cols;i++)//输出横坐标
{
cout<
if(Cols>=10&&i<10)
{
cout<<"";
}
}
for(inti=1;i<=Rows;i++)
for(intj=1;j<=Cols;j++)
{
if(k%Cols==0)
{
cout<if(i<10&&Rows>=10)
cout<<"";
}
if(Rows>=10)
cout<<"";
if(pos[j][i]->Opened)
{
cout<AroundMines<<"";
k++;
}
else
{
cout<<"H";
k++;
}
}cout<}
}
voidOperation:
:
OpenOneMine(intx,inty)//打开一个雷位
{
if(x>Cols||x<1||y>Rows||y<1)return;//如果点的位置不在雷区,则返回
if(GameOver)return;//如果扫雷结束,则返回
if(pos[x][y]->Opened)return;//如果该位置已经打开,则返回
if(pos[x][y]->IsMine)//如果该雷位是地雷
{
ShowAllMine();//找出所有的地雷,并显示出来
cout<<"BOOM!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
";
GameOver=true;
return;
}
else//如果该雷位不是地雷
{
pos[x][y]->Opened=true;
if(pos[x][y]->AroundMines==0)//如果该雷位周边的雷数为零,打开周边的雷位
{
if(x!
=1)OpenOneMine(x-1,y);//打开左边
if(x!
=Cols)OpenOneMine(x+1,y);//打开右边
if(y!
=1)OpenOneMine(x,y-1);//打开上边
if(y!
=Rows)OpenOneMine(x,y+1);//打开下边
if(x!
=1&&y!
=1)OpenOneMine(x-1,y-1);//打开左上
if(x!
=1&&y!
=Rows)OpenOneMine(x-1,y+1);//打开左下
if(x!
=Cols&&y!
=1)OpenOneMine(x+1,y-1);//打开右上
if(x!
=Cols&&y!
=Rows)OpenOneMine(x+1,y+1);//打开右下
}
}
}
intmain()//主函数
{
shortrow,col,mines;
intx,y,i;
Operationp;
cout<<"请输入行、列、布雷数"<cin>>row>>col>>mines;
p.ReInitMine(row,col,mines);
p.ShowMine();
for(i=0;i<=row*col;i++)//循环要求输入打开雷位并循环输出雷区
{
cout<<"请输入要打开的行、列坐标:
"<cin>>y>>x;
p.OpenOneMine(x,y);
p.ShowMine();
cout<}
return0;
}