#include
#include
#include
#include
#include
#define M_Symbol 'F' //打印雷的符号
typedef struct node{
char chess; //存放棋盘节点的值
char mine; //存放雷盘节点的值
}Node;
int M,N; //M:用户设置雷的个数,N:用户输入棋盘的大小(N*N)
Node** panel;
void print_hline(),set_size(),title();
void chess_panel(),update_chess(),mine_panel();
void show_mine(),check(),zero_open(),play_game();
int main()
{
set_size();
title();
chess_panel();
mine_panel();
play_game();
return 0;
}
//print horizontal line
void print_hline()
{
int i;
for(i=0;i<3*(N-1)+1;i++)
printf("-");
printf("\n");
}
//set size of panel
void set_size()
{
print_hline();
int i;
for(i=0;i
printf("Welcome to minesweeper\n");
print_hline();
input_size:
printf("棋盘大小_雷的个数:");
scanf("%d %d",&N,&M);
if(N*N
{
printf("Error:the mines was greater then chess,pls re-input\n");
goto input_size;
}
system("clear");
}
//set title of panel
void title()
{
int i;
print_hline();
for(i=0;i
printf("Welcome to minesweeper\n");
for(i=0;i
printf("Panel:%d*%d Mine:%d\n",N,N,M);
print_hline();
}
//chess panel genarate
void chess_panel()
{
int i,j;
panel=(Node**)malloc(N*sizeof(Node*));
for(i=0;i
{
panel[i]=(Node*)malloc(N*sizeof(Node));
for(j=0;j
{
panel[i][j].chess='*';
printf("%-3c",panel[i][j].chess);
if(j==N-1) printf("\n");
}
}
print_hline();
}
//update chess panel
void update_chess()
{
int i,j;
title();
for(i=0;i
{
for(j=0;j
{
printf("%-3c",panel[i][j].chess);
if(j==N-1) printf("\n");
}
}
print_hline();
}
//mine panel genarate
void mine_panel()
{
/*-------创建一个动态数组存放M个雷的下标-------*/
int* a=(int*)malloc(M*sizeof(int));
if(!a)
{
printf("内存分配失败\n");
return;
}
/*-------在0~N*N内产生M个不同的下标-------*/
int i=0,j,k;
srand(time(NULL));
a[i++]=rand()%(N*N);
while(1)
{
k=rand()%(N*N);
for(j=0;j
{
if(k==a[j]) break;
if(j==i-1)
{ a[i++]=k;break;}
}
if(i==M) break;
}
/*创建一个临时(N+2)*(N+2)二维字符数组用来辅助计算每个点的周围雷的个数*/
char** temp;
temp=(char**)malloc((N+2)*sizeof(char*));
for(i=0;i
{
temp[i]=(char*)malloc((N+2)*sizeof(char));
for(j=0;j
{
temp[i][j]=0;
for(k=0;k
{
if(a[k]==(i-1)*N+j-1 && i>=1 && j>=1 && i<=N && j<=N)
temp[i][j]=1;
}
}
}
/*---用临时二维数组来辅助计算每个点的周围雷的个数---*/
char tmp;
for(i=0;i
{
for(j=0;j
{
if(i>=1 && i<=N && j>=1 && j<=N)
{
tmp=temp[i-1][j-1]+
temp[i-1][j]+
temp[i-1][j+1]+
temp[i][j-1]+
temp[i][j+1]+
temp[i+1][j-1]+
temp[i+1][j]+
temp[i+1][j+1];
panel[i-1][j-1].mine=tmp+48;
}
}
}
free(temp);
/*-----------将雷盘上有雷的地方置为M_Symbol-----------*/
for(i=0;i
{
for(j=0;j
{
for(k=0;k
{
if(a[k]==i*N+j)
panel[i][j].mine=M_Symbol;
}
if(panel[i][j].mine=='0')
panel[i][j].mine='-';
}
}
free(a);
}
void show_mine()
{
title();
int i,j;
for(i=0;i
{
for(j=0;j
{
printf("%-3c",panel[i][j].mine);
if(j==N-1) printf("\n");
}
}
print_hline();
}
void check()
{
int i,j;
for(i=0;i
{
for(j=0;j
{
if(panel[i][j].mine!=panel[i][j].chess)
return;
}
}
printf("You Win !\n");
exit(1);
}
void zero_open(int x,int y)
{
if(x<0||x>=N||y<0||y>=N) //如果坐标值越界则返回
return;
if(panel[x][y].mine=='-' && panel[x][y].chess=='*') //如果雷盘上该点雷的个数为0并且该点用户还没有选择过,则其周围8个点肯定无雷,故用递归将其周围8个点都显示出来
{
panel[x][y].chess=panel[x][y].mine;
zero_open(x-1,y-1);
zero_open(x-1,y);
zero_open(x-1,y+1);
zero_open(x,y-1);
zero_open(x,y+1);
zero_open(x+1,y-1);
zero_open(x+1,y);
zero_open(x+1,y+1);
}
else
panel[x][y].chess=panel[x][y].mine; //如果雷盘上该点雷的个数不为零则只将其显示出来
}
void play_game()
{
int x,y,flag; //x:存放用户输入的x坐标 y:存放用户输入的y坐标 flag:存放用户输入的选择,0为该点非雷,1为该点是雷
char mine,chess;
while(1)
{
printf("[(x,y)_flag]>");
scanf("%d,%d %d",&x,&y,&flag);
if(1>x || x>N || 1>y || y>N || 0>flag || flag>1) //若用户输入的坐标值超出棋盘范围,则给出提示并重新输入
{
printf("超出范围,请重新输入\n");
sleep(1);
continue;
}
system("clear");
x=x-1;y=y-1; //将用户习惯的坐标转换为与二维数组对应的坐标
mine=panel[x][y].mine;
chess=panel[x][y].chess;
if(mine!='-' && mine!=M_Symbol && chess=='*' && flag==0) //根据输入坐标对应的雷盘值来决策玩家是否胜出
{
panel[x][y].chess=mine;
update_chess();
}
else if(mine==M_Symbol && chess=='*' && flag==1)
{
M--;
panel[x][y].chess=mine;
update_chess();
}
else if(mine==M_Symbol && chess=='*' && flag==0)
{
show_mine();
printf("Game Over\n");
exit(-1);
}
else if(mine=='-' && chess=='*' && flag==0)
{
zero_open(x,y);
update_chess();
}
else if(mine!=M_Symbol && chess==M_Symbol && flag==0)
{
M++;
panel[x][y].chess=mine;
update_chess();
}
else if(mine!=M_Symbol && chess!=M_Symbol && chess!='*')
{
update_chess();
printf("Error:Already open\n");
continue;
}
else if(mine!=M_Symbol && chess=='*' && flag==1)
{
M--;
panel[x][y].chess=M_Symbol;
update_chess();
}
else
{
show_mine();
printf("Game Over\n");
exit(-1);
}
check();
}
}