目录
一、游戏介绍
《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
二、游戏步骤
1. 程序开始执行是玩家首先选择是否开始游戏。选 1开始游戏;选0则退出游戏。
2. 显示棋盘后玩家开始进行选择,输出1则开始排雷;输入2则可以标记自己认为是雷的位置;
输出3则可以取消自己标记的位置。
3. 当所以的雷排查出后游戏胜利。
三、游戏功能介绍
(1)初始化雷盘
初始化雷盘需要构建两个数组,一个数组(mine数组)里面放的是存雷的,用于实现各种功能的,另一个数组(show数组)是给玩家操作的,看不到雷的位置。
//Initboard(mine, ROWS, COLS, '0');
//Initboard(show, ROWS, COLS, '*');
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0, j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
(2)打印雷盘
一般扫雷是9*9的雷盘,如果想要打印更大雷盘,可以直接在头文件里改行和列的大小。
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10//雷的数量
打印雷盘的函数:
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0, j = 0;
//打印列号
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
实现效果如下:
(3)随机布雷
在雷盘中要实现随机布雷,需要用到srand()和rand()函数 ,用‘0’字符表示无雷区域,用字符‘1’表示‘雷’。
void SetMine(char board[ROWS][COLS], int row, int col)
{
int x = 0, y = 0;
int count = EASY_COUNT;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
(4)玩家排雷
玩家根据show数组所展现的雷盘开始排雷,选择不是自己认为不是雷的地方进行排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int ch = 0;
size_t flag_count = 0;
int win = 0;
int fch = 1;//标记玩家是否为第一次排雷
while (1)
{
menu1();
scanf("%d", &ch);
if (ch == 1)
{
int x = 0, y = 0;
printf("请开始排雷:>");
scanf("%d%d", &x, &y);
//判断坐标合法
if (x <= row && x > 0 && y > 0 && y <= col)
{
//判断玩家是否是第一次排雷
if (fch == 1 && mine[x][y] == '1')
{
ChangePlace(mine, row, col, x, y);
fch++;
}
else
{
if (mine[x][y] == '1')
{
printf("游戏结束\n");
printf("恭喜你,踩到雷了\n");
DisplayBoard(mine, row, col);
break;
}
else
{
broad(mine, show, x, y);
DisplayBoard(show, row, col);
}
fch++;
}
}
else
{
printf("输入坐标不合法,请重新输入\n");
}
}
else if (ch == 2)
{
printf("请开始标记雷:>\n");
flag_count = Flagmine(show, row, col, flag_count);
DisplayBoard(show, row, col);
}
else if (ch == 3)
{
printf("请选择要取消标记的位置:>\n");
flag_count = Cancelflag(show, row, col, flag_count);
DisplayBoard(show, row, col);
}
else if ((ch != 1) ||( ch != 2) ||( ch != 3))
{
printf("输入错误,请重新输入:>\n");
DisplayBoard(show, row, col);
}
//遍历show地图(改进)
win = Travel(show, row, col);
if (win == EASY_COUNT)
break;
}
//判断游戏胜利的标准(改进)
if (win == EASY_COUNT)
{
printf("恭喜你,游戏胜利\n");
}
}
(5)统计所选周围八个位置雷的位置
计算所选周围八个位置中雷的个数,并打印到所选的位置上
int get_mine(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';
}
(6)递归拓展已选位置周围的区域
以递归的方式拓展排雷
void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
return;
if (show[x][y] != '*')
{
return;
}
int count = get_mine(mine, x, y);
if (count > 0)
{
show[x][y] = count + '0';
return;
}
else if (count == 0)
{
show[x][y] = '0';
broad(mine, show, x - 1, y);
broad(mine, show, x - 1, y - 1);
broad(mine, show, x, y - 1);
broad(mine, show, x + 1, y - 1);
broad(mine, show, x + 1, y);
broad(mine, show, x + 1, y + 1);
broad(mine, show, x, y + 1);
broad(mine, show, x - 1, y + 1);
}
}
如果游戏只能一个一个输入,效率低,而且玩家游玩的体验也会很差,故用递归的方式判断所选位置周围八个位置,把没有雷的位置自动排查,只把可能有雷的位置展示给玩家。
(7)标记雷和取消标记
玩家若根据数字判断某一位置是雷, 则通过菜单二的提示选择“2”进入标记模式,选择玩家想要标记的位置,输入坐标,完成标记,标记的位置会显示“ !”,表明标记成功。若玩家想要取消某一已被标记的位置,则在菜单二的界面选择“3“,输入坐标,取消标记。
int Flagmine(char show[ROWS][COLS], int row, int col, size_t flag)
{
int x = 0, y = 0;
if (flag == EASY_COUNT)
{
printf("标记的雷数和实际存在的雷数相等,无法再标记\n");
return;
}
printf("请输入你要标记位置的坐标:>\n");
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判断该坐标是否已经被确认不为雷
if (show[x][y] == '*')
{
show[x][y] = '!';
flag++;
}
else
{
printf("该位置不可能是雷,请重新输入\n");
}
}
else
{
printf("该坐标不合法,请重新输入:>\n");
}
return flag;
}
//取消标记
int Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count)
{
int x = 0;
int y = 0;
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x > 0 && x <= row && y > 0 && y <= col)
{
//判断该位置是否被标记过
if (show[x][y] == '!')
{
show[x][y] = '*';
flag_count--;
}
else
printf("该位置未被标记过,无需取消标记\n");
}
else
{
printf("该坐标不合法,请重新输入:>\n");
}
return flag_count;
}
效果如下:
综上,此程序基本实现扫雷的基本功能,感兴趣的小伙伴们可自己模仿写一下。
源代码链接:扫雷源代码