//扫雷游戏
#include<iostream>
#include<iomanip> //输出 对齐 (manipulator操纵器) setw(n)
using namespace std;
#include<stdlib.h>
#include<time.h>
#define M1 10 //行
#define M2 8 //列
#define MYN 8 //雷个数
int arr1[M1+2][M2+2]; //arr1用于布雷,arr2用于扫雷显示
char arr2[M1+2][M2+2];
int E1[8]={-1,0,1,1,1,0,-1,-1};//搜索规则
int E2[8]={-1,-1,-1,0,1,1,1,0};
//初始化
void initiate()
{
for(int i=0;i<M1+2;i++)
{
for(int j=0;j<M2+2;j++)
{
if(i==0||j==0||i==M1+1||j==M2+1)
arr2[i][j]='#'; //边界墙 --对*操作时不影响
else
{
arr1[i][j]=0;
arr2[i][j]='*'; //开始界面全是*
}
}
}
}
//布雷和数字
void putLandmine ()
{
srand((unsigned int)time(NULL));
for(int k=0;k<MYN;k++) //随机下标布置地雷
{
int i=1+rand()%(M1-1);
int j=1+rand()%(M2-1);
arr1[i][j]=-1;
}
//计算数字 :
int temp=0;
for(int i=1;i<=M1;i++)
{
for(int j=1;j<=M2;j++)
{
if(arr1[i][j]!=-1)
{
temp=0;
for(int k=0;k<8;k++)
if(arr1[i+E1[k]][j+E2[k]]==-1) //如果四周有雷,计数并放在(i,j)位置上
temp++;
arr1[i][j]=temp;
}
}
}
}
//打印1
void view()
{
for(int i=0;i<M1+2;i++)
{
for(int j=0;j<M2+2;j++)
{
cout<<setw(3)<<arr1[i][j];//setw(n) 保证输出宽度为n
}
cout<<endl;
}
}
//打印arr2面向用户
void view2()
{
for(int i=0;i<M1+2;i++)
{
for(int j=0;j<M2+2;j++)
{
if(i==0&&j!=(M2+1)) //打印列数
{
cout<<setw(3)<<j;
}
else if(j==0&&i!=(M1+1)) //打印行数
{
cout<<setw(3)<<i;
}
else
{
cout<<setw(3)<<arr2[i][j];
}
}
cout<<endl;
}
}
void defeat() //打印失败时的界面
{
for(int i=0;i<M1+2;i++)
{
for(int j=0;j<M2+2;j++)
{
if(arr1[i][j]==-1)
arr2[i][j]='U'; //U表示雷
}
}
view2();
}
void set(int x,int y) //是0则递归展开
{
if(arr1[x][y]==0) //数字是0的位置周围一定没雷
{
arr2[x][y]=' ';
for(int k=0;k<8;k++)
{
if(x+E1[k]>=0&&x<=(M1+2)&&y+E2[k]>=0&&y<=(M2+2)&&arr2[x+E1[k]][y+E2[k]]=='*')
{
set(x+E1[k],y+E2[k]);
}
}
}
else
{
arr2[x][y]=arr1[x][y]+'0';//按字符存到arr2中
}
}
int LmGame(int x,int y) //扫雷过程 踩雷返回0,否则返回1
{
if(arr1[x][y]==-1) //踩着雷了
{
defeat();
cout<<"踩着雷了!!"<<endl;
return 0; //直接返回
}
set(x,y);
view2();
cout<<"很棒!继续扫雷"<<endl;
return 1;
}
int succeed()//判断全部扫完 若是返回1 否则返回0
{
int count=0;
for(int i=1;i<=M1;i++)
{
for(int j=1;j<=M2;j++)
{
if(arr2[i][j]=='*')
{
count+=1;
}
}
}
if(count==MYN) //成功条件 剩余个数刚好是雷的个数
return 1;
else
return 0;
}
int allow(char ca[],int& x,int& y) //误输入? 判断
{
x=0;y=0;
for(int i=0;ca[i]!='\0';i++)
{
if(ca[i]==' ')
{
for(int j=0;j<i;j++)
{
x=x*10;
x+=(int)ca[j]-48;
}
for(int k=i+1;ca[k]!='\0';k++)
{
y=y*10;
y+=(int)ca[k]-48;
}
system("cls");
return 1;
}
}
system("cls");
return 0;
}
int main()
{
cout<<"开始扫雷游戏"<<endl;
initiate();
putLandmine ();
view(); //查看部署
view2(); //用户界面
char ca[10]; //输入
int x,y,p,s;
do{
cout<<"输入坐标:";
gets(ca); //输入字符串:数字空格数字
int ret=allow(ca,x,y);
if(ret==0||x<1||x>M1||y<1||y>M2) //误输入? 判断
{
view2();
cout<<"请输入你要扫雷的下标x y:(1~9)" <<endl;
cout<<"你的输入有误,重新输入"<<endl;
}
else if(arr2[x][y]!='*')
{
view2();
cout<<"请输入你要扫雷的下标x y:(1~9)" <<endl;
cout<<"这里已经扫过,重新输入"<<endl;
}
else
{
system("cls"); //清屏
p=LmGame(x,y); //扫雷
s=succeed(); //是否成功
}
}while(p&&!s||x<1||x>M1||y<1||y>M2);
// p==1单步没有踩雷、且s==0整体没有扫完---继续
// 误输入---继续
if(s==1) cout<<"哇哦,扫完了!原来你就是扫雷大神"<<endl;
else cout<<"游戏结束,再接再厉" <<endl;
system("pause");
return 0;
}