把所有非地雷的地图格子排查掉,即胜利。踩到地雷格子即失败!
init 初始化函数
数组创建好后,我们要对两个数组进行初始化,用双重循环有些许麻烦,这里使用memset实现,memset功能是把一段内存上的每个字节都设置成一个具体的值, memset(第一段内存起始的地址,具体想要转换成什么样的值,内存的长度)
//1.初始化地图
void init(char ShowMap[MAX_ROW][MAX_COL], char MineMap[MAX_ROW][MAX_COL]) {
//for (int row = 0; row < MAX_ROW; row++) {
// for (int col = 0; col < MAX_COL; col++) {
// ShowMap[row][col] = '*';
// MineMap[row][col] = '0';
// }
//}
memset(ShowMap, '*', MAX_ROW * MAX_COL);
//此处计算内存的长度不能用sizeof,会隐式转化成指针!因此用sizeof求的是一个指针的长度,并非数组的长度
memset(MineMap, '0', MAX_ROW * MAX_COL);
srand((unsigned int)time(0));//随机种子
int MineCount = 0;
while (MineCount<MINE_COUNT) {
int row = rand() % MAX_ROW;//随即生成10个位置 存放地雷
int col = rand() % MAX_COL;
if (MineMap[row][col] == '1') {
continue;
}
MineMap[row][col] = '1';
MineCount++;
}
}
第一个数组存放地图的排查状态,面向玩家创建,展示给玩家,称之为ShowMap,如下所示:
char ShowMap[MAX_ROW][MAX_COL] = {
0 };
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
* * * * * * * * *
第二个数组存放地雷的分布信息,面向游戏设计者创建,称之为MineMap,如下所示:
char MineMAP[MAX_ROW][MAX_COL] = {
0 };
1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1
此处形参命名为theMap是希望这个函数同时具备打印两张地图的功能,只叫map也不太合适,因为C++标准库中有一个 std::map
使用双for循环实现地图的打印
void Print(char theMap[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
printf("%c ", theMap[row][col]);
}
printf("\n");
}
}
玩家确定排查位置:在主函数中写一个while循环即可实现!
玩家输入要排查的坐标时,一定不要忘了合法性判定!
1.越界判定
2.重复排查判定
while (1) {
Print(ShowMap);
int row = 0;
int col = 0;
printf("请输入要排查的坐标(row,col):");
scanf("%d %d", &row, &col);
//合法性判定
//1.越界判定
if (row<0 || row>=MAX_ROW || col<0 || col>=MAX_COL) {
printf("您输入的坐标已越界,请重新输入:\n");
continue;
}
//2.重复排查判定
if (ShowMap[row][col] != '*') {
printf("您输入的坐标位置已被排查,请重新输入:\n");
continue;
}
玩家输入坐标排查地图格子,我们初始化的时候,
while (1) {
int row = 0;
int col = 0;
printf("请输入要排查的坐标(row,col):");
scanf("%d %d", &row, &col);
if (MineMap[row][col] == '1') {
printf("您踩雷了!游戏结束!!\n");
break;
}
}
Update函数 即实现未踩雷,进行已排查地图格子周围格子地雷的个数统计
计算中间位置周围格子的地雷数count,边角位置和中间位置不参与计算,使用双for循环实现count的计数
周围格子的表示方式如下图:
void Update(char ShowMap[MAX_ROW][MAX_COL], char MineMap[MAX_ROW][MAX_COL], int row, int col) {
int count = 0;
for (int r = row - 1; r <= row + 1; r++) {
for (int c = col - 1; c <= col + 1; c++) {
if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL) {
//超出地图范围,直接跳出进入下次循环
continue;
}
if (r == row && c == col) {
//中间位置不参与计算 直接进入下次循环
continue;
}
if (MineMap[r][c] == '1') {
count++;
}
}
}
ShowMap[row][col] = '0' + count;//类似这种转换 仅限C中使用
//不能直接给赋值,因为 数值是int类型,ShowMap是char型,
//ShowMap[row][col] =2 此时row ,col的位置元素就设置成了ASCII值为2的字符 而不是字符'2'
}
进行扫雷,如果玩家踩雷就被炸死,未踩雷,系统报告周围雷的个数。直到所有非地雷地图格子都被排查 即获胜!
int main(){
char ShowMap[MAX_ROW][MAX_COL] = {
0 };
char MineMap[MAX_ROW][MAX_COL] = {
0 };
init(ShowMap, MineMap);
int openedCount = 0;
while (1) {
Print(ShowMap);
int row = 0;
int col = 0;
printf("请输入要排查的坐标(row,col):");
scanf("%d %d", &row, &col);
//合法性判定
//1.越界判定
if (row<0 || row>=MAX_ROW || col<0 || col>=MAX_COL) {
printf("您输入的坐标已越界,请重新输入:\n");
continue;
}
//2.重复排查判定
if (ShowMap[row][col] != '*') {
printf("您输入的坐标位置已被排查,请重新输入:\n");
continue;
}
if (MineMap[row][col] == '1') {
printf("您踩雷了!游戏结束!!\n");
break;
}
system("cls");
//更新ShowMap
Update(ShowMap,MineMap,row,col);
openedCount++;
if (openedCount == MAX_COL * MAX_COL - MINE_COUNT) {
printf("恭喜您!赢得胜利!\n");
}
}
system("pause");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define MAX_ROW 9
#define MAX_COL 9
#define MINE_COUNT 10
//1.初始化地图
void init(char ShowMap[MAX_ROW][MAX_COL], char MineMap[MAX_ROW][MAX_COL]) {
//for (int row = 0; row < MAX_ROW; row++) {
// for (int col = 0; col < MAX_COL; col++) {
// ShowMap[row][col] = '*';
// MineMap[row][col] = '0';
// }
//}
memset(ShowMap, '*', MAX_ROW * MAX_COL);//(第一段内存起始的地址,具体想要转换成什么样的值,内存的长度)
//此处计算内存的长度不能用sizeof,会隐式转化成指针!因此用sizeof求的是一个指针的长度,并非数组的长度
//memset功能是把 一段内存上的每个字节都设置成一个具体的值
memset(MineMap, '0', MAX_ROW * MAX_COL);//memset 虽然在string头文件里,但与字符串没关系,只是方式放错了,现在改不了,因为“向前兼容!”
srand((unsigned int)time(0));
int MineCount = 0;
while (MineCount<MINE_COUNT) {
int row = rand() % MAX_ROW;//随即生成10个位置 存放地雷
int col = rand() % MAX_COL;//这样生成随机数可能会重复,
if (MineMap[row][col] == '1') {
continue;
}
MineMap[row][col] = '1';
MineCount++;
}
}
void Print(char theMap[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
printf("%c ", theMap[row][col]);
}
printf("\n");
}
}
void Update(char ShowMap[MAX_ROW][MAX_COL], char MineMap[MAX_ROW][MAX_COL], int row, int col) {
int count = 0;
//if (MineMap[row - 1][col - 1] == '1') {
//count++;
//}
for (int r = row - 1; r <= row + 1; r++) {
for (int c = col - 1; c <= col + 1; c++) {
if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL) {
//超出地图范围,直接跳出进入下次循环
continue;
}
if (r == row && c == col) {
//中间位置不参与计算 直接进入下次循环
continue;
}
if (MineMap[r][c] == '1') {
count++;
}
}
}
ShowMap[row][col] = '0' + count;//类似这种转换 仅限C中使用
//不能直接给赋值,因为 数值是int类型,ShowMap是char型,
//ShowMap[row][col] =2 此时row ,col的位置元素就设置成了ASCII值为2的字符 而不是字符'2'
}
int main(){
//Menu();
char ShowMap[MAX_ROW][MAX_COL] = {
0 };
char MineMap[MAX_ROW][MAX_COL] = {
0 };
init(ShowMap, MineMap);
int openedCount = 0;
while (1) {
Print(ShowMap);
int row = 0;
int col = 0;
printf("请输入要排查的坐标(row,col):");
scanf("%d %d", &row, &col);
//合法性判定
//1.越界判定
if (row<0 || row>=MAX_ROW || col<0 || col>=MAX_COL) {
printf("您输入的坐标已越界,请重新输入:\n");
continue;
}
//2.重复排查判定
if (ShowMap[row][col] != '*') {
printf("您输入的坐标位置已被排查,请重新输入:\n");
continue;
}
if (MineMap[row][col] == '1') {
printf("您踩雷了!游戏结束!!\n");
break;
}
system("cls");
//更新ShowMap
Update(ShowMap,MineMap,row,col);
openedCount++;
if (openedCount == MAX_COL * MAX_COL - MINE_COUNT) {
printf("恭喜您!赢得胜利!\n");
}
}
system("pause");
return 0;
}
#define MAX_ROW 9 //地图行宽
#define MAX_COL 9 //地图列宽
#define MINE_COUNT 10
在创建地图时,建立了两个二维数组,ShowMap[9][9] 和 MineMap[9][9],代码中没有直接写9,是用宏给一个定义,避免这些魔幻数字的出现!大大增加代码的可读性~~
srand((unsigned int)time(0));//随机种子
int row = rand() % MAX_ROW;//随即生成10个位置 存放地雷
int col = rand() % MAX_COL;
rand() 用于生成随机数,但不是生成真正的随机数
srand()用于设置供rand使用的随机数种子
第一次调用rand之前没有调用srand,那么系统会为你自动调用srand,自动调用传参值为1,这样的话,采用相同的种子则每次生成的随机数便会重复,故我们常常使用“时间戳”来初始化~包含在头文件
这里不做详细的解释,后序会出 rand&srand 篇!