“纯C”实现——扫雷游戏(递归实现展开功能)
Posted 小明的c++笔记本
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“纯C”实现——扫雷游戏(递归实现展开功能)相关的知识,希望对你有一定的参考价值。
文章目录
📺游戏动画演示
游戏实现完成的模样:
🚀扫雷实现思路
实现扫雷游戏的前提是要知道:>扫雷游戏的玩法(会玩的跳过这步)
扫雷游戏也就是排雷,让玩家点一个坐标,然后显示该坐标周围八个格子有多少个雷
如图所示:
如果踩到雷了就游戏结束,如图
那如果把全部非雷的位置找了出来那么游戏就胜利!
那么知道了游戏的规则,我们就可以大概知道要实现什么功能了!
还是老规矩,玩之前是不是得要把一个游戏画面打印出来给玩家看着进行排雷,那么游戏没有开始的时候我们的游戏画面该是怎么样的呢,你可以要一些字符来填充,比如“#”,“+”等等,我这就用字符“ * ”表示还没被点的坐标
那打印字符前是需要一个数组存放数据,这样子的话二维数组的选择是无可厚非的了!
我们用“ * ”来初始化的数组是用来展示给玩家看的,那么我们是不是还需要一个二维数组,用来存放地雷数据呀!
因为开两个二维数组,这样子才不会混乱,一个用来展示给玩家看,可以理解成前端,一个是用来控制雷的信息,可以理解成后端。
那么下一步,就是怎样去布置雷呢?
记不记得我们之前实现的三子棋游戏,让电脑下棋的时候是不是用随机值进行下棋的,那我们布置雷不也是随机放的吗!
那简直不要太简单,直接让随机值去完成即可
那么最后一步,就是玩家一直输入坐标,然后显示该坐标的周围八个格子有多少个雷,就一直判断玩家是否踩雷了,直至游戏胜利了或者失败!
游戏的大概思路知道了!我们就开始层层解剖啦!
🚀棋盘实现
实现棋盘我们是不是说过要用二维数组来存放“ * ”表示没有被排过雷的初始状态。
那么二维数组的行列该怎么确定呢?
其实我们也不知道具体要多少,是根据玩家来确定的嘛,玩家想玩20*20,就打印20*20,玩家想玩简单一点的9*9,我们就打印9*9,所以是不是需要一个宏定义来设定行列的大小呢,这样的方便了后续想修改多少行就多少行,多少列就多少列,灵活性就更高了!
#define ROW 10 //实际游戏的行
#define COL 10 //实际游戏的列
#define EASY_COUNT 30 //要布置多少个雷的设置(游戏难度)
//为什么要这样定义,下面排雷的时候会讲,别急
#define ROWS ROW+2 //方便后台处理的行
#define COLS COL+2//放后台处理的行
那行列确定好了,是不是就需要初始化数组了,那需要把二维数组传给函数,比如我这里的show数组是展示给玩家看的数组,那是不是需要初始化成“ * ”,这个mine就是存放雷信息的,为了避免和show数组重复我们可以先初始化成字符’0’
//模拟一下调用函数的过程
char mine[ROWS][COLS] = 0 ;
char show[ROWS][COLS] = 0 ;
//初始化雷的棋盘
BoardInit(mine, ROWS, COLS, '0');
//初始化展现的棋盘
BoardInit(show, ROWS, COLS, '*');
//**************************************************//
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set)
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols;j++)
board[i][j] = set;
初始化完成后就需要把它打印出来给玩家看,所以还需要一个打印数组的函数,打印的方式可以任意,你喜欢以什么样的方式打印就用什么方式(怎么好看怎么来),我这里就用我上面演示的那样!
注意:我们那里mine数组的内容是不用打印的,打印的话就可以知道雷的信息(开挂专用!)
void BoardPrint(char board[ROWS][COLS], int row, int col)
int i, j;
printf("********扫雷游戏*********\\n");
for (i = 0; i <= col; i++)
printf("%d ", i);
printf("\\n");
for (i = 0; i <= col; i++)
printf("--");
printf("\\n");
for (i = 1; i <= row; i++)
if (i < 10)
printf("%d |", i);
else
printf("%d|", i);
for (j = 1; j <= col; j++)
printf("%c ", board[i][j]);
printf("\\n");
printf("********扫雷游戏*********\\n");
🚀布置雷实现
布置雷要用的就是随机数的获取,我们就保证获取的坐标在要展示二维数组的范围内即可,这里就给大家解释一下上面为什么要定义一个比游戏实现行列数多2行2列的原因,完全是为了我们在检测有多少个雷的时候,防止数组越界 |
所以我们是需要把雷放在中间要展示的区域,不要把雷放在边界的地方!!
而且我们的show数组,也就是展示给玩家看的数组也要定义多两行两列,因为这样就可以跟mine数组相对于,把玩家输入的坐标就可以直接进行判断对应位置是否有雷 前提是同样是把原来的行列打印出去给玩家看,比如玩家选择的是9*9的,我们后台就实现11*11的show,而打印就打印show中间9*9的格子 ,11*11只是为了和我们的mine数组的雷相对于
我们用字符’1’来表示是雷的标志,字符‘ 0 ’表示不是雷
void setmine(char board[ROWS][COLS], int row, int col)
//count为雷的数量
int count = EASY_COUNT;
while (count)
//确定坐标在合法范围内
int x = rand() % row + 1; //模row加一为了让它不要布置在边界的地方
int y = rand() % col + 1;
if (board[x][y] == '0')
//每布一个雷,就把count-1
count--;
board[x][y] = '1';
我们可以把存放雷信息的mine数组打印看一下:>
🚀玩家扫雷实现
把上面的工作做完了,就要进行最后一步,也是这个游戏最重要的一步,玩家输入坐标,然后根据坐标判断游戏的情况
不管怎么样,玩家输入坐标后第一件事就是判断坐标是否合法,非法的话提醒玩家重新输入坐标。
合法之后就要判断输入的坐标是否踩雷,为了就直接结算游戏,非雷就把该坐标的周围8个格子检查有多少个雷,把雷数赋值给show数组,提示给玩家看周围分布有几个雷!
然后最后一步就是判断游戏胜利的条件了,我们可以定义一个变量win,而且的值就等于要排雷的次数,比如你是99行列的游戏,雷的数量为20,99-20就是剩下你要排雷的次数
达了这个次数就说明已经把全部非雷的区域确定好,游戏就胜利!
不过要注意的是因为我们是采用char字符数组,所以我们虽然是把雷初始化成"1",但它是一个字符‘1’,而非雷的格子为字符‘0’,它们的本质是ascll码,字符‘0’的ascll码为48,字符‘1’就为49,所以我们只需要要周围8个格子的字符加起来,然后减去8*字符‘0’就可以了。
比如你如果周围只有一个雷,那就是7 * 48 +1 * 49- 8 * 48=1
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
//win为要胜利排雷的总次数 比如你是9*9行列的游戏,雷的数量为20,9*9-20就是剩下你要排雷的次数
int win = row*col- EASY_COUNT;
while (win)
printf("输入坐标:>");
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
if (show[x][y]!='*')
printf("坐标已被占用,请重新输入\\n");
else
if (mine[x][y] == '1')
printf("很遗憾,你被炸死了\\n");
//游戏结束前打印雷的布置位置给玩家看
BoardPrint(mine, ROW, COL);
break;
else
//没踩雷,就把win-1,直至win为0就胜利
win--;
//获取周围雷的个数
int count = get_mine_count(mine, x, y);//函数实现在下面
//加字符'0'是为了将数字变为字符表示
show[x][y] = count + '0';
BoardPrint(show, row, col);
else
printf("坐标非法,请重新输入\\n");
if(win==0)
printf("恭喜你,游戏胜利!\\n");
//获取坐标中心周围雷的个数
int get_mine_count(char mine[ROWS][COLS], int x, int y)
//检查坐标周围8个格子有多少个雷
return (mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0');
🚀带展开功能的扫雷
什么是带展开功能的扫雷呢,请看动画
就是一点就把所有为周围为零个雷的区域展开
最要思想就是下面的openshow函数实现的递归,如果对于坐标为零,就把改坐标该为显示‘ 0 ’,并就把周围8个坐标在传给openshow函数,非零就停止递归
int win = ROW * COL - EASY_COUNT;
//展开功能
void openshow(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
win--;
int count = get_mine_count(mine, x, y);
if (count == 0)
if (show[x][y] != '0')
show[x][y] = '0';
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
openshow(mine, show, x + i, y + j);
else
show[x][y] = count + '0';
return;
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
//win为要胜利排雷的总次数
while (win)
printf("输入坐标:>");
scanf("%d%d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
if (show[x][y] != '*')
printf("坐标已被占用,请重新输入\\n");
else
if (mine[x][y] == '1')
printf("很遗憾,你被炸死了\\n");
//游戏结束前打印雷的布置位置给玩家看
BoardPrint(mine, ROW, COL);
break;
else
openshow(mine, show, x, y);
BoardPrint(show, row, col);
else
printf("坐标非法,请重新输入\\n");
if (win == 0)
printf("恭喜你,游戏胜利!\\n");
🚀小结语
看到这个游戏的基础功能就已经完成了,但有一些比标记雷的位置,这个功能还没实现,感兴趣的小伙伴可以自行实现,不出意外的话,后续会更新 |
这次扫雷和上一期的三子棋游戏其实都是对二维数组的理解,然后加上一些C语言的基础语法加以组装的实现,你们有get到吗? |
下面还是老规矩,分享一下我的源代码给你们玩玩!!
🚗text.c文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
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 ;
//初始化雷的棋盘
BoardInit(mine, ROWS, COLS, '0');
//初始化展现的棋盘
BoardInit(show, ROWS, COLS, '*');
BoardPrint(show, ROW, COL);
//布雷
setmine(mine, ROW, COL);
//BoardPrint(mine, ROW, COL); //作弊开关
//排查雷
FindMine(mine, show, ROW, COL);
//扫雷开始
//FindMine(mine, show, ROW, COL);
int main()
system("color 2");//改变字体颜色
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文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 30
//初始化棋盘
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void BoardPrint(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
#include"game.h"
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set)
int i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols;j++)
board[i][j] = set;
void BoardPrint(char board[ROWS][COLS], int row, int col)
int i, j;
printf("********扫雷游戏*********\\n");
printf(" ");
for (i = 0; i <= col; i++)
printf扫雷C语言如何实现(含递归展开)
目录
返回该坐标周围一圈8个坐标的雷的个数count_mine()
判断棋盘上还有多少个“雷”count_show_mine()
扫雷介绍
扫雷游戏就是要把所有非地雷的格子揭开即胜利,踩到地雷格子就算失败。 游戏主区域由很多个方格组成, 使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字,方格中数字则表示其周围的8个方格隐藏了几颗雷。
在C语言中我们用输入坐标的方式代替鼠标点击。
本文未介绍功能:(不是不想介绍,只是博主还未掌握能力,主要还是因为懒)
- 交互难度选择功能
- 标记雷功能
- 标记雷后选择坐标展开功能
实现思路
首先我们使用三个文件包含整个程序
- Mine.h
- Mine.c
- test.c
Mine.h头文件包含代码实现所需所有头文件及全局变量
Mine.c源文件包含代码实现的主要函数
test.c源文件负责测试代码
实现流程
- 打印交互菜单
- 初始化棋盘
- 布置雷
- 扫雷(递归展开)
- 判断胜利
- 胜利游戏结束,否则循环第4步
在定义棋盘的二维数组时我们需要定义两个数组;一个数组mine用来放置雷的位置(不显示),另一个数组show用来展示棋面!
代码分解
-
棋盘定义
//全局变量行和列
#define ROW 3
#define COL 3
//避免数组越界,在原有棋盘的基础上周围多一行和列
#define ROWS ROW+2
#define COLS COL+2
-
交互菜单menu()
//交互菜单
void menu()
printf("-----------------------\\n");
printf("------ 【扫雷】 ------\\n");
printf("------ 1.开始 ------\\n");
printf("------ 0.退出 ------\\n");
printf("-----------------------\\n");
-
初始化棋盘init_board()
这里我们把show棋盘初始化为 '*'
把mine棋盘初始化为 '0'
//初始化棋盘
void init_board(char board[ROWS][COLS], int row, int col, char ch)
int i = 0;
int j = 0;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
board[i][j] = ch;
-
打印棋盘display()
//打印棋盘
void display(char show[ROWS][COLS], int row, int col)
int i = 0;
int 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 ", show[i][j]);
printf("\\n");
printf("\\n");
-
布置雷set_mine()
//雷的数量
#define COUNT 1
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
int count = COUNT;
while (count)
//获取随机数在棋盘上生成雷('1')
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
mine[x][y] = '1';
count--;
-
返回该坐标周围一圈8个坐标的雷的个数count_mine()
注意这里函数的返回类型是 static
//返回该坐标周围一圈雷的个数
static count_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';//ASCII值与数字字符相差'0'
-
递归展开super_open_mine()
递归展开条件:
- 该坐标处不是雷, != '1'
- 该坐标周围八个坐标没有雷,count = 0
- 该坐标没有被展开过,!= ' '
//递归展开
void super_open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
//获取该坐标周围八个坐标雷数
int count = count_mine(mine, x, y);
if (count == 0 && show[x][y] != ' ')
show[x][y] = ' ';
if (x - 1 >= 0 && x <= ROW && y >= 0 && y <= COL && show[x - 1][y] == '*')
super_open_mine(mine, show, x - 1, y);
if (x + 1 >= 0 && x + 1 <= ROW && y >= 0 && y <= COL && show[x + 1][y] == '*')
super_open_mine(mine, show, x + 1, y);
if (x >= 0 && x <= ROW && y - 1 >= 0 && y - 1 <= COL && show[x][y - 1] == '*')
super_open_mine(mine, show, x, y - 1);
if (x >= 0 && x <= ROW && y + 1 >= 0 && y + 1 <= COL && show[x][y + 1] == '*')
super_open_mine(mine, show, x, y + 1);
else
show[x][y] = count + '0';
-
排查雷sweep_mine()
//排查雷
int sweep_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
int count = 0;
printf("请输入扫雷坐标(行.列):>");
scanf("%d.%d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
if (mine[x][y] == '1')
return 1;
else
super_open_mine(mine, show, x, y);
display(show, ROW, COL);
return 0;
else
printf("输入坐标非法,请重新输入!\\a\\n\\n");
return 0;
-
判断棋盘上还有多少个“雷”count_show_mine()
//判断棋盘上还有多少个“雷”
int count_show_mine(char show[ROWS][COLS], int row, int col)
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
for (j = 1; j <=col; j++)
if (show[i][j] == '*')
count++;
return count;
-
游戏实现函数game()
//游戏实现函数
void game()
char mine[ROWS][COLS] = 0 ;
char show[ROWS][COLS] = 0 ;
init_board(mine, ROWS, COLS, '0');//mine初始化为'0'
init_board(show, ROWS, COLS, '*');//show初始化为'*'
set_mine(mine, ROW, COL);
//display(mine, ROW, COL);
display(show, ROW, COL);
while (1)
int ret = sweep_mine(mine, show, ROW, COL);
if (ret)
printf("\\n你被炸死了,游戏结束!\\n\\a");
display(mine, ROW, COL);
break;
int key = count_show_mine(show, ROW, COL);
if (key == COUNT)
printf("WIN!\\a\\n");
break;
-
测试函数test()
//测试函数
void test()
srand((unsigned int)time(NULL));
int choose = -1;
do
menu();
scanf("%d", &choose);
switch (choose)
case 1:
printf("\\n游戏开始:\\n");
game();
break;
case 0:
printf("游戏结束...\\n\\a");
break;
default:
printf("输入有误,请重新输入!\\n\\a");
break;
while (choose);
-
主调函数main()
//主调函数
int main(void)
test();
return 0;
代码总览
- Mine.h
#pragma once
#include <stdio.h>//printf(),scanf()函数头文件
#include <stdlib.h>//获取时间戳头文件
#include <time.h>//时间头文件
//全局变量行和列
#define ROW 3
#define COL 3
//避免数组越界,在原有棋盘的基础上周围多一行和列
#define ROWS ROW+2
#define COLS COL+2
//雷的数量
#define COUNT 1
//函数声明
void menu();
void init_board();
void display();
void set_mine();
int sweep_mine();
- Mine.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Mine.h"
//交互菜单
void menu()
printf("-----------------------\\n");
printf("------ 【扫雷】 ------\\n");
printf("------ 1.开始 ------\\n");
printf("------ 0.退出 ------\\n");
printf("-----------------------\\n");
//初始化棋盘
void init_board(char board[ROWS][COLS], int row, int col, char ch)
int i = 0;
int j = 0;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
board[i][j] = ch;
//打印棋盘
void display(char show[ROWS][COLS], int row, int col)
int i = 0;
int 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 ", show[i][j]);
printf("\\n");
printf("\\n");
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
int count = COUNT;
while (count)
//获取随机数在棋盘上生成雷('1')
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
mine[x][y] = '1';
count--;
//返回该坐标周围一圈雷的个数
static count_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';//ASCII值与数字字符相差'0'
//递归展开
void super_open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
int count = count_mine(mine, x, y);
if (count == 0 && show[x][y] != ' ')
show[x][y] = ' ';
if (x - 1 >= 0 && x <= ROW && y >= 0 && y <= COL && show[x - 1][y] == '*')
super_open_mine(mine, show, x - 1, y);
if (x + 1 >= 0 && x + 1 <= ROW && y >= 0 && y <= COL && show[x + 1][y] == '*')
super_open_mine(mine, show, x + 1, y);
if (x >= 0 && x <= ROW && y - 1 >= 0 && y - 1 <= COL && show[x][y - 1] == '*')
super_open_mine(mine, show, x, y - 1);
if (x >= 0 && x <= ROW && y + 1 >= 0 && y + 1 <= COL && show[x][y + 1] == '*')
super_open_mine(mine, show, x, y + 1);
else
show[x][y] = count + '0';
//排查雷
int sweep_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
int x = 0;
int y = 0;
int count = 0;
printf("请输入扫雷坐标(行.列):>");
scanf("%d.%d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
if (mine[x][y] == '1')
return 1;
else
super_open_mine(mine, show, x, y);
display(show, ROW, COL);
return 0;
else
printf("输入坐标非法,请重新输入!\\a\\n\\n");
return 0;
//判断棋盘上还有多少个“雷”
int count_show_mine(char show[ROWS][COLS], int row, int col)
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
for (j = 1; j <=col; j++)
if (show[i][j] == '*')
count++;
return count;
- test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Mine.h"
//游戏实现函数
void game()
char mine[ROWS][COLS] = 0 ;
char show[ROWS][COLS] = 0 ;
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
set_mine(mine, ROW, COL);
//display(mine, ROW, COL);
display(show, ROW, COL);
while (1)
int ret = sweep_mine(mine, show, ROW, COL);
if (ret)
printf("\\n你被炸死了,游戏结束!\\n\\a");
display(mine, ROW, COL);
break;
int key = count_show_mine(show, ROW, COL);
if (key == COUNT)
printf("WIN!\\a\\n");
break;
//测试函数
void test()
srand((unsigned int)time(NULL));
int choose = -1;
do
menu();
scanf("%d", &choose);
switch (choose)
case 1:
printf("\\n游戏开始:\\n");
game();
break;
case 0:
printf("游戏结束...\\n\\a");
break;
default:
printf("输入有误,请重新输入!\\n\\a");
break;
while (choose);
//主调函数
int main(void)
test();
return 0;
以上是关于“纯C”实现——扫雷游戏(递归实现展开功能)的主要内容,如果未能解决你的问题,请参考以下文章
扫雷游戏(C语言实现)初级版和优化版(增加了自动展开标记地雷功能,同时排除了第一次排到地雷的情况)