一.扫雷规则
扫雷的详细规则是随便点开一个方格,根据展开方格的数字去推断其相邻九宫格内未展开方格下面是否是地雷,最终任务就是点开所有没有地雷的方格,以找出所有的地雷。
二.设计思路
1.创建二维数组来表示地图
(1)第一个二维数组(showMap)表示未翻开状态(草地)和已翻开状态(数字)
用表示未翻开,字符0-8表示已经翻开的数字
(2)第二个二维数组(mineMap)表示每个格子是否是地雷
1 表示是地雷 0表示不是地雷
2.初始化地图
(1)将地图全部变为未翻开状态,针对showMap,即
(2)将每个位置全部变为非地雷,针对mineMap,即所有元素都初始化为0,然后随机生成十个位置作为地雷,设置为1
3.打印地图
4.让玩家输入坐标,表示要翻开的位置
5.判断是否踩雷
6.更新showMap,在翻开位置显示周围有多少地雷
7.判断玩家是否翻开所有位置
三.代码详解
1.创建地图并初始化
#define MAX_ROW 9
#define MAX_COL 9
void init(char showMap[MAX_ROW][MAX_COL], char mineMap[MAX_ROW][MAX_COL])
{
memset(showMap, '*', MAX_ROW * MAX_COL);
memset(mineMap, '0', MAX_ROW * MAX_COL);
//数组名相当于指针
//二维数组的每个元素都是在一个连续的内存空间上布局
/*for (int row = 0; row < MAX_ROW; row++)
{
for (int col = 0; col < MAX_COL; col++)
{
showMap[row][col] = '*';
}
}*/
srand((unsigned int)time(0));
int mineCount = 0;
while (mineCount<10)
{
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (mineMap[row][col] == '1')
{
continue;
}
mineMap[row][col] = '1';
mineCount++;
}
}
memset=>标准库函数,把一段内存上的每个字节都设置成一个具体的值
(要在连续内存空间上设置)
mem=>memory 内存
set=>设置,集合
memset(内存起始位置,具体填充值,内存长度)
2.打印地图
需要这个函数同时打印两张地图,取决于实参
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");
}
}
print(showMap);
print(mineMap);
3. 更新地图showMap
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; r <= 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;
}
ASCII值是48的字符为‘0’,只有C语言中可以进行这种转换。
4.合法判断
while (1)
{
//打印地图
print(showMap);
print(mineMap);
//玩家输入坐标
int row = 0;
int col = 0;
printf("请输入坐标:\n");
scanf("%d %d", &row, &col);
//合法性判定
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL)
{
printf("坐标错误\n");
continue;
}
if (showMap[row][col] != '*')
{
printf("已经翻开\n");
continue;
}
//判断是否踩雷
if (mineMap[row][col] == '1')
{
printf("您踩雷了\n");
break;
}
//更新shouMap,显示当前位置有几个地雷
update(showMap, mineMap, row, col);
}
四.完整代码
#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
void init(char showMap[MAX_ROW][MAX_COL], char mineMap[MAX_ROW][MAX_COL])
{
memset(showMap, '*', MAX_ROW * MAX_COL);
memset(mineMap, '0', MAX_ROW * MAX_COL);
//二维数组的每个元素都是在一个连续的内存空间上布局
/*for (int row = 0; row < MAX_ROW; row++)
{
for (int col = 0; col < MAX_COL; col++)
{
showMap[row][col] = '*';
}
}*/
srand((unsigned int)time(0));
int mineCount = 0;
while (mineCount<10)
{
int row = rand() % MAX_ROW;
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;
for (int r = row - 1; r <= row + 1; r++)
{
for (int c = col - 1; r <= col + 1; c++)
{
if (r < 0 || r >= MAX_ROW || c < 0 || c >= MAX_COL)
{
//此时超出棋盘范围,跳过
continue;
}
//不需要判断,直接进行下次循环
if (r == row && c == col)
{
continue;
}
}
}
showMap[row][col] = '0' + count;
}
int main()
{
char showMap[MAX_ROW][MAX_COL] = { 0 };
char mineMap[MAX_ROW][MAX_COL] = { 0 };
init(showMap, mineMap);
while (1)
{
//打印地图
print(showMap);
print(mineMap);
//玩家输入坐标
int row = 0;
int col = 0;
printf("请输入坐标:\n");
scanf("%d %d", &row, &col);
//合法性判定
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL)
{
printf("坐标错误\n");
continue;
}
if (showMap[row][col] != '*')
{
printf("已经翻开\n");
continue;
}
//判断是否踩雷
if (mineMap[row][col] == '1')
{
printf("您踩雷了\n");
break;
}
//更新shouMap,显示当前位置有几个地雷
update(showMap, mineMap, row, col);
}
system("pause");
return 0;
}