linux终端多线程小游戏,【C语言结构体+动态二维数组】Linux终端扫雷小游戏

#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();

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值