一、前提准备
1.首先要创建三个文件方便书写代码
add.h test.c add.c
这样逻辑清晰一点
2.我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的四周8个坐标雷总个数存放在show数组,并且打印show数组的信息给后期 排查参考。 同时为了保持神秘,show数组开始时初始化为字符 '*',
为了保持两个数组的类型⼀致,可以使⽤同⼀ 套函数处理,mine数组最开始也初始化为字符'0',布置雷改成'1'。
3.我们要想实现9*9的扫雷棋盘,注意当我们排查边界上的坐标时,要统计它四周一圈8个坐标中的雷总个数时会越界了这时我们应该多加上下左右应该多加一行,列,变成11*11的数组,应一起初始化为‘0’,当然雷只能布置在9*9的数组中
二、add.h 函数声明
注意: 1.这里用了#define 预处理命令来定义行,列数,是为了以后修改行、列数方便
#define ROW 9 //行
#define COL 9 //列
#define ROWS ROW+2 //多加2
#define COLS COL+2 //多加2
#define NUMBER 10 //雷的总数
2.#include<stdlib.h> 为 srand 和rand函数 的头文件
3.#include<time.h> 为 time函数 头文件
函数的声明
1.Intial 函数 用来初始化化棋盘
void Intial(char a[ROWS][COLS], char ch);
2. Print 函数 用来打印棋盘
void Print(char a[ROWS][COLS]);
3.Arrangemine 函数 用来布置雷在
void Arrangemine(char a[ROWS][COLS]);
4.Check 函数 用来排查棋盘
char Check(char a[ROWS][COLS], char b[ROWS][COLS]);
5.Count 函数 用来计算用户输入坐标周围一圈8个坐标的雷总数
char Count(char a[ROWS][COLS], char b[ROWS][COLS], int x, int y);
三.test.c 函数调用
注意:主函数前一定要包含头文件 add.h
1.先定义一个meau函数,打印菜单
2. 初始化 input=1(input为玩家的输入)
3.再用一个while循环来控制多重循环,不跳出(input作为条件)。
4.while括号里的条件为input
5.while里面先调用一下meau函数 打印菜单,让玩家知道有那些选项
,在提示玩家输入他的选择,用一个 scanf 函数读取用户的选择,并存在input里面
6.在加一个Switch语句,括号里的条件也为input,
这样可以保证玩家在输入非0时,不会跳出,能继续循环下去,
而当玩家输入0时,while循环就会结束。
Switch中各个语句如下:
case 1: 表示进行游戏,调用game函数
case 0:表示游戏结束,退出程序
default : 提示玩家输入错误。因为input不是0,所以不会结束程序
每一个case要加break;执行完一个case时,才能跳出Switch循环,进而结束游戏。不然出现错误
注意:case 1:后面要用一个自定义game函数来实现游戏的进行。
下面重点讲述一下game 函数
四、add.c 函数定义
1.game函数
先定义game函数作为主体,里面再调用其他自定义函数,从而实现游戏的正常进行
注意:game函数前一定要包含头文件 add.h
(1).定义两个字符型数组
char mine[ROWS][COLS]; //隐含的布置雷的棋盘--mine
char show[ROWS][COLS]; //显示在屏幕上的棋盘--show
注意:这里是ROWS 和COLS,因为我们为了方便计算雷总数把数组扩大,当然定义时也不能忘了要定义大棋盘。
(2).调用两次Intial函数 来初始化
Intial(mine, '0'); //初始化mine棋盘为字符'0'
Intial(show, '*'); //初始化show棋盘为字符'*'
(3).调用Arrangemine 函数来布置雷在mine数组上
Arrangemine(mine); //布置雷在mine棋盘上,'0'表示无雷,'1'表示有雷
结果如下:
(4).调用 Print函数来把show棋盘展示出来
Print(show); //把全是※号的原始show棋盘打印在屏幕上,让玩家来进行猜测
结果如下:
(5).用Check 函数来进行排查 判断玩家输入的坐标结果
Check(mine, show); //排查 表明了 a-mine b-show
2.Intial函数
注意:把char也作为一个形参,这样,就可以很方便的调用两次,初始化mine 和 show棋盘
3.Arrangemine 函数
注意:1. srand((unsigned int)time(NULL));中 srand括号里的是种子
(unsigned int)time(NULL) 用来生成随机的种子的,只有种子变化,rand 生成的随机数才每次不一样
2.rand生成随机数范围 是0到RAND_MAX(32767或0x7ffff)
rand()%ROW +1 和 rand()%COL+1 使得 i 和 j 的范围在 1--9 之间,
3.要控制在1---9,是因为真正打印在屏幕上的,能布置雷的棋盘的位置的数组的下标是从[1]----[9],
这样,就可以在正确的范围随机布置好10个雷
4.Print函数
注意:
1.这里打印的是 ROW 行 COL列,因为,玩家就只需关注 ROW*COL 的棋盘,全打印出来会产生误导和干扰
2.这里,打印了边际,还打印了行号,列号,方便玩家判断坐标
5.Check 函数
计算雷总数
注意:Check函数还调用了Count函数,下面介绍Count函数
6.Count函数
注意: 因为 '1' - '0' = 1 '2' - '0' = 2
sum-9*'0'得到的是一个数字,要把它加上'0' 转换成字符 n ,再用return 返回
正好也可以反映雷个数
五、完整代码和运行过程
1.add.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9 //行
#define COL 9 //列
#define ROWS ROW+2 //多加2
#define COLS COL+2 //多加2
#define NUMBER 10 //十个雷
void Intial(char a[ROWS][COLS], char ch); //初始化数组
void Print(char a[ROWS][COLS]); //打印数组
void Arrangemine(char a[ROWS][COLS]); //布置数组
char Check(char a[ROWS][COLS], char b[ROWS][COLS]); //排查数组
char Count(char a[ROWS][COLS], char b[ROWS][COLS], int x, int y); //计算周围8个空格中雷数量并返回 x,y,为玩家输入的坐标
2.test.c
#include"add.h"
void meau()
{
printf("\n");
printf("************\n");
printf("* 1.play *\n");
printf("* 0.exit *\n");
printf("************\n");
}
int main()
{
int input = 1;
while (input)
{
meau();
printf("enter your option:>");
scanf("%d", &input);
switch (input)
{
case 1:printf("游戏开始\n"); game(); break;
case 0:printf("游戏结束\n"); break;
default:printf("输入错误,请重新输入\n"); break;
}
}
printf("have a good time\n");
}
3.add.c
#include "add.h"
void game()
{
char mine[ROWS][COLS]; //隐含的布置雷的棋盘--mine
char show[ROWS][COLS]; //显示在屏幕上的棋盘--show
Intial(mine, '0'); //初始化mine棋盘为字符'0'
Intial(show, '*'); //初始化show棋盘为字符'*'
Arrangemine(mine); //布置雷在mine棋盘上,'0'表示无雷,'1'表示有雷
Print(show); //把全是※号的原始show打印在屏幕上,让玩家来进行猜测
Check(mine, show); //排查 表明了 a-mine b-show
}
void Intial(char a[ROWS][COLS], char ch) //多加两行,都要初始化
{
int i, j;
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
a[i][j] = ch;
}
}
}
void Print(char a[ROWS][COLS]) //打印
{
int i, j;
printf("----------------------\n");
printf(" "); //三个空格
for (i = 1; i <= COL; i++)
printf("%-2d", i);
printf("\n");
printf(" ------------------\n");//前面有两个空格
for (i = 1; i <= ROW; i++) //显示出9*9就行 从a[1]到a[9]
{
printf("%-2d", i);
printf("|");
for (j = 1; j <= COL; j++)
{
printf("%-2c", a[i][j]);
}
printf("\n");
}
}
void Arrangemine(char a[ROWS][COLS]) //布置从[1]到[9]
{
srand((unsigned int)time(NULL));
int i, j;
int count = NUMBER;
while (count)
{
i = rand() % ROW + 1; //1-9
j = rand() % COL + 1;
if (a[i][j] == '0')
{
a[i][j] = '1';
count--;
}
}
}
char Check(char a[ROWS][COLS], char b[ROWS][COLS])//检查棋盘
{ //上面实参已说明 a-mine b-show
int x, y;
int count = ROW*COL-NUMBER; //不是雷的总数目
char appear;
while (1)
{
printf("enter what place you think:");
scanf("%d%d", &x, &y); //x,y,存储玩家输入的坐标
if (x >= 1 && x <= ROW && y >= 1 && y <= COL) // 保证坐标有效性
{
if (a[x][y] == '1') //如果是雷
{
printf("Unluckly,you are out\n");
printf("the mine board is\n");
Print(a); //给玩家看布置雷棋盘,让他输的心里有数
break;
}
else { //计算周围一圈雷数量
appear = Count(a,b, x, y); //把Count 函数返回值存在 appear 中
//printf("%c\n", appear);
b[x][y] = appear; //将周围八个中有几个雷显示出来 显示在玩家输入的坐标上
Print(b); //打印显示周围雷数量的棋盘
count--; //每成功排查一个,不是雷的数量就减一
}
if (count == 0) //当count为0,剩下的全是雷,证明游戏成功
{
printf("\nYou are successful! Congrutulations!\n");
Print(b); //给玩家看布置雷的棋盘
break;
}
}
else printf("enter error ,please enter again\n"); //提示玩家重新输入正确坐标
}
}
char Count(char a[ROWS][COLS], char b[ROWS][COLS], int x, int y) //计算周围并返回 返回型为char
{ //上面game函数调用时,实参已说明 a-mine b-show
int i, j;
int sum = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
sum += a[i][j]; //统计9宫格中的字符总和
}
}
return (sum - 9 * '0') + '0'; // 返回字符 'n ’,n表示周围一圈8个中有几个雷
}
//