扫雷规则
游戏开始时,玩家会看到一个由 * 组成的神秘矩阵,每个 * 中可能包含数字或一个地雷。
数字表示该方格周围8个方格中隐藏的地雷数量。例如,一个数字为1的方格表示周围8个方格中有一个地雷。
玩家可以通过键盘输入坐标来翻开某一个 * ,如果 * 是地雷则游戏结束,如果不是地雷则会该位置显示周围8个坐标有多少个地雷。
游戏的目标是在不踩到地雷的情况下,找出不是雷的地方。
布置菜单
创建一个菜单来展示进行游戏和退出游戏的功能。
void menu()
{
printf("\t 菜单\n");
printf("\t0:退出游戏\n");
printf("\t1:开始游戏\n");
}
创建菜单之后呢,我用了一个do while循环同时加入了switch语句来执行菜单。
我们使用game函数来实现扫雷的每个功能
game();
do
{
menu();//菜单
printf("请输入数字:");
scanf("%d", &x);
switch (x)
{
case 1:
printf(" 扫雷游戏开始\n");
game();
break;
case 0:
printf(" 退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (x);
实现扫雷
这次我们创立一个9*9棋盘来放置10个雷,当然了,为了之后方便更改雷的数量或者是棋盘的大小,我们可以用define来定义雷的数量和棋盘的长度,宽度。
#define COUNT 10//雷的数量
#define LINE 9//行的数量
#define LINES LINE+2//拓展后的行数量
#define FORCE 9//列的数量
#define FORCES FORCE+2//拓展后的列数量
而为什么要拓展呢?
假设我们排查(2,5)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数是1
假设我们排查(8,6)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数时,最下⾯的三个坐标就会越界,为了防⽌越界,我们在设计的时候,给数组扩⼤⼀圈,雷还是布置在中间的9 * 9的坐标上,周围⼀圈不去布置雷就⾏,这样就解决了越界的问题。所以我们将存放数据的数组创建成11*11是⽐较合适。
创建九 * 九棋盘
首先呢,我们为了方便我们创建两个棋盘,一个棋盘是电脑自己用来布置雷的另一个棋盘是打印出来给我们看的。
而这个棋盘呢我们用二维数组来代替,也就是创建两个二维数组。
两个二维数组我们一个用1和0当作元素,另外一个用 * 来当做元素,其中0和1构成的棋盘中0表示不是雷,1表示是雷,而 * 构成的棋盘呢,是打印出来给我们看的。
char mine[LINES][FORCES];
char show[LINES][FORCES];
InitBoart(mine, LINES, FORCES, '0');//用于初始化数组
InitBoart(show, LINES, FORCES, '*');//用于初始化数组
InitBoart函数是用来初始化数组的,为了使用一个InitBoart函数就能初始化两个数组,我们将1和0当作字符来处理。
函数实现
void InitBoart(char camp[LINES][FORCES], int lines, int forces, char q)
{
for (int x = 0;x < lines;x++)
for (int y = 0;y < forces;y++)
camp[x][y] = q;
}
打印九 * 九棋盘
而打印的棋盘呢,我们只需要打印由 * 构成的二维数组就可以了。
而我们使用show函数来打印棋盘
Show(show, LINE, FORCE);//用于打印数组
函数实现
void Show(char camp[LINES][FORCES], int line, int force)
{
for (int z = 0;z < line + 1;z++)
printf("%d ", z);
printf("\n");
for (int x = 1;x <= line;x++)
{
printf("%d ", x);
for (int y = 1;y <= force;y++)
{
printf("%c ", camp[x][y]);
}
printf("\n");
}
}
放置雷
为了保证雷放置的随机性,我们就要借助C语言中的time函数和rand函数,而其中要引用两个头文件。
#include <stdlib.h>//--->rand
#include <time.h>//--->time
而调用rand函数我们就需要通过srand函数.而这个调用呢,是放在main函数里面的。
int main()
{
int x;
srand((unsigned int)time(NULL));
do
{
menu();//菜单
printf("请输入数字:");
scanf("%d", &x);
switch (x)
{
case 1:
printf(" 扫雷游戏开始\n");
game();
break;
case 0:
printf(" 退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (x);
}
而这就是main函数的整体样子。
rand的函数呢有一个特点。
rand() % 100,余数的范围是0~99
rand()%100+1,余数是1~100
rand() % 9,余数的范围是0~8
哦我们为了满足雷的横坐标和纵坐标的范围都是在1到9我们就要使用
int x = rand() % line + 1;
int y = rand() % force + 1;
接下来我们通过Putmine函数来实现布置雷。我们是在由0和1构成的二维数组里面布置雷。
Putmine(mine, LINE, FORCE);//用于放置雷
函数实现
void Putmine(char camp[LINES][FORCES], int line, int force)
{
int count = COUNT;
while (count)
{
int x = rand() % line + 1;
int y = rand() % force + 1;
if (camp[x][y] == '0')//这里是用来判断该地点是不是已经放置了雷
{
camp[x][y] = '1';
count--;
}
}
}
该if语句是用来这里是用来判断该地点是不是已经放置了雷,如果没有放置雷,则放雷,如果放了则进行下一个while循环直到10个雷完全放进去。
排查雷
我们先输入一个坐标,通过判断mine函数里面的该坐标是不是1,从而使show函数来发生变化。如果是1直接游戏结束,如果是0的话,我们就把show函数的该坐标改为数字,该数字表示周围的八个坐标里有多少雷。
如果该坐标内为1的话,游戏结束的同时将地雷的分布图显示出来。
Show(mine, LINE, FORCE);
如果输入的该坐标内为0的话,那么就统计该坐标周围有多少个雷,我们就要借助satistic函数来实现。
satistic(mine, x, y);
函数实现
int satistic(char mine[LINES][FORCES], int x, int y)//计算该坐标周围的雷的数量并返回
{
int sz = mine[x][y + 1] + mine[x - 1][y + 1] + mine[x + 1][y + 1]
+ mine[x + 1][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y - 1]
+ mine[x + 1][y] + mine[x - 1][y] - 8 * '0';
return sz;
}
其中的ASCll码值减法呢,有一个机制,字符1减字符0它们的ASCII码值相差1。
所以说,周围如果有6个雷,那么就会返回6个字符1减去8个字符0所产生的ASCll码值差,结果是6也恰巧等于雷的数量。
而我们使用Findmine函数来排查雷。
Findmine(mine, show, LINE, FORCE);//用于排查雷
函数实现
void Findmine(char mine[LINES][FORCES], char show[LINES][FORCES], int line, int force)
{
int x, y;
int number = 0;
while (number <= LINE * FORCE - COUNT)
{
printf("请输入你选择的点的坐标:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= LINE && y > 0 && y <= FORCE)
{
if (mine[x][y] == '1')
{
printf("Boom 你踩到雷了 游戏结束\n");
printf("这是地雷分布图 1(地雷)0(无地雷)\n");
Show(mine, LINE, FORCE);
break;
}
else
{
int sz = satistic(mine, x, y);
show[x][y] = sz + '0';
Show(show, LINE, FORCE);
number++;
}
}
else
printf("输入的坐标不符合规范,请重新输入\n");
}
if (number == line * force - COUNT)
printf("太棒了,排雷成功\n");
}
全部代码
#include<stdio.h>
#include <stdlib.h>
#include <time.h>
#define COUNT 10//雷的数量
#define LINE 9//行数量
#define LINES LINE+2//拓展后的行数量
#define FORCE 9//列数量
#define FORCES FORCE+2//拓展后的列数量
void game();
void InitBoart(char camp[LINES][FORCES], int lines, int forces, char q);
void Show(char camp[LINES][FORCES], int line, int force);
void Putmine(char camp[LINES][FORCES], int line, int force);
void Findmine(char mine[LINES][FORCES], char show[LINES][FORCES], int line, int force);
void InitBoart(char camp[LINES][FORCES], int lines, int forces, char q)
{
for (int x = 0;x < lines;x++)
for (int y = 0;y < forces;y++)
camp[x][y] = q;
}
void Show(char camp[LINES][FORCES], int line, int force)
{
for (int z = 0;z < line + 1;z++)
printf("%d ", z);
printf("\n");
for (int x = 1;x <= line;x++)
{
printf("%d ", x);
for (int y = 1;y <= force;y++)
{
printf("%c ", camp[x][y]);
}
printf("\n");
}
}
void Putmine(char camp[LINES][FORCES], int line, int force)
{
int count = COUNT;
while (count)
{
int x = rand() % line + 1;
int y = rand() % force + 1;
if (camp[x][y] == '0')
{
camp[x][y] = '1';
count--;
}
}
}
int satistic(char mine[LINES][FORCES], int x, int y)//计算该坐标周围的雷的数量并返回
{
int sz = mine[x][y + 1] + mine[x - 1][y + 1] + mine[x + 1][y + 1]
+ mine[x + 1][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y - 1]
+ mine[x + 1][y] + mine[x - 1][y] - 8 * '0';
return sz;
}
void Findmine(char mine[LINES][FORCES], char show[LINES][FORCES], int line, int force)
{
int x, y;
int number = 0;
while (number <= LINE * FORCE - COUNT)
{
printf("请输入你选择的点的坐标:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= LINE && y > 0 && y <= FORCE)
{
if (mine[x][y] == '1')
{
printf("Boom 你踩到雷了 游戏结束\n");
printf("这是地雷分布图 1(地雷)0(无地雷)\n");
Show(mine, LINE, FORCE);
break;
}
else
{
int sz = satistic(mine, x, y);
show[x][y] = sz + '0';
Show(show, LINE, FORCE);
number++;
}
}
else
printf("输入的坐标不符合规范,请重新输入\n");
}
if (number == line * force - COUNT)
printf("太棒了,排雷成功\n");
}
void menu()
{
printf("\t 菜单\n");
printf("\t0:退出游戏\n");
printf("\t1:开始游戏\n");
}
void game()
{
char mine[LINES][FORCES];
char show[LINES][FORCES];
InitBoart(mine, LINES, FORCES, '0');//用于初始化数组
InitBoart(show, LINES, FORCES, '*');//用于初始化
Show(show, LINE, FORCE);//用于打印数组
Putmine(mine, LINE, FORCE);//用于放置雷
//Show(mine, LINE, FORCE);
Findmine(mine, show, LINE, FORCE);//用于排查雷
}
int main()
{
int x;
srand((unsigned int)time(NULL));
do
{
menu();//菜单
printf("请输入数字:");
scanf("%d", &x);
switch (x)
{
case 1:
printf(" 扫雷游戏开始\n");
game();
break;
case 0:
printf(" 退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
}
} while (x);
}
本次扫雷学习告一段落,扫雷详解+完整代码,反复阅读,坚持打码,相信你在不久的将来就会拿下扫雷,以扩展更高级代码。期待下次作品与大家见面!!!