文章目录
-
前言
-
一、扫雷大致思路
-
二、主要步骤的实现
-
1.创建数组和数组的初始化
-
2.打印棋盘
-
3.布雷💣
-
4.排查雷💣和是否排雷成功
-
-
三、完整代码
前言
运用数组实现经典的简易版扫雷游戏
一、扫雷大致思路
这里以9*9的扫雷为例:
创建两个9*9的二维数组,在其中一个数组中随机去布置雷,另一个数组是存放排查雷。
通过输入坐标,如果该坐标不是雷,会对该坐标周围8个位置进行排雷,该坐标会显示周围8个位置雷的个数。
通过不断的输入坐标进行排雷直至排除所有雷,你将会取的胜利。
如果你在排雷过程中,输入坐标是雷的位置,你将会被告知:你被炸死了。
二、具体实现步骤
1.创建数组
我们实现的是9*9的扫雷游戏,如果创建9*9的数组的话,那么我们在排雷的时候输入的坐标是数据最边上的坐标就会出现下面这张图的数组越界
为了防止再排雷过程中数组越界我们应该创建11*11的数组
但是我们布置雷的时候只在圈起来这9*9的格子里面防雷和排雷
创建数组
mine 数组 是布雷数组
show 数组 是排雷数组
因为我们将布雷数组初始化的是字符’0’,排雷数组初始化的是字符’*’
所以我们创建的数组的类型就是char类型
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
用#define来定义常量是为了我们可以之间通过修改ROW和COL来直接修改我们的棋盘大小
数组的初始化,代码如下:
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
InitBoard是我们初始化数组的函数
为了实现一个InitBoard函数初始化两个数组,因为两个数组大小都是一样的,所以我们在数组传参的时候,多传入一个参数,这个多传入的参数就是我们对mine 和 show 数组初始化的内容
set就是接受字符参数的形参
InitBoard函数的调用以及传参
代码如下:
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
2.打印棋盘
DisplayBoar是我们打印棋盘的函数
我们打印的时候只需要打印9*9的数组,所以参数传得是ROW ,COL
但是数组在内存中是连续的,所以我们传参的时候只能将整个数组传过去,也就是数组名
代码如下:
DisplayBoar(show, ROW, COL);
DisplayBoard函数的实现
代码如下:
void DisplayBoard(char show[ROWS][COLS], int row, int col)
{
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 ", show[i][j]);
}
printf("\n");
}
}
因为我们打印的是9*9的是从1行1列开始打印的,所以坐标就应该是从1 1开始
3.布置雷💣
布置雷的时候我们要注意的是只需在9*9的数组中布置雷
我们的雷用’1’表示
布置雷我们通过rand函数产生随机数产生坐标来布置雷
代码如下:
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';//放置雷
count--;
}
}
}
4.排查雷💣
我们通过输入坐标来排查该位置的雷
输入坐标我们要判断输入坐标是否合法,输入坐标是否已经被排查过,如果排查过了则重新输入
并且每次成功排完一个雷,打印棋盘,而且还要判断是否排雷成功
如果你输入的坐标是雷的话,你被炸死结束游戏,并打印排雷棋盘
我们排查的位置就是出x,y所在格子的其他8个格子
EASY_COUNT 就是累的个数
代码如下:
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x-1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;//不是雷的格子数
while (win < (row * col - EASY_COUNT))
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);//输入所要排查的目标
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断该坐标是否被排查过
if (show[x][y] != '*')
{
printf("该坐标已被排查过\n");
}
//判断你输入的坐标是否是雷
if (mine[x][y] == '1')
{
printf("很遗憾,你踩雷了,被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int n = get_mine_count(mine, ROW, COL);
show[x][y] = n + '0';
DisplayBoard(show, x, y);
win++;
}
}
else
{
printf("输入坐标非法\n");
}
if (win == (row * col - EASY_COUNT))
{
printf("恭喜你,排雷成功\n");
break;
}
}
}
get_mine_count函数的设计的原因
所要排雷的位置
红色框位置就是我们需要排查的位置,黑色框就是我们输入坐标的位置
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x-1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}
排雷是对我们输入坐标周围的8个位置雷的个数的统计,并且在该坐标显示这8个位置出现雷的个数,这里也就是统计该坐标8个位置出现 字符’1’的个数,这里就是将出现的字符’1’加起来,所以我们需要减去8个字符’0’就是数字,所以返回的就是雷的个数n。
(雷的个数是数字n)
这个位置是因为我们排雷数组是字符数组,所以我们存放的时候就需要将雷的个数加上字符’0’,就将雷的个数n转化为了字符n。
我们判断是否排雷成功是看没有雷的位置显示了多少个,在这里也就是win的值,每次成功就会win+1
四、完整代码
代码分为2个源文件,1个头文件
源文件: test.c 测试
game.c 具体函数的实现
头文件 game.h test.c所用到的自定义函数的声明
test.c 测试
代码如下:
void menu()
{
printf("**************************************\n");
printf("*********** 1.play ***********\n");
printf("*********** 0.exit ***********\n");
printf("**************************************\n");
}
void game()
{
//创建数组
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化数组
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印排雷棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);,查看布雷位置,测试代码是否有bug
//排雷
FindMine(mine, show, ROW, COL);
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();//打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
geme.h 函数的声明
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS ROW+2
#define EASY_COUNT 10//雷数
//初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoar(char show[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS] ,int row, int col);
geme.c 函数的实现
代码如下:
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印排雷棋盘
void DisplayBoard(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------ 扫雷 ------\n");
//控制列号
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 ", show[i][j]);
}
printf("\n");
}
printf("------ 扫雷 -------\n");
}
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';//放置雷
count--;
}
}
}
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x-1][y] + mine[x - 1][y - 1] + mine[x][y - 1] +
mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] +
mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}
//排查雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;//不是雷的格子数
while (win < (row * col - EASY_COUNT))
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);//输入所要排查的目标
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断该坐标是否被排查过
if (show[x][y] != '*')
{
printf("该坐标已被排查过\n");
}
//判断你输入的坐标是否是雷
if (mine[x][y] == '1')
{
printf("很遗憾,你踩雷了,被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
int n = get_mine_count(mine, ROW, COL);
show[x][y] = n + '0';
DisplayBoard(show, x, y);
win++;
}
}
else
{
printf("输入坐标非法\n");
}
if (win == (row * col - EASY_COUNT))
{
printf("恭喜你,排雷成功\n");
break;
}
}
}