使用工具:Visual Studio 2022
前言:对扫雷的数据结构分析略讲,并主要讲解具体代码和代码的逻辑
1. 分析和设计
1.1 扫雷游戏的功能和玩法
1.1.1 功能
- 使⽤控制台实现经典的扫雷游戏
- 游戏可以通过菜单实现继续玩或者退出游戏
- 扫雷的棋盘是9*9的格⼦
- 默认随机布置有10个地雷
- 可以排查地雷
- 扩展:有难度选择:简单 99 棋盘、10个雷,中等 1616棋盘、40个雷,困难 30*16棋盘,99个雷;可以标记地雷;排查位置不是雷,周围也没有雷,可以展开周围的⼀⽚。
1.1.2 玩法
- 输入坐标,如果位置不是雷,就显⽰周围有⼏个雷,如果位置是雷,就炸死游戏结束
- 把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束
- 扩展:输入0 0进行标记
1.2 游戏界面



1.3 数据结构的分析
扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要⼀定的数据结构来存储这些信息。
如果创建⼀个99的数组来存放信息,在最外围的一圈进行地雷排查时会出现越界的情况,所以创建1111的数组进行信息存储。
创建两个字符数组,一个数组(mine)存储雷和非雷的信息:雷用'1'
非雷用'0'
,另⼀个数组(show)存放排查出的雷的信息,show数组开始时初始化为字符 ‘*’。
1.4 设计三个⽂件
1.4.1 test.c部分(游戏的测试逻辑)
- 创建main函数= =>创建test函数(开始与退出游戏)= =>创建game函数(实现游戏)+扩展:创建select函数(选择游戏难度)
- game函数:InitBoard函数(初始化棋盘)= =>DisplayBoard函数(打印棋盘) = =>SetMine函数(布置地雷)= =>FindMine函数(排查地雷)
1.4.2 game.c部分(游戏中函数的实现)
- 创建InitBoard函数= =>创建DisplayBoard 函数= =>创建SetMine函数= =>创建FindMine函数= =>{创建GetMineCount函数(获取地雷个数)}+扩展:创建MarkMine函数(标记地雷)= =>{创建Mark函数(进行标记)= =>创建Unmark函数(取消标记)} = =>创建SpreadMine函数(排查周围,不是雷,进行扩展)= =>创建WinMine函数(游戏胜利所需要的值)
1.4.3 game.h部分(游戏需要的数据类型和函数声明)
- 定义 EASY_COUNT(地雷个数)、定义ROW(棋盘行数)、定义COL(棋盘列数)、定义ROWS(实际行数)、定义COLS(实际列数)、在game.c创建函数的声明+扩展:分别定义三种难度的地雷个数、棋盘行列数、实际行列数
2. 具体代码讲解
将所有库函数引用的头文件放入game.h文件中,直接在test.c和game.c文件中引用:#include “game.h”
2.1 test.c部分
2.1.1 main函数
int main()
{
test();//在主函数外另封装一个函数进行具体的游戏测试
return 0;
}
2.1.2 test函数
在控制台打印菜单,选择是否开始游戏,用switch语句进行菜单选择,do-while循环让游戏可以重复游玩
void menu1()
{
printf("********************\n");
printf("***** 1.paly *****\n");
printf("***** 0.exit *****\n");
printf("********************\n");
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu1();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
2.1.3 game函数
四个变量ROW、COL、ROWS、COLS在game.h文件中被定义,剩余函数在game.h文件中声明,在game.c文件中定义
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);
//DisplayBoard(mine, ROW, COL);
//布置地雷
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查显示地雷的信息
FindMine(mine,show, ROW, COL);
}
2.2 game.c部分
2.2.1 InitBoard函数
对数组mine和数组show进行初始化,mine全部初始化为'0'
,show全部初始化为'*'
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;
}
}
}
2.2.2 DisplayBoard函数
对数组内容进行打印,以9*9棋盘的形式打印
void DisplayBoard(char Board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("\n-------------扫雷-------------\n");
for (i = 0; i <= col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%2c ", Board[i][j]);
}
printf("\n");
}
}
2.2.3 SetMine函数
⽣成a~b的随机数: a + rand()%(b-a+1)
变量EASY_COUNT在game.h文件中被定义,为简单模式下地雷个数
用Board[x][y] = '1’表示埋下地雷
void SetMine(char Board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (Board[x][y] != '1')
{
Board[x][y] = '1';
count--;
}
}
}
2.2.4 FindMine函数
要对输入坐标进行判断,因为输入的坐标可能会超出棋盘的界限;而在界限内的坐标如果踩雷(当输入坐标所得mine[x][y] == '1’时),没有踩雷则对周围八个坐标中雷的个数进行统计,并让show[x][y]等于所统计个数,使用GetMineCount函数统计
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 > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
DisplayBoard(mine, row, col);
printf("游戏失败\n");
break;
}
else
{
int count = GetMineCount(mine, x, y);//该位置不是雷,就统计这个坐标周围有⼏个雷
show[x][y] = count + '0';
DisplayBoard(show, row, col);
win++;
}
}
else
printf("输入错误,请重新输入\n");
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,成功了\n");
DisplayBoard(mine, row, col);
}
}
2.2.5GetMineCount函数
此函数应该放在FindMine函数前,它只在game.c文件中被FindMine函数引用
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
int i = 0;
int j = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
count += (mine[x + i][y + j] - '0');//数组mine是字符型数组,返回的ASCII值减去0的ASCII值为字符本身所表示的数字
}
}
return count;
}
2.3 game.h部分
变量的定义和函数的声明
#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);
3. 扩展:清屏、难度选择、标记地雷、周围无雷展开
3.1 清屏
包含头文件 #include <stdlib.h>
所用库函数system( );
system("cls");
因为使用后会直接清屏,所以需要一些技巧
- 在test.c文件中的test函数
- 在game.c文件中的FindMine函数
清屏代码的具体位置可以在末尾的成品展示中查找
3.2 难度选择
位置:test.c文件
所用函数:Select函数、menu2函数、WinMine函数、FindMine函数(改)
因为新的难度需要更多的行数和地雷实现,所以行数、地雷个数要增加定义,而二维数组,因为定义数组设置大小只能用常量,所以为了避免越界,我们将棋盘大小设为三种难度中棋盘最大的那一个
#define EASY_COUNT 10
#define EASY_ROW 9
#define EASY_COL 9
#define EASY_ROWS EASY_ROW+2
#define EASY_COLS EASY_COL+2
#define MID_COUNT 40
#define MID_ROW 16
#define MID_COL 16
#define MID_ROWS MID_ROW+2
#define MID_COLS MID_COL+2
#define DIF_COUNT 99
#define DIF_ROW 16
#define DIF_COL 30
#define DIF_ROWS DIF_ROW+2
#define DIF_COLS DIF_COL+2
之前数组的全部名称都要由
char name[ROWS][COLS]
变为char name[DIF_ROWS][DIF_COLS]
3.2.1 menu2函数
void menu2()
{
printf("********************\n");
printf("***** 1.简单 *****\n");
printf("***** 2.中等 *****\n");
printf("***** 3.困难 *****\n");
printf("********************\n");
}
3.2.2 select函数
void select()
{
int input = 0;
int i = 0;
do
{
menu2();
printf("请选择>:");
scanf("%d", &input);
system("cls");
switch (input)
{
case 1:
ROW = EASY_ROW;
COL = EASY_COL;
ROWS = EASY_ROWS;
COLS = EASY_COLS;
count = EASY_COUNT;
i = 0;
break;
case 2:
ROW = MID_ROW;
COL = MID_COL;
ROWS = MID_ROWS;
COLS = MID_COLS;
count = MID_COUNT;
i = 0;
break;
case 3:
ROW = DIF_ROW;
COL = DIF_COL;
ROWS = DIF_ROWS;
COLS = DIF_COLS;
count = DIF_COUNT;
i = 0;
break;
default:
printf("选择错误,请重新选择\n");
i = 1;
break;
}
} while (i);
}
3.2.3 WinMine函数
WinMine函数返回的值是row * col - count,其中row、col、count分别为不同难度中的行、列、地雷个数;同时WinMine函数应该在FindMine函数前运行
int WinMine(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int i = 0;
int j = 0;
int win = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if(show[i][j] !='*'&& show[i][j] != '!')
win++;
}
}
return win;
}
3.2.4 FindMine函数
void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int count)
{
int x = 0;
int y = 0;
int i = 0;
while (WinMine(show,row,col) < row * col - count)
{
printf("请输入坐标>:");
scanf("%d %d", &x, &y);
system("cls");
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
DisplayBoard(show, row, col);
printf("请输入坐标>:%d %d", x, y);
DisplayBoard(mine, row, col);
printf("游戏失败\n");
printf("输入1继续>");
scanf("%d", &i);
system("cls");
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
//DisplayBoard(mine, row, col);
DisplayBoard(show, row, col);
}
}
else
{
DisplayBoard(show, row, col);
printf("输入错误,请重新输入\n");
}
}
if (WinMine(show, row, col) == row * col - count)
{
printf("恭喜你,成功了\n");
DisplayBoard(mine, row, col);
printf("输入1继续>");
scanf("%d", &i);
system("cls");
}
}
3.3 标记地雷
位置:game.c文件
所用函数:MarkMine函数、Mark函数、Unmark函数、FindMine函数(2改)
3.3.1 FindMine函数
在FindMine函数运行时(即排查地雷输入坐标时),输入0 0,进入标记地雷的函数
void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int count)
{
int x = 0;
int y = 0;
int i = 0;
while (WinMine(show,row,col) < row * col - count)
{
printf("输入0 0进行标记\n");
printf("请输入坐标>:");
scanf("%d %d", &x, &y);
system("cls");
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
DisplayBoard(show, row, col);
printf("请输入坐标>:%d %d", x, y);
DisplayBoard(mine, row, col);
printf("游戏失败\n");
printf("输入1继续>");
scanf("%d", &i);
system("cls");
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
//DisplayBoard(mine, row, col);
DisplayBoard(show, row, col);
}
}
else if (x == 0 && y == 0)
{
MarkMine(mine, show, row, col);
}
else
{
DisplayBoard(show, row, col);
printf("输入错误,请重新输入\n");
}
}
if (WinMine(show, row, col) == row * col - count)
{
printf("恭喜你,成功了\n");
DisplayBoard(mine, row, col);
printf("输入1继续>");
scanf("%d", &i);
system("cls");
}
}
3.3.2 MarkMine函数
在选择1时进入Mark函数,选择2时进入Unmark函数,所以这两个函数要在MarkMine函数前
void MarkMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int input = 0;
int i = 0;
do
{
DisplayBoard(show, row, col);
printf("1.进行标记\n2.取消标记\n0.退出标记\n");
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
Mark(show, row, col);
break;
case 2:
Unmark(show, row, col);
break;
case 0:
system("cls");
DisplayBoard(show, row, col);
break;
default:
printf("选择错误,请重新选择\n");
printf("输入1继续>");
scanf("%d", &i);
system("cls");
break;
}
} while (input);
}
3.3.3 Mark函数
要对已标记,已排查的坐标进行说明,同时要有退出的功能
void Mark(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int x = 0;
int y = 0;
int i = 0;
while(1)
{
system("cls");
DisplayBoard(show, row, col);
printf("正在进行标记,输入0 0退出\n");
printf("请输入要标记的坐标>:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
system("cls");
break;
}
else if (show[x][y] == '!')
{
printf("已标记,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
else
{
printf("已排查,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
}
else if (x == 0 && y == 0)
{
system("cls");
break;
}
else
printf("输入错误,请重新输入\n");
}
}
3.3.4 Unmark函数
要对未标记,已排查的坐标进行说明,同时要有退出的功能,不然在游戏还未进行标记时,会出现无法退出的情况
void Unmark(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int x = 0;
int y = 0;
int i = 0;
while (1)
{
system("cls");
DisplayBoard(show, row, col);
printf("正在取消标记,输入0 0退出\n");
printf("请输入要取消标记的坐标>:");
scanf("%d %d", &x, &y);
if(x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
system("cls");
break;
}
else if (show[x][y] == '*')
{
printf("未标记,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
else
{
printf("已排查,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
}
else if (x == 0 && y == 0)
{
system("cls");
break;
}
else
printf("输入错误,请重新输入\n");
}
}
3.4 周围无雷展开
位置:game.c文件
所用函数:SpreadMine函数、FindMine函数(2改)
会用到递推函数
3.4.1 FindMine函数
3.4.2 SpreadMine函数
注意:这里的show[m][n] == '*'
不能改写为show[m][n] != '0'
,因为我们创建的二维数组行列数比实际棋盘的行列数均多出两行,而多出的两行初始化均为字符0
void SpreadMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int x, int y)
{
if (GetMineCount(mine, x - 1, y) == 0 && show[x - 1][y] == '*')
{
show[x - 1][y] = '0';
//x = x - 1;
SpreadMine(mine, show, row, col, x - 1, y);
}
if (GetMineCount(mine, x + 1, y) == 0 && show[x + 1][y] == '*')
{
show[x + 1][y] = '0';
//x = x + 1;
SpreadMine(mine, show, row, col, x + 1, y);
}
if (GetMineCount(mine, x, y - 1) == 0 && show[x][y - 1] == '*')
{
show[x ][y - 1] = '0';
//y = y - 1;
SpreadMine(mine, show, row, col, x, y - 1);
}
if (GetMineCount(mine, x, y + 1) == 0 && show[x][y + 1] == '*')
{
show[x][y + 1] = '0';
//y = y + 1;
SpreadMine(mine, show, row, col, x, y + 1);
}
}
4. 最终成品展示
4.1 游戏界面
4.2 test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int ROW = 0;
int COL = 0;
int ROWS = 0;
int COLS = 0;
int count = 0;
//菜单1
void menu1()
{
printf("********************\n");
printf("***** 1.paly *****\n");
printf("***** 0.exit *****\n");
printf("********************\n");
}
//菜单2
void menu2()
{
printf("********************\n");
printf("***** 1.简单 *****\n");
printf("***** 2.中等 *****\n");
printf("***** 3.困难 *****\n");
printf("********************\n");
}
//难度选择
void select()
{
int input = 0;
int i = 0;
do
{
menu2();
printf("请选择>:");
scanf("%d", &input);
system("cls");
switch (input)
{
case 1:
ROW = EASY_ROW;
COL = EASY_COL;
ROWS = EASY_ROWS;
COLS = EASY_COLS;
count = EASY_COUNT;
i = 0;
break;
case 2:
ROW = MID_ROW;
COL = MID_COL;
ROWS = MID_ROWS;
COLS = MID_COLS;
count = MID_COUNT;
i = 0;
break;
case 3:
ROW = DIF_ROW;
COL = DIF_COL;
ROWS = DIF_ROWS;
COLS = DIF_COLS;
count = DIF_COUNT;
i = 0;
break;
default:
printf("选择错误,请重新选择\n");
i = 1;
break;
}
} while (i);
}
//游戏运行
void game()
{
select();
char mine[DIF_ROWS][DIF_COLS];//存放布置好的雷
char show[DIF_ROWS][DIF_COLS];//存放排查出的雷的信息
//初始化面板(棋盘)
//初始化数组mine中全为字符0
//初始化数组show中全为字符*
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//展示面板(打印棋盘)
DisplayBoard(show, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//布置地雷
SetMine(mine, ROW, COL, count);
//DisplayBoard(show, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//排查显示地雷的信息
FindMine(mine,show, ROW, COL, count);
}
//选择开始
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu1();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
system("cls");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
4.3 game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化面板
void InitBoard(char Board[DIF_ROWS][DIF_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[DIF_ROWS][DIF_COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("\n-------------扫雷-------------\n");
for (i = 0; i <= col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%2c ", Board[i][j]);
}
printf("\n");
}
}
//布置地雷
void SetMine(char Board[DIF_ROWS][DIF_COLS], int row, int col, int count)
{
int x = 0;
int y = 0;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (Board[x][y] != '1')
{
Board[x][y] = '1';
count--;
}
}
}
//得到输入坐标周围地雷个数
int GetMineCount(char mine[DIF_ROWS][DIF_COLS], int x, int y)
{
int i = 0;
int j = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
count += (mine[x + i][y + j] - '0');
}
}
return count;
}
//排查周围,不是雷,进行扩展
void SpreadMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int x, int y)
{
if (GetMineCount(mine, x - 1, y) == 0 && show[x - 1][y] == '*')
{
show[x - 1][y] = '0';
//x = x - 1;
SpreadMine(mine, show, row, col, x - 1, y);
}
if (GetMineCount(mine, x + 1, y) == 0 && show[x + 1][y] == '*')
{
show[x + 1][y] = '0';
//x = x + 1;
SpreadMine(mine, show, row, col, x + 1, y);
}
if (GetMineCount(mine, x, y - 1) == 0 && show[x][y - 1] == '*')
{
show[x ][y - 1] = '0';
//y = y - 1;
SpreadMine(mine, show, row, col, x, y - 1);
}
if (GetMineCount(mine, x, y + 1) == 0 && show[x][y + 1] == '*')
{
show[x][y + 1] = '0';
//y = y + 1;
SpreadMine(mine, show, row, col, x, y + 1);
}
}
//进行标记
void Mark(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int x = 0;
int y = 0;
int i = 0;
while(1)
{
system("cls");
DisplayBoard(show, row, col);
printf("正在进行标记,输入0 0退出\n");
printf("请输入要标记的坐标>:");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
system("cls");
break;
}
else if (show[x][y] == '!')
{
printf("已标记,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
else
{
printf("已排查,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
}
else if (x == 0 && y == 0)
{
system("cls");
break;
}
else
printf("输入错误,请重新输入\n");
}
}
//取消标记
void Unmark(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int x = 0;
int y = 0;
int i = 0;
while (1)
{
system("cls");
DisplayBoard(show, row, col);
printf("正在取消标记,输入0 0退出\n");
printf("请输入要取消标记的坐标>:");
scanf("%d %d", &x, &y);
if(x > 0 && x <= row && y > 0 && y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
system("cls");
break;
}
else if (show[x][y] == '*')
{
printf("未标记,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
else
{
printf("已排查,请重新输入\n");
printf("输入1确定>");
scanf("%d", &i);
system("cls");
}
}
else if (x == 0 && y == 0)
{
system("cls");
break;
}
else
printf("输入错误,请重新输入\n");
}
}
//标记地雷
void MarkMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int input = 0;
int i = 0;
do
{
DisplayBoard(show, row, col);
printf("1.进行标记\n2.取消标记\n0.退出标记\n");
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
Mark(show, row, col);
break;
case 2:
Unmark(show, row, col);
break;
case 0:
system("cls");
DisplayBoard(show, row, col);
break;
default:
printf("选择错误,请重新选择\n");
printf("输入1继续>");
scanf("%d", &i);
system("cls");
break;
}
} while (input);
}
//游戏胜利所需要的值
int WinMine(char show[DIF_ROWS][DIF_COLS], int row, int col)
{
int i = 0;
int j = 0;
int win = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if(show[i][j] !='*'&& show[i][j] != '!')
win++;
}
}
return win;
}
//排查显示地雷的信息
void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int count)
{
int x = 0;
int y = 0;
int i = 0;
while (WinMine(show,row,col) < row * col - count)
{
printf("输入0 0进行标记\n");
printf("请输入坐标>:");
scanf("%d %d", &x, &y);
system("cls");
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
DisplayBoard(show, row, col);
printf("请输入坐标>:%d %d", x, y);
DisplayBoard(mine, row, col);
printf("游戏失败\n");
printf("输入1继续>");
scanf("%d", &i);
system("cls");
break;
}
else
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
SpreadMine(mine, show, row, col, x, y);
//DisplayBoard(mine, row, col);
DisplayBoard(show, row, col);
}
}
else if (x == 0 && y == 0)
{
MarkMine(mine, show, row, col);
}
else
{
DisplayBoard(show, row, col);
printf("输入错误,请重新输入\n");
}
}
if (WinMine(show, row, col) == row * col - count)
{
printf("恭喜你,成功了\n");
DisplayBoard(mine, row, col);
printf("输入1继续>");
scanf("%d", &i);
system("cls");
}
}
4.4 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
#define EASY_COUNT 10
#define EASY_ROW 9
#define EASY_COL 9
#define EASY_ROWS EASY_ROW+2
#define EASY_COLS EASY_COL+2
#define MID_COUNT 40
#define MID_ROW 16
#define MID_COL 16
#define MID_ROWS MID_ROW+2
#define MID_COLS MID_COL+2
#define DIF_COUNT 99
#define DIF_ROW 16
#define DIF_COL 30
#define DIF_ROWS DIF_ROW+2
#define DIF_COLS DIF_COL+2
void InitBoard(char Board[DIF_ROWS][DIF_COLS], int rows, int cols, char set);
void DisplayBoard(char Board[DIF_ROWS][DIF_COLS], int row, int col);
void SetMine(char Board[DIF_ROWS][DIF_COLS], int row, int col, int count);
void FindMine(char mine[DIF_ROWS][DIF_COLS], char show[DIF_ROWS][DIF_COLS], int row, int col, int count);