扫雷游戏的分析与设计
扫雷游戏功能介绍
- 使⽤控制台实现经典的扫雷游戏
- 通过菜单实现继续玩或者退出游戏
- 棋盘9*9,并在第一行和第一列显示出坐标以便查找
- 默认随机布置10个雷
- 通过键盘输入排查(x,y)是否是雷时
- 若(x,y)不是雷,就在(x,y)这个位置上显示周围有几个雷,继续通过键盘输入排雷
- 若(x,y)是雷,就显示被雷炸死,游戏结束,返回菜单选择是否继续游戏
- 若排查出所有不是雷的位置,显示排雷成功,游戏结束,返回菜单选择是否继续游戏
扫雷游戏分析与设计
- 设置棋盘:在扫雷游戏实现的过程中设置两个棋盘mine和show(用自定义函数InitBoard初始化两个棋盘)
2. 游戏过程中能看见的棋盘:一个是玩家游戏时看到的show棋盘(用自定义函数DisplayBoard将其打印出来)棋盘9*9,并在第一行和第一列显示出坐标以便查找
3. 游戏过程中看不见的棋盘:而另一个棋盘mine用来设置随机的十个雷(使用srand和rand两个库函数得出十个随机坐标设置雷,有雷的坐标在mine棋盘上赋值为‘1’,而没有雷的坐标上仍然是之前初始化的字符‘0’)
4. 游戏过程中未踩到雷时:访问周围八个坐标,统计这八个坐标雷的个数,由于越界时无法统计,故可以将棋盘周围加上一圈以便统计雷的个数。用mine存放布置好的雷的信息,用show存放排查出的雷的信息,也就是说把雷布置到mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期排查参考。另外同时为了保持神秘,show数组开始时初始化为字符’ * ‘,为了保持两个数组的类型⼀致,可以使⽤同⼀套函数处理,mine数组最开始也初始化为字符’0’,布置雷改成’1’
5. 游戏胜利或失败:显示出mine棋盘的实际情况(用自定义函数DisplayBoard将其打印出来)
6. 继续选择:回到菜单栏(也就是menu函数打印菜单键盘输入0或1选择是否继续游戏)
文件结构设计
- test.c 写游戏的测试逻辑
- game.c 写游戏中函数的实现
- game.h 写游戏需要的数据类型和函数声明等
代码的实现
game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EASY_COUNT 10
#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);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘( 数组名 行数 列数 填满数组的符号)
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
printf("-----扫雷游戏------\n");
int i = 0;
for (i = 0; i <= col; i++)//打印横着的坐标
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印竖着的坐标
int j = 0;
for (j = 1; j <= col; j++)//打印棋盘(二维数组)内容
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
//生成十个随机坐标布置雷
int count = EASY_COUNT;
while (count)//当count变成1说明十个雷已经全部布置完毕,循环结束
{
int x = rand() % row + 1;
int y = rand() % col + 1;//xy均大于等于1小于等于row或col
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//排雷过程
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int win = 0;
int x = 0;
int y = 0;
while (win < row * col - EASY_COUNT)//当棋盘上的雷全部未触发时循环结束
{
printf("请输入你要排查的坐标(注意这里横纵坐标都不能超过九):\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')//排到了雷
{
printf("很遗憾,你输了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
//输入的坐标没有雷,统计这个坐标周围有几个雷
int count = GetMineCount(mine, x, y);//坐标周围雷的个数
show[x][y] = count + '0';//加上0的ASCLL码,使show[x][y]这个字符ASCLL码为周围雷的个数的ASCLL码
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐标输入错误,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜过关,排雷成功!\n");
DisplayBoard(mine, ROW, COL);
}
}
//计算输入坐标周围雷的个数
//统计mine棋盘里输入的周围八个位置字符(1或0)与0的差值之和
//计算字符加减相当于计算它们的ASCLL码‘1’-‘0’=1,那么坐标周围八个位置字符与0的差值之和就为这个坐标附近的雷的个数
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x - 1][y + 1] + mine[x + 1][y] + mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x][y + 1] +mine[x][y - 1] - 8 * '0');
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void mune()
{
printf("*************************\n");
printf("******** 菜单 ********\n");
printf("******** 1.play ********\n");
printf("******** 0.exit ********\n");
printf("*************************\n");
}
void game()
{
char mine[ROWS][COLS];//存放布置好的雷
char show[ROWS][COLS];//存放排查出的信息
//初始化棋盘
//mine数组最开始全都是‘0’
//show数组最开始全都是‘*’
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//1.布置雷
SetMine(mine, ROW, COL);
//2.排查雷
FindMine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//设置随机种子
do
{
mune();//打印菜单
printf("请输入0或1选择是否游戏");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("游戏关闭\n");
break;
default:
printf("输入错误,请重新输入0或1选择是否开始游戏~\n");
break;
}
} while (input);
return 0;
}
扫雷游戏的拓展
- 游戏难度选择
- 简单9 * 9 棋盘,10雷
- 中等16*16 棋盘,40雷
- 困难30*16 棋盘,99雷
- 如果排查位置不是雷,周围也没有雷,可以展开周围的⼀⽚
- 标记雷,方便查找
- 加上排雷时间显示