1.用C语言实现扫雷游戏
本博客和三子棋游戏比较大的区别是,三子棋游戏是写完了再总结的,本博客是边代码实现边编辑博客,所以本博客会比较详细的po出每一步骤,在每实现一个小功能的时候我们都先验证下效果,再继续下一步。
2.思路
总体的思路和三子棋游戏是一样的,我们把游戏实现部分放在game.c和game.h中,把游戏的测试代码放到test.c中。main函数在test.c中。
小tips:我们把需要包含的头文件都放在game.h中,game.c和test.c中只需要包含我们的game.h一个头文件即可。
2.1 test.c函数实现
2.1.1 main()函数和test()函数实现
在main函数中只简单调用我们的test()函数,在test()函数中打印游戏菜单,实现让玩家选择开始游戏还是结束游戏。
- game.h中的代码实现
#pragma once //这个是我创建.h文件的时候自动出现的,不是自己手敲的
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
- test.c中的代码实现
#include "game.h"
void manu()
{
printf("===========================\n");
printf("========1:开始游戏=========\n");
printf("========0:结束游戏=========\n");
printf("===========================\n");
}
void test()
{
int input = 0;
do
{
manu();
printf("请输入您的选择:\n");
scanf("%d", &input);
switch(input)
{
case 1:
//game(); 因为还没有实现game()所以这里我屏蔽掉了。
break;
case 0:
printf("游戏结束,欢迎下次再来!\n");
break;
default:
printf("您的输入有误,请重新输入:\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
- 验证
2.1.2 test.c中的game()函数实现思路
设计扫雷游戏之前,先进行思考
- 创建地图,9*9的二维数组,元素类型是什么?
- 每个格子的状态有以下状态
a)未翻开(草地)
b)已翻开(数字)
c)是地雷
d)不是地雷
四种状态是两大类,我们用两个二维数组表示。
第一个数组表示翻开状态showMap:
char类型表示,如果是 * 表示未翻开 ; 如果是阿拉伯数字,就表示翻开
第二个数组表示是否地雷状态mineMap:
char 类型表示 如果是 【1】:表示是地雷 【0】:表示不是地雷 、 也可以int 类型表示 如果是数字1:地雷; 数字0:不是地雷 - 这里还有个需要考虑的是虽然9×9数组是我们的目标,但是在边角位置,我们要对周围8个位置进行数雷的个数,非常容易数组越界,这里的解决思路有两个,其一是每次都需要判定我们的翻开位置是否是边角位置,这样比较繁琐。其二是直接创建两个11×11的数组,这样我们使用我们9*9的地图的时候就没有这个风险。这里使用的是第二个思路。
扫雷游戏的思路
- 先创建地图(两个地图一个是我们放雷的地图mineMap,一个是我们的展示地图showMap),并进行初始化
a)针对showMap 默认初始化全是 *,表示未知,等待玩家翻开
b)针对mineMap 默认初始化都是字符’0’,之后我们初始化10个地雷(根据随机位置来摆放) 没地雷用字符’0’ 表示,地雷位置用字符’1’表示- 打印地图showMap
- 给mineMap地图布置雷。
- 排查雷
a)提示玩家输入要翻开的位置坐标,并进行校验
b) 判定当前位置是否是雷,如果是雷则游戏失败,游戏结束
c) 如果当前位置是最后一个“不是雷的格子”那么游戏胜利,游戏结束
d)如果不是雷,更新翻开的当前位置,把【* 】替换成一个数字(就把showMap中对应位置的 * 修改成一个具体的数字)这个数字要根据当前位置周围8个格子的地雷数目来决定。- 下一步从2继续开始,直到游戏结束。
2.2 test.c中的game()函数和game.c中的函数实现
2.2.1 地图创建
- 在test.c中的game()函数中创建两个char类型的二维数组,需要设置两个全局变量,我们放在game.h中,这里我们先设置两个为9的行和列,由于我们为了避免数组越界所以又定义了一个,MAX_ROW和MAX_COL变量,这样设置,之后打印的时候不需要写很多个9了,直接用这个全局变量。
//game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9
#define COL 9
#define MAX_ROW ROW+2
#define MAX_COL COL+2
#include <stdio.h>
//test.c
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
}
2.2.2 地图初始化
- game函数中只需要调用init函数,init函数的实际的实现在game.c中。
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
}
- init函数具体实现
先在game.h中声明
//game.h
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char i);
然后在game.c中具体实现
可以用for循环,也可以使用库函数memset,这里因为我们需要初始化两个数组,但是两个数组的内容不同,所以给init函数添加了一个参数,用来传入我们要初始化的值。
//game.c
//1.地图初始化
void init(char board[MAX_ROW][MAX_COL], int row, int col, char set)
{
#if 0
int i = 0;
int j = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
#endif
memset(board, set, row * col * sizeof(char));
}
2.2.3 地图打印
- game函数中只需要调用Print函数,Print函数的实际的实现在game.c中。
//test.c
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
Print(mineMap, ROW, COL);
}
- Print函数具体实现
先在game.h中声明
//game.h
//1.地图初始化
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char set);
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col);
在game.c中具体实现
第一版本
//game.c
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col)
{
//我们只需要打印9*9的,但是我们必须用11*11的接收,
// 因为数组的存储方式决定了,我们不可能只单单把中间元素取出来,只能按顺序取
int i = 0;
int j = 0;
for (i = 1; i < row-1; i++)
{
for (j = 1; j < col-1; j++)
{
printf("%c", board[i][j]);
}
printf("\n");
}
}
第一版本效果(有点丑)
第二版本,每个值之间添加空格
第三版本,给每一行上面和每一列的前面增加数字,让玩家能直观的看到是第几行第几列。在最开始和结束打印一行提示扫雷。
//game.c
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col)
{
//我们只需要打印9*9的,所以传值的时候只需要传9行9列
// 但是我们必须用11*11的接收, 因为数组的存储方式决定了,
// 我们不可能只单单把中间元素取出来,只能按顺序取
printf("--------扫雷-------\n");
int i = 0;
int j = 0;
//控制列号
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//控制行号
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------扫雷-------\n");
}
第三版本效果
2.3.4 布置雷
- 在game()函数中调用布置雷函数
//test.c
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
Print(mineMap, ROW, COL);//实际游戏的时候,不能打印存放雷的地图
//4.布置雷
setMine(mineMap, ROW, COL);//布置9*9,所以传的是9行9列
Print(mineMap, ROW, COL);//布置完打印下看看效果
}
- 在game.h中声明
//test.c
//1.地图初始化
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char set);
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col);
//3.布置雷
void setMine(char board[MAX_ROW][MAX_COL], int row, int col);//接收还是11行11列,我们只是只需要对9*9的位置进行布置雷操作。
- 在game.c中实现
设定10个雷,在game.h中宏定义一下
//game.h
#define EASY_MODE 10
思路:随机生成坐标,只要该坐标不是雷,就布置雷。
随机数生成函数rand()需要和srand()函数搭配使用,在我们的test()函数中调用我们的srand()函数生成随机数种子,要记得在game.h中添加我们的头文件。
//game.h
#include<stdlib.h>
#include<time.h>
//test.c中的test()添加
srand((unsigned int)time(NULL));
排查雷函数实现
//3.布置雷
void setMine(char board[MAX_ROW][MAX_COL], int row, int col)
{
//思路:设置10个count,让count一直减减,当count减到0的时候就表示我们布置雷完成。
int mine_Count = EASY_MODE;
while (mine_Count)
{
//1.生成随机数坐标
int x = rand() % row+1;//要生成0~9 mod9就是0~9 全部+1 就是1~10
int y = rand() % col+1;
//2.判断该坐标是否是雷,是雷就重新生成随机坐标,否则就布置
if (board[x][y] == '1')
{
continue;
}
else
{
board[x][y] = '1';
mine_Count--;//布置成功之后要记得给count--
}
}
}
布置雷函数效果
2.3.5 排查雷
实现思路:
- 提示玩家输入要翻开的位置坐标,并去mineMap中进行校验
- 判定当前位置是否是雷,如果是雷则游戏失败,游戏结束
- 如果当前位置是最后一个“不是雷的格子”那么游戏胜利,(81个格子,10个雷,即需要找到71个不是雷的格子),游戏结束
- 如果不是雷,showMap中更新翻开的当前位置,把【‘*’ 】替换成一个数字(就把showMap中对应位置的【’ * '】修改成一个具体的数字)这个数字要根据当前位置周围8个格子的地雷数目来决定。
- 在game()函数中调用findMine()
//test.c
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
Print(mineMap, ROW, COL);//实际游戏的时候,不能打印存放雷的地图
//4.布置雷
setMine(mineMap, ROW, COL);//布置9*9,所以传的是9行9列
Print(mineMap, ROW, COL);
//5.排查雷
findMine(mineMap, showMap, ROW, COL);
}
- 在game.h中声明
//game.h
//1.地图初始化
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char set);
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col);
//3.布置雷
void setMine(char board[MAX_ROW][MAX_COL], int row, int col);
//4.排查雷
void findMine(char board[MAX_ROW][MAX_COL], char board2[MAX_ROW][MAX_COL], int row, int col);
- 在game.c中实现
版本1
//game.c
//可以加static 只有本.c文件的函数可以调用它
static int getMineCount(char mineMap[MAX_ROW][MAX_COL], int x, int y)
{
//知道了x,y能够算出它的周围格子坐标,我们把所有坐标的值加起来,减去8*字符‘0’就把字符数字转换为数字,得到的值就是周围有几个1
return (mineMap[x - 1][y - 1] + mineMap[x - 1][y] + mineMap[x - 1][y + 1] + mineMap[x][y + 1]
+ mineMap[x + 1][y + 1] + mineMap[x + 1][y] + mineMap[x + 1][y - 1] + mineMap[x][y - 1]) - 8 * '0';
}
//4.排查雷
void findMine(char mineMap[MAX_ROW][MAX_COL], char showMap[MAX_ROW][MAX_COL], int row, int col)
{
//1.提示玩家,输入要排查的坐标
printf("请输入你要排查的坐标:\n");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//1.判断这个坐标是不是雷。是雷提示,游戏失败
if (mineMap[x][y] == '1')
{
printf("很抱歉你扫到雷了,游戏结束\n");
Print(mineMap, row, col);
break;
}
else
{ //不是雷,需要数下周围8个格子有几个雷,封装一个函数 ,得到的数值写回到showMap中去。
int n = getMineCount(mineMap, x, y);//这里是int
showMap[x][y] = n+'0';//showMap存放的是字符类型,我们需要把得到的int数字。转换成对应的字符。这里是加上一个字符'0'
Print(showMap, row, col);
}
}
else
{
printf("坐标非法,请重新输入:\n");//所以这里要用到循环,万一玩家输入非法坐标
}
}
}
版本1效果
我们到这一步就可以简单的玩起来了,我们可以 game()中不打印我们的mineMap(),然后玩下我们的游戏。
版本2:
版本1缺少赢的判断。是死循环,我们需要增加对于玩家赢的情况的判断。
思路:每找到一个不是雷的格子count就++。 当找到第71个不是雷的格子的时候,游戏结束。 (81个格子减去10个雷,就剩下71个不是雷的格子)
//4.排查雷
void findMine(char mineMap[MAX_ROW][MAX_COL], char showMap[MAX_ROW][MAX_COL], int row, int col)
{
//1.提示玩家,输入要排查的坐标
printf("请输入你要排查的坐标:\n");
int x = 0;
int y = 0;
//每找到一个不是雷的格子count就++。
// 当找到第71个不是雷的格子的时候,游戏结束。
// (81个格子减去10个雷,就剩下71个不是雷的格子)
int winCount = 0;
while (winCount < row*col-EASY_MODE)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//1.判断这个坐标是不是雷。是雷提示,游戏失败
if (mineMap[x][y] == '1')
{
printf("很抱歉你扫到雷了,游戏结束\n");
Print(mineMap, row, col);
break;
}
else
{ //不是雷,需要数下周围8个格子有几个雷,封装一个函数 ,得到的数值写回到showMap中去。
int n = getMineCount(mineMap, x, y);//这里是int
showMap[x][y] = n+'0';//showMap存放的是字符类型,我们需要把得到的int数字。转换成对应的字符。这里是加上一个字符'0'
Print(showMap, row, col);
winCount++;
}
}
else
{
printf("坐标非法,请重新输入:\n");//所以这里要用到循环,万一玩家输入非法坐标
}
}
if (winCount == row * col - EASY_MODE) //这里必须加判断条件,因为排雷失败也会跳出出while循环
{
printf("恭喜你!排雷成功!\n");
}
}
验证下,把我们的雷改成80个,我们直接找到那个不是雷的坐标,验证下我们的逻辑。
在game.h中
#define EASY_MODE 80
在test.c的game()函数中打印我们的mineMap。
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
//Print(mineMap, ROW, COL);//实际游戏的时候,不能打印存放雷的地图
//4.布置雷
setMine(mineMap, ROW, COL);//布置9*9,所以传的是9行9列
Print(mineMap, ROW, COL);
//5.排查雷
findMine(mineMap, showMap, ROW, COL);//我们找雷的时候也只需要9*9的
}
版本2效果
版本3
小优化,(1)我们应该把我们的提示,请输入想要排查的坐标放到循环里面(2)在我们排雷成功的时候打印下我们的mineMap,看下我们的成功结果(3)把我们的EASY_MODE 改回10(4)在test的game函数中不打印我们的mineMap。就可以正常玩游戏了。(5)在玩家输入坐标的时候要判断下是否已经输入过这个坐标,否则我们重复我们已经排查过的坐标,count还一直++,会导致我们还没有拍完雷就判定我们赢了。
//game.h
#define EASY_MODE 10
//game.c
//4.排查雷
void findMine(char mineMap[MAX_ROW][MAX_COL], char showMap[MAX_ROW][MAX_COL], int row, int col)
{
int x = 0;
int y = 0;
//每找到一个不是雷的格子count就++。
// 当找到第71个不是雷的格子的时候,游戏结束。
// (81个格子减去10个雷,就剩下71个不是雷的格子)
int winCount = 0;
while (winCount < row*col-EASY_MODE)
{
//1.提示玩家,输入要排查的坐标
printf("请输入你要排查的坐标:\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断输入的坐标是否已经排查过了。排查过的坐标在showMap中不是*
if (showMap[x][y] != '*')
{
printf("该坐标已经排查过了,请重新输入:\n");
continue;
}
//1.判断这个坐标是不是雷。是雷提示,游戏失败
if (mineMap[x][y] == '1')
{
printf("很抱歉你扫到雷了,游戏结束\n");
Print(mineMap, row, col);
break;
}
else
{ //不是雷,需要数下周围8个格子有几个雷,封装一个函数 ,得到的数值写回到showMap中去。
int n = getMineCount(mineMap, x, y);//这里是int
showMap[x][y] = n+'0';//showMap存放的是字符类型,我们需要把得到的int数字。转换成对应的字符。这里是加上一个字符'0'
Print(showMap, row, col);
winCount++;
}
}
else
{
printf("坐标非法,请重新输入:\n");//所以这里要用到循环,万一玩家输入非法坐标
}
}
if (winCount == row * col - EASY_MODE) //这里必须判断,因为排雷失败也会出while循环
{
printf("恭喜你!排雷成功!\n");
Print(mineMap, row, col);
}
}
//test.c
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
//Print(mineMap, ROW, COL);//实际游戏的时候,不能打印存放雷的地图
//4.布置雷
setMine(mineMap, ROW, COL);//布置9*9,所以传的是9行9列
//Print(mineMap, ROW, COL);
//5.排查雷
findMine(mineMap, showMap, ROW, COL);//我们找雷的时候也只需要9*9的
}
我们也是验证下,把我们的EASY_MODE改成79 ,打印我们的mineMap,
#define EASY_MODE 79
3.全部代码
3.1 test.c
#include "game.h"
void manu()
{
printf("===========================\n");
printf("========1:开始游戏=========\n");
printf("========0:结束游戏=========\n");
printf("===========================\n");
}
void game()
{
//1.地图创建
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
//2.地图初始化
init(showMap, MAX_ROW,MAX_COL,'*');
init(mineMap, MAX_ROW, MAX_COL, '0');
//3. 地图打印
Print(showMap, ROW, COL); //打印地图我们只需要9行9列
//Print(mineMap, ROW, COL);//实际游戏的时候,不能打印存放雷的地图
//4.布置雷
setMine(mineMap, ROW, COL);//布置9*9,所以传的是9行9列
//Print(mineMap, ROW, COL);
//5.排查雷
findMine(mineMap, showMap, ROW, COL);//我们找雷的时候也只需要9*9的
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
manu();
printf("请输入您的选择:\n");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("游戏结束,欢迎下次再来!\n");
break;
default:
printf("您的输入有误,请重新输入:\n");
}
} while (input);
}
int main()
{
test();
return 0;
}
3.2 game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9
#define COL 9
#define MAX_ROW ROW+2
#define MAX_COL COL+2
#define EASY_MODE 10
#include <stdio.h>
#include <string.h>
#include<stdlib.h>
#include<time.h>
//1.地图初始化
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char set);
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col);
//3.布置雷
void setMine(char board[MAX_ROW][MAX_COL], int row, int col);
//4.排查雷
void findMine(char board[MAX_ROW][MAX_COL], char board2[MAX_ROW][MAX_COL], int row, int col);
3.3 game.c
#include "game.h"
//1.地图初始化
void init(char board[MAX_ROW][MAX_COL], int row, int col, char set)
{
#if 0
int i = 0;
int j = 0;
for (i = 0; i < col; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
#endif
memset(board, set, row * col * sizeof(char));
}
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col)
{
//我们只需要打印9*9的,所以传值的时候只需要传9行9列
// 但是我们必须用11*11的接收, 因为数组的存储方式决定了,
// 我们不可能只单单把中间元素取出来,只能按顺序取
printf("--------扫雷-------\n");
int i = 0;
int j = 0;
//控制列号
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//控制行号
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------扫雷-------\n");
}
//3.布置雷
void setMine(char board[MAX_ROW][MAX_COL], int row, int col)
{
//思路:设置10个count,让count一直减减,当count减到0的时候就表示我们布置雷完成。
int mine_Count = EASY_MODE;
while (mine_Count)
{
//1.生成随机数坐标
int x = rand() % row+1;//要生成0~9 mod9就是0~9 全部+1 就是1~10
int y = rand() % col+1;
//2.判断该坐标是否是雷,是雷就重新生成随机坐标,否则就布置
if (board[x][y] == '1')
{
continue;
}
else
{
board[x][y] = '1';
mine_Count--;
}
}
}
//可以加static 只有本.c文件的函数可以调用它
static int getMineCount(char mineMap[MAX_ROW][MAX_COL], int x, int y)
{
//知道了x,y能够算出它的周围格子坐标,我们把所有坐标的值加起来,减去8*字符‘0’就把字符数字转换为数字,得到的值就是周围有几个1
return (mineMap[x - 1][y - 1] + mineMap[x - 1][y] + mineMap[x - 1][y + 1] + mineMap[x][y + 1]
+ mineMap[x + 1][y + 1] + mineMap[x + 1][y] + mineMap[x + 1][y - 1] + mineMap[x][y - 1]) - 8 * '0';
}
//4.排查雷
void findMine(char mineMap[MAX_ROW][MAX_COL], char showMap[MAX_ROW][MAX_COL], int row, int col)
{
int x = 0;
int y = 0;
//每找到一个不是雷的格子count就++。
// 当找到第71个不是雷的格子的时候,游戏结束。
// (81个格子减去10个雷,就剩下71个不是雷的格子)
int winCount = 0;
while (winCount < row*col-EASY_MODE)
{
//1.提示玩家,输入要排查的坐标
printf("请输入你要排查的坐标:\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断输入的坐标是否已经排查过了。排查过的坐标在showMap中不是*
if (showMap[x][y] != '*')
{
printf("该坐标已经排查过了,请重新输入:\n");
continue;
}
//1.判断这个坐标是不是雷。是雷提示,游戏失败
if (mineMap[x][y] == '1')
{
printf("很抱歉你扫到雷了,游戏结束\n");
Print(mineMap, row, col);
break;
}
else
{ //不是雷,需要数下周围8个格子有几个雷,封装一个函数 ,得到的数值写回到showMap中去。
int n = getMineCount(mineMap, x, y);//这里是int
showMap[x][y] = n+'0';//showMap存放的是字符类型,我们需要把得到的int数字。转换成对应的字符。这里是加上一个字符'0'
Print(showMap, row, col);
winCount++;
}
}
else
{
printf("坐标非法,请重新输入:\n");//所以这里要用到循环,万一玩家输入非法坐标
}
}
if (winCount == row * col - EASY_MODE) //这里必须判断,因为排雷失败也会出while循环
{
printf("恭喜你!排雷成功!\n");
Print(mineMap, row, col);
}
}
4 小结
-
关于为什么定义了全局常量,但是在函数实现的时候没有直接使用定义的全局常量,还传了两个row和col参数。
其一是尽量不要让函数过分依赖全局符号;
其二是以参数的形式传进去,是比较灵活的,比如我们的打印函数,我们只需要使用9×9的,我们就传9×9,如果我们要用12×12的我们就可以直接传,尽量用什么以参数的形式传递给函数进行使用。 -
数字2如何变成字符2
字符2的ASCII码是50
字符‘0’ 的ASCII码是48
所以 给数字2+字符’0’就能得到字符‘2’。