扫雷游戏介绍
格子里的数字表示周围雷的个数,目标是找出所有的雷
代码设计思路
功能需求
1.游戏首先需要打印菜单,让玩家进行自主选择
2.游戏默认为9*9的棋盘
3.雷的个数默认为10个
4.排查雷时,如果选择的坐标不是雷就显示周围八个格子中的雷的个数,是雷则游戏失败结束
棋盘设计
由上图可以直观看出我们需要的是正方形棋盘,因此我们可以使用二维数组来存储游戏相关数据,数组中以0代表不是雷,1代表是雷,然后我们还需要思考需要几个数组,如图:
如果我们只使用一个数组来进行雷的相关布置以及游戏展示的话,当图中箭头所指绿色的方块周围只有一个雷时,它将被改为1,此时难以区分1指的是雷还是周围雷的个数,导致信息混乱,所以我们考虑使用两个数组,一个用来存放雷相关的信息,一个用来展示给玩家使用
而对于数组大小:
由图可见,当需要排查的坐标在边界时,排查周边雷的个数时可能导致越界,为此我们可以考虑将二维数组的上下左右各扩充一格:
这样就不会导致数组越界访问了
而展示给用户时我们需要将数据隐藏起来,打印给用户的界面应该如下:
因此数组元素类型考虑使用char类型
综上 我们需要两个11 * 11的char 数组
//定义两个数组分别用来存放雷以及游戏中的展示
char mine[ROWS][COLS];//ROWS COLS为11
char show[ROWS][COLS];
文件的结构设计
为了方便数据保护以及代码模块实现,我们将代码分为三个文件
test.c//进行游戏逻辑的测试
game.h//游戏相关函数的声明
game.c//游戏相关函数的实现
游戏代码实现
//test.c文件代码
//1.初始化雷
//2.展示雷
//3.布置雷
//4.排查雷
#include"game.h"
//函数打印菜单界面
void Menu()
{
printf("**************************\n");
printf("****** 1. 开始游戏 *******\n");
printf("****** 0. 退出游戏 *******\n");
printf("**************************\n");
}
//函数实现扫雷游戏
void Game()
{
//定义两个数组分别用来存放雷以及游戏中的展示
char mine[ROWS][COLS];
char show[ROWS][COLS];
//对两个数组初始化
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//分别测试打印展示
//PrintBoard(mine, ROW, COL);
PrintBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
//布置完以后进行一次打印测试
//PrintBoard(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
//设置随机种子
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);
return 0;
}
//game.h文件代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//规定扫雷规模大小
#define ROW 9
#define COL 9
//规定存放雷的数组大小
#define ROWS (ROW + 2)
#define COLS (COL + 2)
//规定雷的个数
#define MINE_NUMBER 10
//初始化函数声明
void InitBoard(char arr[ROWS][COLS], int row, int col, char set);
//打印函数声明
void PrintBoard(char arr[ROWS][COLS], int row, int col);
//布置雷函数声明
void SetMine(char arr[ROWS][COLS], int row, int col);
//排查雷函数声明
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//某个格子周围雷数统计函数声明
int SurroundingMine(char arr[ROWS][COLS], int x, int y);
//game.c文件代码
#include"game.h"
//初始化函数的实现
void InitBoard(char arr[ROWS][COLS], int row, int col, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = set;
}
}
}
//打印函数实现
void PrintBoard(char arr[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 ", arr[i][j]);
}
printf("\n");
}
}
//布置雷函数实现
void SetMine(char arr[ROWS][COLS], int row, int col)
{
int count = MINE_NUMBER;
while (count)
{
int x = ((rand() % row) + 1);//产生1-9的随机行号
int y = ((rand() % col) + 1);//产生1-9的随机列号
//判断该处是否已经被设置雷
if (arr[x][y] == '0')
{
//printf("x=%d,y=%d\n", x, y);
arr[x][y] = '1';
//PrintBoard(arr, ROW, COL);
count--;
}
}
}
某个格子周围雷数统计函数实现
int SurroundingMine(char arr[ROWS][COLS], int x, int y)
{
return (arr[x - 1][y - 1] +
arr[x - 1][y] +
arr[x - 1][y + 1] +
arr[x][y - 1] +
arr[x][y + 1] +
arr[x + 1][y - 1] +
arr[x + 1][y] +
arr[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 count = 0;//用来记录已经排查到的雷的个数
while (count < ROW * COL - MINE_NUMBER)
{
printf("请输入需要排查的坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("踩到地雷,游戏失败!\n");
PrintBoard(mine, ROW, COL);
return;
}
else//判断周围8个格子中有几个地雷,并将数字展示出来
{
//首先需要判断该坐标是否已经被排查过
if (show[x][y] != '*')
{
printf("该坐标已经排查!\n");
}
else
{
int num = SurroundingMine(mine, x, y);
show[x][y] = num + '0';
count++;
//排查一次以后打印出来
PrintBoard(show, ROW, COL);
}
}
}
else
{
printf("该坐标非法,请重新输入!\n");
}
}
printf("恭喜成功排查所有雷!\n");
}