扫雷的过程中,布置的雷和排出的雷都需要被存储,因为如果将两种都放在一起,就分别不出这个位置是雷的位置还是周围8个格子的雷的总数。
因为我们需要在99的棋盘上布置雷的信息和排查雷,首先想到的是创建一个99的数组来实现棋盘。
那如果这个位置布置雷,就存放1,没有布置雷就存放0。
当这个位置不是雷的时候,就需要统计周围8个位置的和,然后存放到当前位置。
那如果在计算边角时进行计算,就会发生数组越界的问题,为了解决这个问题,我们可以再在周围加一圈构成11*11的棋盘,这样就不会发生数组越界了。
解决了这个问题,就可以关注两个数组的问题了,因为我们的展示界面全是由 *构成的,而排查雷需要使用数字来表示,那我们可以使用数字字符来表示数值,最后将字符转化为数字就行了
这里我们设置3个文件
1.test.c 文件中写游戏的逻辑测试
2.game.c 文件中写游戏的函数实现
3.game.h 文件中写游戏需要的数据类型和游戏声明
第一步:菜单设置
test.c
void menu(void) {
printf("******************\n");
printf("******1.play******\n");
printf("******0.exit******\n");
printf("******************\n");
int main() {
int input = 0;
//srand((unsigned int)time(NULL));//使用时间种子
do {
menu();
printf("请选择:>");
scanf("%d", &input);
if (input == 1) {
//printf("ready\n");
game();
}
else if(input == 0) {
printf("end\n");
}
else {
printf("输入错误,重新输入\n");
}
} while (input);
return 0;
}
}
这样就可输出菜单,选择1的话就可以开始游戏,选择0退出游戏,选择错误重新选择
第二步:游戏函数
test.c
void game(void) {
//设置棋盘的格数,,11*11的棋盘不会出现越界问题
char mine[ROWS][COLS];//11
char show[ROWS][COLS];//11
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
}
game.h
#include
#define COL 9
#define ROW 9
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);
game.c
#include"game.h"
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
borad[i][j] = type;
}
}
}
这个函数的作用是创建数组,初始化棋盘,分别将数据类型和函数实现写在头文件中
第三步:打印棋盘
test.c
void game(void) {
//设置棋盘的格数,,11*11的棋盘不会出现越界问题
char mine[ROWS][COLS];//11
char show[ROWS][COLS];//11
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//打印棋盘
Printborad(show, ROW, COL);
Printborad(mine, ROW, COL);
}
game.h
#define COL 9
#define ROW 9
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);
//打印棋盘函数
void Printborad(char borad[ROW][COL], int row,int col);
game.c
void Printborad(char borad[ROW][COL],int row,int col) {
for (int i = 0; i <= row; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {
printf("%c ",borad[i][j]);
}
printf("\n");
}
}
这个函数用以打印棋盘,可以看出棋盘的规划是否正确,当然我们只用打印show棋盘,不用打印mine棋盘,因为mine棋盘可以看到的全是0,这里为了不多写一个函数用来分别打印’*‘和’0’,所有我们再传一个一个参数type,告诉Printboard函数应该打印什么字符。
第四步:布置雷
test.c
void game(void) {
//设置棋盘的格数,,11*11的棋盘不会出现越界问题
char mine[ROWS][COLS];//11
char show[ROWS][COLS];//11
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//打印棋盘
Printborad(show, ROW, COL);
//Printborad(mine, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
Printborad(mine, ROW, COL);//查看是否将雷布置好了
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));//使用时间种子
do {
menu();
printf("请选择:>");
scanf("%d", &input);
if (input == 1) {
//printf("ready\n");
game();
}
else if(input == 0) {
printf("end\n");
}
else {
printf("输入错误,重新输入\n");
}
} while (input);
return 0;
}
game.h
#include //使用时间种子
#include //使用随机数
#define COUNT 10//10个雷
//布置雷函数
void SetMine(char borad[ROW][COL], int row, int col);
game.c
void SetMine(char borad[ROW][COL], int row, int col) {
//产生随机数
int count = COUNT;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (borad[x][y] == '0') {
borad[x][y] = '1';
count--;
}
}
}
这里使用随机数设置雷的位置坐标,需要包含头文件#include
#include
第五步:排查雷
test.c
void game(void) {
//设置棋盘的格数,,11*11的棋盘不会出现越界问题
char mine[ROWS][COLS];//11
char show[ROWS][COLS];//11
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//打印棋盘
Printborad(show, ROW, COL);
//Printborad(mine, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
Printborad(mine, ROW, COL);//查看是否将雷布置好了
//排查雷
FindMine(mine, show, ROW, COL);
}
game.h
void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col);
game.c
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
return (mine[x - 1][y] + mine[x - 1][y - 1] +mine[x-1][y+1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}
void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col) {
int x = 0;
int y = 0;
int win = 0;
while (win < row * col- COUNT) {
printf("输入要查看的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了\n");
Printborad(show, ROW, COL);
break;
}
else {
//说明此处不是雷,则统计周围8个雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
Printborad(show, ROW, COL);
win++;
}
}
else {
printf("坐标非法,重新输入\n");
}
}
if (win == row * col - COUNT) {
printf("恭喜,排雷成功\n");
Printborad(mine, ROW, COL);
}
}
使用FindMine函数排查雷,先输入要查看的坐标,如果坐标符合规定,则看这个坐标是否是雷,如果不是则计算周围8个位置的和并输出在棋盘上,当排查完71个没有雷的位置后,游戏成功。如果该位置非法,则重新输入。
以上涉及到一个重要的知识点,那就是:如何将数字字符转化为数字
可以直接使用数字字符减去字符0,比如:
‘0’ - ‘0’ = 0
‘1’ - ‘0’ = 1
‘55’ - ‘0’ = 55
这是因为字符之间的减法是减的ASCII码值,所以ASCII值相减就可以得到数字。
完整代码:
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include //使用时间种子
#include //使用随机数
#define COUNT 10//10个雷
#define COL 9
#define ROW 9
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type);
//打印棋盘函数
void Printborad(char borad[ROW][COL], int row,int col);
//布置雷函数
void SetMine(char borad[ROW][COL], int row, int col);
//排查雷
void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char borad[ROWS][COLS], int rows, int cols,char type) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
borad[i][j] = type;
}
}
}
void Printborad(char borad[ROW][COL],int row,int col) {
for (int i = 0; i <= row; i++) {
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {
printf("%c ",borad[i][j]);
}
printf("\n");
}
}
void SetMine(char borad[ROW][COL], int row, int col) {
//产生随机数
int count = COUNT;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (borad[x][y] == '0') {
borad[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
return (mine[x - 1][y] + mine[x - 1][y - 1] +mine[x-1][y+1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}
void FindMine(char mine[ROW][COL], char show[ROW][COL], int row, int col) {
int x = 0;
int y = 0;
int win = 0;
while (win < row * col- COUNT) {
printf("输入要查看的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (mine[x][y] == '1') {
printf("很遗憾,你被炸死了\n");
Printborad(show, ROW, COL);
break;
}
else {
//说明此处不是雷,则统计周围8个雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
Printborad(show, ROW, COL);
win++;
}
}
else {
printf("坐标非法,重新输入\n");
}
}
if (win == row * col - COUNT) {
printf("恭喜,排雷成功\n");
Printborad(mine, ROW, COL);
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu(void) {
printf("******************\n");
printf("******1.play******\n");
printf("******0.exit******\n");
printf("******************\n");
}
void game(void) {
//设置棋盘的格数,,11*11的棋盘不会出现越界问题
char mine[ROWS][COLS];//11
char show[ROWS][COLS];//11
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//打印棋盘
Printborad(show, ROW, COL);
//Printborad(mine, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
Printborad(mine, ROW, COL);//查看是否将雷布置好了
//排查雷
FindMine(mine, show, ROW, COL);
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));//使用时间种子
do {
menu();
printf("请选择:>");
scanf("%d", &input);
if (input == 1) {
//printf("ready\n");
game();
}
else if(input == 0) {
printf("end\n");
}
else {
printf("输入错误,重新输入\n");
}
} while (input);
return 0;
}
感谢观看!