自动扫雷的一种最为简易的实现方式,分为两部分:扫雷游戏和自动判断。思想很简单,不需要任何介绍。
emoji: /奸邪一笑hiahiahia
附上源码
C语言,
笔记本键值,
Windows 下编译运行。
/*********************
忘了操作就看KeyScan
**********************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#define Esc 27
#define Tab 9
#define Enter 13
#define Up 72
#define Down 80
enum{col=/*110*/30/**//*10*/,row=/*110*/16/**//*10*/};
int A[col][row][2+2]; //雷板-第零层:雷与数字标识-第一层:可视标识(0&1)
//+2是后来加上的,这是加概率层与概率自检层
int BJV=0;//Border Judge Value: the value for judging whether a block is the border.
void init(void); //初始化三维数组A
void SetValue(double); //在A上布雷
void SetValue_vice(void); //在A上码数字
void PrtPad(void); //显示A
void KeyScan(void); //键值扫描
void OpenBlockAtMost(int,int); //打开所有可打开方块
void SolveProbability(void); //概率逼近
int JudgeNumber_ForAllType(int,int,int);//输入坐标,返回数值(未打开的块&未打开块中一定是雷的个数)
//void OpenSaveBlock(void); //翻开概率为0的方块
void BJfunction(int,int); //判断某方块的边界位置
//void JudgeDeath(void); //在KeyScan中运行,判断是否扫雷失败
//void JudgeVictory(void); //在KeyScan中运行,判断是否扫雷胜利
/*void JudgeDeath(void)
{
int i,j;
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
if(A[i][j][0]==-1)
{
if(A[i][j][1]==1)
{
printf("Boooooom!\n\a");//踩到了雷
goto loop0;//跳出KeyScan的循环
}
}
}
}*/
/*void JudgeVictory(void)
{
int i,j;
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
if(A[i][j][0]!=-1)
{
if(A[i][j][1]==0)
goto loop1;//继续KeyScan的循环
}
}
printf("Congratulations!\n\a");//如果经住了考验,胜利!
}*/
int JudgeNumber_ForAllType(int i,int j,int type)//两种type,type==0:未打开格数。type==1:未打开格数中已确定的雷数
{
int k;//k是九宫格的标号
int x,y; //x&y是九宫格坐标
int bomb_n=0;//bomb_n是九宫格内的未打开格数中的已确定雷数
int unopen_n=0;//未打开格数
BJfunction(i,j);
bomb_n=0;
unopen_n=0;
switch(BJV)
{
case 0://若不在边界
for(k=8;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 1://若在上边界
for(k=8;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 2://若在右上角
for(k=7;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 3://若在右边界
for(k=7;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 4://若在右下角
for(k=4;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 5://若在下边界
for(k=5;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 6://若在左下角
for(k=5;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 7://若在左边界
for(k=8;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
case 8://若在左上角
for(k=8;k>=4;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][1]==2)//判定为雷(小红旗)
bomb_n++;
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//不可视+标记为雷=未打开格数
unopen_n++;
}
}
if(type==0)
return unopen_n;
else if(type==1)
return bomb_n;
else
return 0;
break;
default:
break;
}
return 0;
}
void BJfunction(int x,int y)//判断某方块的边界位置
{
switch(y)
{
case 0://首行
switch(x)
{
case 0://左上
BJV=8;
break;
case (col-1)://右上
BJV=2;
break;
default://上
BJV=1;
break;
}
break;
case (row-1)://末行
switch(x)
{
case 0://左下
BJV=6;
break;
case (col-1)://右下
BJV=4;
break;
default://下
BJV=5;
break;
}
break;
default://中间行
switch(x)
{
case 0://左
BJV=7;
break;
case (col-1)://右
BJV=3;
break;
default://中
BJV=0;
break;
}
break;
}
}
void AxisPrt(void)
{
int i=0;
printf(" ");
for(;i<=col-1;i++)
{
if(i<=9)
printf("%d ",i);
else if(i<=99)
printf("%d",i);
else
printf("%d\b",i);
}
printf("\n\n");
}
int main(void)
{
double density=3.85; // 格数(面积)/ 总雷数
//3.85是高级难度的雷密度
while(1)
{
init(); //初始化雷板
puts("Density of bomb");
scanf("%lf",&density); //雷密度输入
system("cls"); // //clearscreen
printf("%f个格点中有一个雷\n",density);
SetValue(density); //铺值函数
PrtPad(); //显示函数
KeyScan();
}
}
void init(void)
{
int i,j;
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
A[i][j][0]=0;//数字板归零
A[i][j][1]=0;//全部不可视
A[i][j][2]=100;//概率层 (有雷概率为1)
A[i][j][3]=0;//概率自检层(无雷:为保证第一次判断的畅通性)
}
}
void SetValue_vice(void)
{
int i,j,k;//k是九宫格的标号
int x,y; //x&y是九宫格坐标
int bomb_n=0;//bomb_n是九宫格内的雷数
for(j=row-1;j>=0;j--) //第j行
{
for(i=col-1;i>=0;i--) //第i列
{
if(A[i][j][0]==-1);//对有雷格点不操作
else
{
BJfunction(i,j);
switch(BJV)
{
case 0://若不在边界
for(k=8;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 1://若在上边界
for(k=8;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 2://若在右上角
for(k=7;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 3://若在右边界
for(k=7;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 4://若在右下角
for(k=4;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 5://若在下边界
for(k=5;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 6://若在左下角
for(k=5;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 7://若在左边界
for(k=8;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
case 8://若在左上角
for(k=8;k>=4;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(A[i+x][j+y][0]==-1)
bomb_n++;
}
}
A[i][j][0]=bomb_n;
bomb_n=0;
break;
default:
break;
}
}
}
}
}
void SetValue(double density)
{
int number; //30X16 上的雷数
int n,x,y; //n是雷位置的一维坐标,x&y是雷位置的二维坐标
number=(int)(row*col/density);
srand((unsigned)time(NULL)); /*随机种子*/
for(;number>0;number--) //布雷核心算法
{
n=rand()%((row*col-1)-0+1)+0; /*n为0~(row*col-1)之间的随机数*/
x=n%col; //这里对x&y的计算处理显示出了数组0打头的优势
y=n/col;
A[x+1][y+1][0]=-1; //-1表示该格点有雷 ,+1表示不在边界布雷
}
SetValue_vice(); //码数字
}
void PrtPad(void)
{
int i,j;
AxisPrt();
for(j=0;j<=row-1;j++) //第j行
{
if(j<=9)
printf("%d ",j);
else if(j<=99)
printf("%d ",j);
else
printf("%d ",j);
for(i=0;i<=col-1;i++) //第i列
{
if(A[i][j][1]==1) //如果格点可视
{
if(A[i][j][0]==-1) //如果有雷
printf("* ");
else //无雷
printf("%d ",A[i][j][0]);//打印数字
}
else if(A[i][j][1]==0) //若格点不可视
printf("# ");
else
printf("@ "); //若格点标雷
}
puts(""); //换行
}
/*
for(j=0;j<=row-1;j++) //第j行
{
for(i=0;i<=col-1;i++) //第i列
{
printf("%d ",A[i][j][2]);
}
puts("");
}
*/ //打印概率板
}
//调用自己时,存在循环调用,来回地推!可行解决方案:计时,当时间超过0.1秒后goto跳出
/*void OpenBlockAtMost(void)//重复扫描式算法 (扫他一百次)
{
int i,j,k,l;//k是九宫格的标号
int x,y; //x&y是九宫格坐标
for(l=100;l>0;l--)
{
for(j=0;j<=16+1;j++) //第j行
{
for(i=0;i<=30+1;i++) //第i列
{
if(A[i][j][1]) //如果格点可视
{
if(A[i][j][0]==0) //如果为零
{
for(k=8;k>=0;k--) //将k对应到x&y,翻开九宫格
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;//翻!
}
}
}
}
}
}
}
*/
void OpenBlockAtMost(int i,int j)//递归式发散扩张算法 (由点(i,j)发散)
{
int k,x,y;
int B[3][3];
A[i][j][1]=1;
BJfunction(i,j);//Judge the position of (i,j)
if(A[i][j][0]==0)//若(i,j)为零
{
switch(BJV)
{
case 0://若不在边界
for(k=8;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
for(k=8;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 1://若在上边界
for(k=8;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
for(k=8;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 2://若在右上角
for(k=7;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=7;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 3://若在右边界
for(k=7;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=7;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 4://若在右下角
for(k=4;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=4;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 5://若在下边界
for(k=5;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
for(k=5;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
break;
case 6://若在左下角
for(k=5;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=5;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 7://若在左边界
for(k=8;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=8;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
case 8://若在左上角
for(k=8;k>=4;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
B[x+1][y+1]=A[i+x][j+y][1];//B用于储存(i,j)九宫格的可视值
}
}
for(k=8;k>=4;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
A[i+x][j+y][1]=1;
if(A[i+x][j+y][0]==0&&B[x+1][y+1]==0)
OpenBlockAtMost(i+x,j+y);//调用自己
}
}
break;
default:
break;
}
}
//PrtPad();//test
//Sleep(20);//test
//puts("");//test
}
/*void OpenSaveBlock(void)//打开所有P=0的方块,并调用OpenBlockAtMost(int,int)
{
int i,j;
for(j=0;j<=row-1;j++) //第j行
{
for(i=0;i<=col-1;i++) //第i列
{
if(A[i][j][2]==0)
A[i][j][1]=1;
OpenBlockAtMost(i,j);
}
}
}*/
void SolveProbability(void)
{
int i,j,k,x,y;
int unopen_block,unopen_mine,mode=0;
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
if(A[i][j][1]==1)//若格点可视
{
if(A[i][j][0]==-1)//若可视格点为雷
printf("Boooooom!\n\a");//踩到了雷
else
{
unopen_block=JudgeNumber_ForAllType(i,j,0);
unopen_mine=JudgeNumber_ForAllType(i,j,1);
if(unopen_block==0)
mode=-1;//do nothing
if(unopen_block!=0)
mode=0;//give probability
if((A[i][j][0]==unopen_block)&&(unopen_block!=0))
mode=1;//all bombs
if((A[i][j][0]==unopen_mine)&&(unopen_block!=0))
mode=2;//all save
//printf("%d ",mode); examine
if(mode==-1);//do nothing
else
{
BJfunction(i,j);
switch(BJV)
{
case 0://若不在边界
for(k=8;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 1://若在上边界
for(k=8;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==4);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 2://若在右上角
for(k=7;k>=3;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 3://若在右边界
for(k=7;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==5);
else if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 4://若在右下角
for(k=4;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==2);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 5://若在下边界
for(k=5;k>=0;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
break;
case 6://若在左下角
for(k=5;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 7://若在左边界
for(k=8;k>=1;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else if(k==3);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
case 8://若在左上角
for(k=8;k>=4;k--) //将k对应到x&y,并翻开九宫格(若九宫格中有零,继续)
{
if(k==6);
else
{
x=k%3-1;
y=k/3-1;//-1的原因在于:以九宫格的中心为原点
if(mode==1)//all bombs
{
if((A[i+x][j+y][1]==0)||(A[i+x][j+y][1]==2))//invisible OR flag-on
{
A[i+x][j+y][1]=2;//插上小红旗
A[i+x][j+y][2]=100;//概率层(有雷概率):100%
}
}
else if(mode==2)//all save
{
if(A[i+x][j+y][1]==0)//invisible
{
OpenBlockAtMost(i+x,j+y);//open it all
A[i+x][j+y][2]=0;//概率层(有雷概率):0%
}
}
else if(mode==0)//give probability
{
if(A[i+x][j+y][1]==0)//invisible
A[i+x][j+y][2]=(int)((A[i+x][j+y][0]-unopen_mine)*1.0/(unopen_block-unopen_mine)*100.0);//概率层(有雷概率):%
}
else;//do nothing
}
}
break;
default:
break;
}//switch
}//else mode=0or1or2
}//else (there is no mine)
}//if visibal
}//for
}//function
void KeyScan(void)
{
int key;
int a=0,b=0; //储存“光标”坐标
int k=0; //mode value
int i,j;
while(1)
{
key=getch();
key=getch();
switch(key)
{
case Up:
if(k==0)
{
printf("up\n");
scanf("%d",&a);
scanf("%d",&b);//相当于鼠标置于坐标(a,b)
OpenBlockAtMost(a,b);//左键点击(a,b)
PrtPad();
}
break;
case Down:
if(k==0)
{
printf("down\n");
scanf("%d",&a);
scanf("%d",&b);//相当于鼠标置于坐标(a,b)
A[a][b][1]=2;//右键点击(a,b)
PrtPad();
}
break;
case Esc:
goto loop0;//跳出循环
case Tab:
if(k==0)
{
k++;
printf("\nSwitch to solve mode!\n");
}
else
{
k--;
printf("\nSwitch to normal mode!\n");
}
break;
case Enter:
if(k==1)
{
SolveProbability();
PrtPad();
puts("");
//OpenSaveBlock();//I won't use it anyway.
}
break;
default:
break;
}
/******************
以下循环判断失败
******************/
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
if(A[i][j][0]==-1)
{
if(A[i][j][1]==1)
{
printf("Boooooom!\n\a");//踩到了雷
goto loop0;//跳出KeyScan的循环
}
}
}
/******************
以下循环判断胜利
******************/
for(j=row-1;j>=0;j--)
for(i=col-1;i>=0;i--)
{
if(A[i][j][0]!=-1)
{
if(A[i][j][1]==0)
goto loop1;//继续KeyScan的循环
}
}
printf("Congratulations!\n\a");//如果经住了考验,胜利!
goto loop0;//到循环外
loop1:; //跳过上两行的TP出口
}
loop0:;//out of the loop "while(1){}"
}