自己写了个控制台的扫雷
输入坐标然后显示地图
但是输入某些坐标的时候卡住不动了 不知道是陷入死循环还是什么问题
求大神解答 已考虑无雷区自动翻开的死循环 可能是双击时陷入死循环 但看不出是不是这个问题 不知道怎么修改代码
#include
#include
#include
#include
#define len 20 //边数
int mine[len+2][len+2] = {0}; //+2是为了在计算周围一圈雷数时不必分四周顶点边界区域,不越界
int dispMine[len+2][len+2] = {0}; //记录当前格子状态:0为未点开、1为已点开、2为双击、3为插旗、4为周围一圈无雷自动翻开
int endindex = 0; //点击到地雷的结束标志
int mines = 0; //记录已排除的地雷数
void SetMine(int n) //布雷
{
srand(time(0));
int k, row, col;
if(n == 1) //初级难度
k = 25;
else if(n == 2) //中级难度
k = 50;
else //高级难度
k = 75;
mines = k;
while(k)
{
row = rand() % len + 1; //+1是为了将地雷分布在除四边以外的区域 显示地图时实际只显示中间部分 不显示四周
col = rand() % len + 1;
if(!mine[row][col])
{
mine[row][col] = 9;
k--;
}
}
}
void round(int mine[][len+2], int x, int y)
{
int k = 0; //地雷数
if(mine[x][y] == 9 && dispMine[x][y] != 3) //点击到地雷
endindex++;
else
{
if(mine[x][y+1] == 9) //计算周围一圈是否有雷
k++;
if(mine[x+1][y+1] == 9)
k++;
if(mine[x+1][y] == 9)
k++;
if(mine[x+1][y-1] == 9)
k++;
if(mine[x][y-1] == 9)
k++;
if(mine[x-1][y-1] == 9)
k++;
if(mine[x-1][y] == 9)
k++;
if(mine[x-1][y+1] == 9)
k++;
mine[x][y] = k; //记录当前位置地雷数
}
}
void open(int mine[][len+2], int x, int y) //翻开
{
if(mine[x][y] == 9) //点击到雷直接返回
return;
if(dispMine[x][y] == 3) //输入坐标位置为插旗的位置
return;
if(mine[x][y] == 0) //无雷区自动翻开
{
dispMine[x][y] = 4; //无雷区标志为4
if(x != 1 && y != 1) //考虑各个特殊位置的坐标
{
round(mine, x-1, y-1);
if(!mine[x-1][y-1] && dispMine[x-1][y-1] != 4) //若无雷自动翻开区域里又有无雷区 继续自动翻开 为了防止死循环
open(mine, x-1, y-1); //要标志已翻开的
else if(mine[x-1][y-1] && !dispMine[x-1][y-1]) //若是周围一周有雷的,则直接显示,标志为1
dispMine[x-1][y-1] = 1;
}
if(x != 1 && y != len)
{
round(mine, x-1, y+1);
if(!mine[x-1][y+1] && dispMine[x-1][y+1] != 4)
open(mine, x-1, y+1);
else if(mine[x-1][y+1] && !dispMine[x-1][y+1])
dispMine[x-1][y+1] = 1;
}
if(x != len && y != 1)
{
round(mine, x+1, y-1);
if(!mine[x+1][y-1] && dispMine[x+1][y-1] != 4)
open(mine, x+1, y-1);
else if(mine[x+1][y-1] && !dispMine[x+1][y-1])
dispMine[x+1][y-1] = 1;
}
if(x != len && y != len)
{
round(mine, x+1, y+1);
if(!mine[x+1][y+1] && dispMine[x+1][y+1] != 4)
open(mine, x+1, y+1);
else if(mine[x+1][y+1] && !dispMine[x+1][y+1])
dispMine[x+1][y+1] = 1;
}
if(x != 1)
{
round(mine, x-1, y);
if(!mine[x-1][y] && dispMine[x-1][y] != 4)
open(mine, x-1, y);
else if(mine[x-1][y] && !dispMine[x-1][y])
dispMine[x-1][y] = 1;
}
if(x != len)
{
round(mine, x+1, y);
if(!mine[x+1][y] && dispMine[x+1][y] != 4)
open(mine, x+1, y);
else if(mine[x+1][y] && !dispMine[x+1][y])
dispMine[x+1][y] = 1;
}
if(y != 1)
{
round(mine, x, y-1);
if(!mine[x][y-1] && dispMine[x][y-1] != 4)
open(mine, x, y-1);
else if(mine[x][y-1] && !dispMine[x][y-1])
dispMine[x][y-1] = 1;
}
if(y != len)
{
round(mine, x, y+1);
if(!mine[x][y+1] && dispMine[x][y+1] != 4)
open(mine, x, y+1);
else if(mine[x][y+1] && !dispMine[x][y+1])
dispMine[x][y+1] = 1;
}
}
if(dispMine[x][y] = 2) //如果双击
{
dispMine[x][y] = 1; //置为已点击防止死循环
int flag = 0; //记录周围一周插旗数
if(dispMine[x-1][y] == 3) //若周围有旗子,flag++
flag++;
if(dispMine[x-1][y+1] == 3)
flag++;
if(dispMine[x][y+1] == 3)
flag++;
if(dispMine[x+1][y+1] == 3)
flag++;
if(dispMine[x+1][y] == 3)
flag++;
if(dispMine[x+1][y-1] == 3)
flag++;
if(dispMine[x][y-1] == 3)
flag++;
if(dispMine[x-1][y-1] == 3)
flag++;
if(mine[x][y] == flag) //双击的当前位置插旗数与该位置地雷数相同时自动翻开周围一圈未点击的位置
{
if(y != len && dispMine[x][y+1] == 0) //考虑各个特殊位置防止越界以及是否为未翻开位置
{
round(mine, x, y+1);
dispMine[x][y+1] = 1;
if(!mine[x][y+1]) //若翻开为无雷区则递归调用
open(mine, x, y+1);
}
if(x != len && y != len && dispMine[x+1][y+1] == 0)
{
round(mine, x+1, y+1);
dispMine[x+1][y+1] = 1;
if(!mine[x+1][y+1])
open(mine, x+1, y+1);
}
if(x != len && dispMine[x+1][y] == 0)
{
round(mine, x+1, y);
dispMine[x+1][y] = 1;
if(!mine[x+1][y])
open(mine, x+1, y);
}
if(x != len && y != 1 && dispMine[x+1][y-1] == 0)
{
round(mine, x+1, y-1);
dispMine[x+1][y-1] = 1;
if(!mine[x+1][y-1])
open(mine, x+1, y-1);
}
if(y != 1 && dispMine[x][y-1] == 0)
{
round(mine, x, y-1);
dispMine[x][y-1] = 1;
if(!mine[x][y-1])
open(mine, x, y-1);
}
if(x != 1 && y != 1 && dispMine[x-1][y-1] == 0)
{
round(mine, x-1, y-1);
dispMine[x-1][y-1] = 1;
if(!mine[x-1][y-1])
open(mine, x-1, y-1);
}
if(x != 1 && dispMine[x-1][y] == 0)
{
round(mine, x-1, y);
dispMine[x-1][y] = 1;
if(!mine[x-1][y])
open(mine, x-1, y);
}
if(x != 1 && y != len && dispMine[x-1][y+1] == 0)
{
round(mine, x-1, y+1);
dispMine[x-1][y+1] = 1;
if(!mine[x-1][y+1])
open(mine, x-1, y+1);
}
}
}
}
void chaqi(int x, int y) //插旗
{
if(dispMine[x][y] == 3) //已经插旗的位置再次插旗视为取消插旗
{
dispMine[x][y] = 0; //置为0表示未点击区域
return;
}
else if(dispMine[x][y]) //若该位置已点开则不改变
return;
dispMine[x][y] = 3; //插旗标志为3
}
void disp(int x, int y) //显示地图
{
cout<<" ";
for(int k = 1; k < len+1; k++)
cout<<setw(2)<<k;
cout<<endl;
if(mine[x][y] == 9 && dispMine[x][y] != 3) //如果点到地雷
{
for(int i = 1; i < len+1; i++)
{
cout<<setw(2)<<i;
for(int j = 1; j < len+1; j++)
{
if(dispMine[i][j] == 3) //插旗的地方显示为■
cout<<"■";
else if(mine[i][j] == 9) //有雷的地方显示为*
cout<<" *";
else if(dispMine[i][j]) //无雷区显示数字
cout<<" "<<mine[i][j];
else //未翻开的地方显示为□
cout<<"□";
}
cout<<endl;
}
return;
}
for(int i = 1; i < len+1; i++) //没有点击到地雷
{
cout<<setw(2)<<i;
for(int j = 1; j < len+1; j++)
{
if(dispMine[i][j] == 3)
cout<<"■";
else if(dispMine[i][j])
cout<<" "<<mine[i][j];
else
cout<<"□";
}
cout<<endl;
}
return;
}
bool win(int mines) //判断胜利条件
{
bool win = false; //默认为没有取得胜利
int noFlag = 0, yesFlag = 0, halfFlag = 0; //noFlag记录未翻开的格子数 yesFlag、halfFlag记录插旗数且该位置有雷 noClip
for(int i = 1; i < len+1; i++)
for(int j = 1; j < len+1; j++)
{
if(dispMine[i][j] == 0 ) //未翻开位置
noFlag++;
if(dispMine[i][j] == 3 && mine[i][j] == 9) //插旗位置正确
{
yesFlag++;
halfFlag++;
}
}
if(noFlag == mines || (yesFlag == mines && !noFlag) || halfFlag == len*len - noFlag) //未翻开的格子数等于地雷数 插旗数等于地雷数
win = true; //插旗与未翻开格子数等于地雷数
return win;
}
void main()
{
int x = 0, y = 0;
cout<<"请选择游戏难度,1.初级 2.中级 3.高级:";
int rank = 0;
while(1)
{
cin>>rank;
if(rank < 1 || rank > 3)
cout<<"输入有误,请重新输入:";
else
{
system("CLS");
break;
}
}
SetMine(rank);
disp(x, y);
while(1)
{
cout<<"1.点击 2.插旗 3.双击"<
cout
int n;
while(1)
{
cin>>n;
cin>>x>>y;
if(n < 1 || n > 3)
{
cout<<"输入有误,请重新输入:";
continue;
}
else if(x < 1 || x > 20 || y < 1 || y > 20)
{
cout<<"输入有误,请重新输入:";
continue;
}
break;
}
if(n == 1 || n == 3)
{
if(n == 3 && dispMine[x][y] == 3)
continue;
round(mine, x, y);
if(dispMine[x][y] < 2)
dispMine[x][y]++;
open(mine, x, y);
}
else if(n == 2)
chaqi(x, y);
system("CLS");
disp(x, y);
if(endindex)
{
cout<<"你输了!"<<endl;
break;
}
if(win(mines))
{
cout<<"你赢了!"<<endl;
break;
}
}
}