进阶版只需要再简单版的基础上增加一个能实现周围坐标展开的功能,并且改变判断是否胜利的条件。
简单版在之前的发布的文章中可看到
C语言实现简易扫雷小游戏_标仔22的博客-CSDN博客
如何能够实现坐标展开呢可以利用递归,首先先判断我们输入的坐标周围的八个坐标,如果周围八个全都不是雷,则先展开这八个坐标。展开这八个坐标后,再依次对这八个坐标每个坐标的周围八个坐标进行判断,依次类推进行判断,直至每个判断的坐标周围全部有雷才停下。
void spread(char arr[hangs][lies], char arr2[hangs][lies], int x, int y)//坐标周围展开
{
int near_x = 0, near_y = 0;
int count = 0;
if (x >= 1 && x <= hang && y >= 1 && y <= lie)//判断输入的坐标是否有效
{
//循环该坐标周围的八个坐标
for (near_x = -1; near_x <= 1; near_x++)
{
for (near_y = -1; near_y <= 1; near_y++)
{
if (arr2[x + near_x][y + near_y] == '#')
{
count = jud(arr2, x + near_x, y + near_y);
if (count == 0)//如果该坐标周围没有雷则全部展开
{
if (arr[x + near_x][y + near_y] == '*')
{
arr[x + near_x][y + near_y] = ' ';
//利用递归第一次扫的坐标后再判断周围八个坐标每个坐标的周围八个坐标,
//直至判断的坐标周围有雷再停下
spread(arr, arr2, x + near_x, y + near_y);
}
}
else
{
arr[x + near_x][y + near_y] = count + '0';
}
}
}
}
}
}
在简单版中,我们一步只能判断一个坐标,因此胜利的条件就是我们扫雷步数等于全部坐标数减去雷的总数即可。但由于现在我们实现了展开坐标功能便不能再用该方法了,可以想一下,如果我们已经把所有的非雷坐标全部扫完,那剩下的未扫坐标就是雷的坐标,因此可以得出当未扫的坐标总数等于雷的总数时,那就已经胜利了。
int ifwin(char arr[hangs][lies], int h, int l,int p)//判断赢的条件
{
int i, j;
int count = 0;
for (i = 1; i <= h; i++)
{
for (j = 1; j <= l; j++)
{
if (arr[i][j] == '*')
count++;
}
}
//如果剩余未扫的坐标和雷的总数相等,那么玩家就获胜
if (count == p)
return 1;
else
return 0;
}
以上就是改进的步骤,下面是全部代码
game.h#pragma once #includegame.c#include #include #define hang 10 #define lie 10 #define hangs hang+2 #define lies lie+2 void chushi(char arr[hangs][lies], int h, int l, char set);//初始化 void print(char arr[hangs][lies], int h, int l);//打印棋盘 void computer(char arr[hangs][lies], int p);//电脑随机生成雷 int jud(char arr[hangs][lies], int x, int y);//判断坐标周围雷的总数 void play(char arr[hangs][lies], char arr2[hangs][lies], int h, int l, int p);//玩家操作 int ifwin(char arr[hangs][lies], int h, int l, int p);//判断赢的条件 void spread(char arr[hangs][lies], char arr2[hangs][lies], int x, int y);//坐标周围展开
#include "game.h"
void chushi(char arr[hangs][lies], int h, int l, char set)//初始化棋盘
{
int x, y;
for (x = 0; x < h; x++)
{
for (y = 0; y < l; y++)
{
arr[x][y] = set;
}
}
}
void print(char arr[hangs][lies], int h, int l)//打印棋盘
{
int x = 0, y = 0;
for (y = 1; y < l - 1; y++)
{
printf(" %d ", y);
}
printf("n");
printf("|");
for (y = 1; y < l - 1; y++)
{
printf("---|");
}
printf("n");
for (x = 1; x < h - 1; x++)
{
printf("|");
for (y = 1; y < l - 1; y++)
{
printf(" %c |", arr[x][y]);
}
printf("%d", x);
printf("n");
printf("|");
for (y = 1; y < l - 1; y++)
{
printf("---|");
}
printf("n");
}
}
void computer(char arr[hangs][lies], int p)//电脑布置雷
{
do
{
//电脑随机生成雷的位置的下标
int x = rand() % hang + 1;
int y = rand() % lie + 1;
if (arr[x][y] == '#')
{
arr[x][y] = '1';
p--;
}
} while (p);
}
int jud(char arr[hangs][lies], int x, int y)//判断扫雷的坐标附近八个坐标一共有多少个雷
{
int i = 0;
if (arr[x - 1][y - 1] == '1')
i++;
if (arr[x - 1][y] == '1')
i++;
if (arr[x - 1][y + 1] == '1')
i++;
if (arr[x][y - 1] == '1')
i++;
if (arr[x][y + 1] == '1')
i++;
if (arr[x + 1][y - 1] == '1')
i++;
if (arr[x + 1][y] == '1')
i++;
if (arr[x + 1][y + 1] == '1')
i++;
return i;
}
void spread(char arr[hangs][lies], char arr2[hangs][lies], int x, int y)//坐标周围展开
{
int near_x = 0, near_y = 0;
int count = 0;
if (x >= 1 && x <= hang && y >= 1 && y <= lie)//判断输入的坐标是否有效
{
//循环该坐标周围的八个坐标
for (near_x = -1; near_x <= 1; near_x++)
{
for (near_y = -1; near_y <= 1; near_y++)
{
if (arr2[x + near_x][y + near_y] == '#')
{
count = jud(arr2, x + near_x, y + near_y);
if (count == 0)//如果该坐标周围没有雷则全部展开
{
if (arr[x + near_x][y + near_y] == '*')
{
arr[x + near_x][y + near_y] = ' ';
//利用递归第一次扫的坐标后再判断周围八个坐标每个坐标的周围八个坐标,
//直至判断的坐标周围有雷再停下
spread(arr, arr2, x + near_x, y + near_y);
}
}
else
{
arr[x + near_x][y + near_y] = count + '0';
}
}
}
}
}
}
int ifwin(char arr[hangs][lies], int h, int l,int p)//判断赢的条件
{
int i, j;
int count = 0;
for (i = 1; i <= h; i++)
{
for (j = 1; j <= l; j++)
{
if (arr[i][j] == '*')
count++;
}
}
//如果剩余未扫的坐标和雷的总数相等,那么玩家就获胜
if (count == p)
return 1;
else
return 0;
}
void play(char arr[hangs][lies], char arr2[hangs][lies], int h, int l,int p)//玩家操作
{
int x = 0, y = 0;
int a;
while (ifwin(arr, hang, lie,p) == 0)
{
printf("请输入你要扫的坐标(x y):");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= h && y >= 1 && y <= l)//判断输入的坐标是否有效
{
//如果该坐标上存放雷的棋盘为1,则踩到雷
if (arr2[x][y] == '1')
{
printf("踩到雷了n");
print(arr2, hangs, lies);
}
//如果该坐标上操作的棋盘还未扫过,则记录并打印附近雷的总数
else
{
a = jud(arr2, x, y);
if (a == 0)
{
arr[x][y] = ' ';
spread(arr, arr2, x, y);
print(arr, hangs, lies);
}
else
{
arr[x][y] = a + '0';
print(arr, hangs, lies);
}
}
}
//判断输入的坐标是否有效
else
printf("输入坐标有误n");
}
if (ifwin(arr, hang, lie,p) == 1)
{
printf("恭喜你,赢了n");
}
}
main.c
#include "game.h"
void meu()
{
printf("*****************************n");
printf("***1、玩游戏 0、退出游戏***n");
printf("*****************************n");
}
void game()
{
int p;
printf("请输入雷的总数:");
scanf("%d", &p);
//创建数组
char arr1[hangs][lies] = { 0 };//操作棋盘
char arr2[hangs][lies] = { 0 };//存放雷的棋盘
//初始化数组
chushi(arr1, hangs, lies, '*');
chushi(arr2, hangs, lies, '#');
//打印棋盘
print(arr1, hangs, lies);
//电脑生成随机雷
computer(arr2, p);
//玩家操作
play(arr1, arr2, hang, lie, p);
}
int main()
{
int i = 0;
srand((unsigned)time(NULL));//设置随机种子
do
{
meu();
printf("请输入你的选择:");
scanf("%d", &i);
switch (i)
{
case 0:
printf("退出成功n");
break;
case 1:
game();
break;
default:
printf("输入错误n");
break;
}
} while (i);
return 0;
}
代码效果



