扫雷?拿来吧你(递归展开+坐标标记)

简介: 扫雷?拿来吧你(递归展开+坐标标记)

前言

如果聊起有什么让大家印象深刻的童年游戏,那么《 扫雷 》的地位应该是不可撼动的。这个搭载在 Windows 系统菜单里的小游戏在当时可谓大红大紫,算的上是我们实打实的童年回忆了。

  • 或许我们在一遍又一遍玩扫雷的同时,都会回忆起小学夏天的那节电脑课上,穿着鞋套,在硕大的白色电脑上,瞒着老师偷偷玩一把扫雷的简单快乐吧~
  • 如今我们用经典的C语言复刻扫雷,还能否勾起你对童年的回忆呢?

一、游戏规则

扫雷游戏规则:玩家需要尽快找出雷区中的所有不是地雷的方块,而不许踩到地雷。


众所周知。点开其中一个小方格之后,数字是几,就说明它周围的八个方位就有几个雷

比如下图中就表示红框内存在2个雷

二、效果演示

🍑1、初级版

🍑2、升级版

三、游戏设计思路

在介绍过三子棋的实现后,要实现扫雷是不是就会感觉就简单一些了呢?其实二者有很多相似的地方,扫雷游戏的实现主要是对下面两个模块的实现:


一、游戏交互界面

  1. 创建游戏菜单
  2. 创建游戏逻辑主体

二、扫雷游戏实现

  1. 创建扫雷棋盘
  2. 初始化扫雷棋盘
  3. 布置雷
  4. 打印扫雷棋盘
  5. 用户排查雷
  6. 判断输赢

这里准备了一张图,便大家更直观的理清游戏实现原理与游戏实现的逻辑 :

四、游戏交互界面

🍑1、创建游戏菜单

📝代码展示:

void menu()
{
  printf("* * * * * * * * * * * * * * * * * *\n");
  printf("* * * * * * 1.扫雷游戏  * * * * * *\n");
  printf("* * * * * * 0.退出游戏  * * * * * *\n");
  printf("* * * * * * * * * * * * * * * * * *\n");
}

🍑2、创建游戏逻辑主体

📝代码展示:

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;
}

1、srand((unsigned int)time(NULL)) 表示随机数生成函数通过时间戳生成随机数,为下面的布置雷做准备。

2、do-while() 因为游戏至少可以进入一次,至少让玩家输入一次玩或不玩,所以用do-while()循环–循环代码至少执行一次。

观察上面这段代码,其中我们使用了一个game()函数来实现扫雷游戏,但是这个函数还未定义,下面将实现对game()函数的定义。

五、扫雷游戏实现(初级版)

🍑1、游戏框架搭建

📝代码展示

void game()
{
  //创建雷盘:
  char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
  char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

  //初始化雷盘:
  InitBoard(mine, ROWS, COLS,'0');
  InitBoard(show, ROWS, COLS,'*');

  //布置雷:
  SetMine(mine, ROW, COL);

  //向玩家打印扫雷棋盘:
  DisPlayBoard(show, ROW, COL);

  //排查雷并判断输赢
  FindMine(mine,show,ROW,COL);
}

🍑2、游戏内函数实现

🌳(1)创建雷盘

📝代码展示:

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

问题1:这里为什么创建两个棋盘?

假设这里只创建一个棋盘,那么这一个棋盘上就要放置3种信息。分别为雷、非雷、排查出周围雷的信息。虽然这种方法也没太大的问题,但是一个棋盘上放置3种信息会给之后打印棋盘时造成麻烦,不易打印。

所以我们创建两个二维数组,一个数组存放布置好雷的信息;另一个数组存放排查出的雷的信息。这样创建不仅方便之后的打印,也可以将问题分解从而让问题层次更加分明,解题思路更加清晰。

问题2:为什么使用宏常量?

其实这个问题在前面的三子棋游戏中也有介绍。在这里使用宏常量主要是为了方便程序的修改,增加了程序的可塑性。

就像我这里通过宏定义将行列通设定为9,也就是9*9的雷盘。假如后面我想要玩12*12的雷盘,我只需要将宏定义中的9改为12即可,这样就省去了在程序中大量修改的精力,使代码可塑性更高。

问题3:为什么二位数组的行列选择ROWS、COLS而不是ROW、COL

通过扫雷游戏规则我们已知,如果一个位置不是雷,我们要排查它周围8个坐标是不是雷,对于9*9的棋盘,当在排查边界时可能会出现越界的情况。因此我们创建11*11的棋盘这样就很好的解决了这个问题。

那么怎么让用户看到9*9的棋盘呀?其实用户看到的只是程序员想让你看到的,后面我们只需要打印11*11中的9*9就ok了。

🌳(2)初始化雷盘

📝代码展示:

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;
    }
  }
}

这里就是简单使用两个for循环遍历整个棋盘从而实现棋盘初始化,这里就不在过多赘述。


补充:这里是将mine[ROWS][COLS]中的内容初始化为‘0’show[ROWS][COLS]中内容初始化为‘*’

效果展示:

🌳(3)打印扫雷棋盘

📝代码展示:

//打印棋盘
DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
  int i = 1;
  int j = 1;
  printf("------扫雷游戏------\n");
  for (i = 1; i <= row; i++)
  {

    for (j = 1; j <= col; j++)
    {
      printf("%c ",board[i][j]);
    }
    printf("\n");
  }
}

效果展示:

简单观察不难发现,上述棋盘使用户查找坐标时变得困难,不易于用户输入排雷坐标 ,因此我们可以通过下面简单优化,为棋盘标号👇:

📝优化后代码:

//打印棋盘
DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
  int i = 1;
  int j = 1;
  printf("------扫雷游戏------\n");
  //打印列号
  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");
  }
}

优化后效果展示:

这样以来雷盘坐标是不是就变得更加直观清楚了 !😊

🌳(4)布置雷

📝代码展示:

#define EASY_COUNT 10
void SetMine(char mine[ROWS][COLS], int row, int col)
{
  //布置10个雷
  int count = EASY_COUNT;
  while (count)
  {
    //生产随机的下标
    int x = rand()%row+1;
    int y = rand()%col+1;
    if (mine[x][y] == '0')
    {
      mine[x][y] = '1';
      count--;
    }
  }
}

1、这里使用宏定义布置雷的个数,便于修改,增加代码的可塑性。

2、rand()函数与srand((unsigned int)time(NULL))函数配合生成随机数,rand()%row+1rand()%col+1保证了生成了横纵坐标在合理范围之内。

补充:这里规定雷为'1'

🌳(5)扫雷并判断输赢

1.排雷原理

在扫雷的时候我们还需要定义一个函数,用来返回排查坐标周围地雷的个数。

下面用一张图来解析排查原理:

假设排查坐标为(x,y),我们可以如右图,依次返回其周围8个坐标下对应的值,由于我们上面规定,雷为‘1’,非雷为‘0’,则字符相加减对应ASCLL码值相加减。

例如:(x,y)周围有1个雷,则7*'0'+'1'-8*'0'即表示‘1’的ASCLL码值减‘0’的ASCLL码值,返回整数1,即周围有1个雷

方案一:逐个遍历

📝代码展示:

//返回排查坐标周围雷的数量
int get_mine_count(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';
}

方案二:循环遍历

📝代码展示:

int get_mine_count2(char mine[ROWS][COLS], int x, int y)
{
  int i = 0;
  int count = 0;
  for (i = -1; i <= 1; i++)
  {
    int j = 0;
    for (j = -1; j <= 1; j++)
    {
      if (mine[x + i][y + j] == '1')
        count++;
    }
  }
  return count;
}

2.扫雷流程+判断输赢

设计思路:

1.输入排查的坐标

2.判断坐标合法性

(1)合法 -程序执行下一步

(2)不合法 -重新输入

3.检查坐标处是不是雷

(1)是雷 - 很遗憾炸死了 - 游戏结束

(2)不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续

程序执行过程如下图:

📝代码展示:

注意:row*col- EASY_COUNT表示所有非雷数量,所有非雷坐标全部排查则游戏正常结束,玩家胜利。

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{   //思路:
  //1. 输入排查的坐标
    //2、判断坐标合法性
  //3. 检查坐标处是不是雷
     // (1) 是雷   - 很遗憾炸死了 - 游戏结束
     // (2) 不是雷  - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续

  int x = 0;
  int y = 0;
  int win = 0;

  while (win<row*col- EASY_COUNT)
  {
    printf("请输入要排查的坐标:>");
    scanf("%d%d", &x, &y);//x--(1,9)  y--(1,9)

    //判断坐标的合法性
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
      if (mine[x][y] == '1')
      {
        printf("很遗憾,你被炸死了\n");
        DisplayBoard(mine, row, col);
        break;
      }
      else
      {
        //不是雷情况下,统计x,y坐标周围有几个雷
        int count = get_mine_count(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);//向玩家展示一下布雷棋盘
  }
}

到这里初级扫雷游戏就搭建完成了,我们来试玩一把:

六、游戏缺陷

1.上述代码每次排雷只展开一个坐标,排雷效率较低.

2.没有标记功能,缺少趣味性.

七、扫雷升级版

显然,初级扫雷虽然能实现扫雷游戏的基本功能,但是缺少展开功能和标记功能,扫雷仿佛没了灵魂,那么我们应该如何画龙点睛,让扫雷如虎添翼,更上一层呢?下面我们就针对游戏缺陷进一步改进!

🍑1、展开功能

如果没有思路,我们可以先观察一下游戏中的展开过程:

聪明的你们一定会发现:当排雷坐标周围处地雷数量为0时,棋盘会向周围展开,并且将周围雷的数量显示到屏幕上,直到坐标周围地雷数不为0

显然,这是一个递归问题,当排雷坐标周围地雷数为0,棋盘会继续遍历周围个坐标,直到坐标周围出现雷,递归停止。

📝代码展示:

static void Digit_boom(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y, int row, int col, int* win)
{
  if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法性
  {
    int ret = Around_num2(mine, x, y);//接受坐标周围雷的数量

    if (ret == 0)//递归条件--周围雷数为0
    {
      (*win)++;//每排查一个坐标,排查次数加1,为判断输赢做准备
      show[x][y] = '0';//显示周围雷数
      int i = 0;
      int j = 0;
      //用两个循环遍历周围8个坐标
      for (i = -1; i <= 1; i++)
      {
        for (j = -1; j <= 1; j++)
        {
          if (show[x + i][y + j] == '*')//递归的坐标必须是未排查过的坐标,
                                                  //防止死递归
          {
            Digit_boom(show, mine, x + i, y + j, row, col,win);
          }
        }
      }
    }
    else
    {    //条件不满足退出递归
      
      (*win)++;//排查坐标,次数加1
      show[x][y] = ret + '0';//显示周围雷数
    }
  }

}

1、递归参数win这里为传址调用,作用为计数器,统计排雷次数,方便之后判断输赢。

2、注意此递归有两个条件:

条件一:if (ret == 0)为大前提,只有周围坐标为0才可能进入递归

条件二:if(show[x+i][y+j]=='*') ,为小前提,进入递归的坐标必须是未排查过的坐标,否则可能重复排查坐标,出现死递归

效果展示:

🍑2、标记功能

标记功能,作用是把玩家确定的雷坐标标记出来,或者是把不确定的雷坐标标记出来。它的作用只是做记号,相比于递归展开,标记功能显然更容易实现。


由于是做标记,我们需要再引入一个标志符号,为了不与雷盘符号*冲突,易于玩家区分,这里使用#作为标记符号。

📝代码展示:(标记雷)

//标记雷
static void flag(char show[ROWS][COLS], int row, int col)
{

  while (1)
  {
    int x = 0;
    int y = 0;
    printf("请输入标记坐标(输入:0 0退出):>");
    scanf("%d %d",&x,&y);
    if (x >= 1 && x <= row && y >= 0 && y <= col)
    {
      if (show[x][y] != '#')
      {
        show[x][y] = '#';
        break;
      }
      else
      {
          printf("该坐标已经标记,请重新选择\n");
      }

    }
    else
    {
      printf("坐标越界,请重新输入\n");
    }
    if (x == y && x == 0)
      break;
  }
}

📝代码展示:(取消标记)

static void cancel_flag(char show[ROWS][COLS], int row, int col)
{
  while (1)
  {
    int x = 0;
    int y = 0;
    printf("请输入取消标记坐标(输入:0 0退出):>");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 0 && y <= col)
    {
      if (show[x][y] == '#')//比较用双等号!!!
      {
        show[x][y] = '*';
        break;
      }
      else
      {
        printf("该坐标还未标记,请重新选择\n");
      }
    }
    else
    {
      printf("坐标越界,请重新输入\n");
    }
    if (x == y && x == 0)
      break;
  }
}

效果展示 :

🍑3、搭建游戏菜单

当我们添加了这些功能后,为了能够有更好的游戏体验我们可以为这些功能添加一个菜单,如下图:

📝代码展示:

static void menu2()
{
  printf("┌-----------------------------┐\n"); 
  printf("├**********1.排雷*************┤\n");
  printf("├**********2.标记*************┤\n");
  printf("├**********3.取消标记*********┤\n");
  printf("└-----------------------------┘\n");

}

🍑4、排雷函数封装

📝在实现了上述功能后,我们可以重新封装排雷函数FindMine()

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int choice = -1;
  int x = 0;
  int y = 0;
  int win = 0;
  while (win < col * row - Easy_Count)
  {
    menu2();
    printf("请选择:>");
    scanf("%d", &choice);
        //标记
    if (2 == choice)
    {
      flag(show, ROW, COL);
      DisplayBoard(show, ROW, COL);

    }
        //取消标记
    else if (3 == choice)
    {
      cancel_flag(show, ROW, COL);
      DisplayBoard(show, ROW, COL);
    }
        //排雷
    else if(1==choice)
    {
      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 if(show[x][y]=='*')
        {
          Digit_boom(show, mine, x, y, row, col, &win);
          DisplayBoard(show, row, col);
        }
        else
        {
          printf("该坐标已排查,请重新选择\n");
        }

      }
      else
      {
        printf("输入坐标错误,请重新输入\n");
      }
    }
    else
    {
      printf("选择错误,请重新选择\n");
    }
  }
  if (win == col * row - Easy_Count)//非雷坐标全部排查完毕
  {
    DisplayBoard(mine, ROW, COL);
    printf("恭喜你,你赢了咯!\n");
  }
  

}

最终效果展示:

为了让扫雷界面更简洁,在每次打印雷盘前增加了清屏操作:system("cls");

七、完整代码

🍑1、游戏交互主体-test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//游戏菜单
menu()
{
  printf("* * * * * * * * * * * * * * * * * *\n");
  printf("* * * * * * 1.扫雷游戏  * * * * * *\n");
  printf("* * * * * * 0.退出游戏  * * * * * *\n");
  printf("* * * * * * * * * * * * * * * * * *\n");
}
//扫雷游戏
void game()
{
  //创建扫雷棋盘
  char mine[ROWS][COLS];
  char show[ROWS][COLS];
  //初始化扫雷棋盘
  Init(mine, ROWS, COLS, '0');
  Init(show, ROWS, COLS, '*');
  //布置雷
  SetMine(mine, ROW, COL);
  //打印扫雷棋盘
  DisplayBoard(show, 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;
}

🍑2、声明部分-game.h

#pragma once
//包含头文件
#include <stdio.h>
#include <time.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
//宏定义
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Easy_Count 10
//初始化雷盘
void Init(char board[ROWS][COLS],int rows,int cols,char x);
//打印雷盘
void DisplayBoard(char board[ROWS][COLS],int row,int col);
//布置雷
void SetMine(char mine[ROWS][COLS],int row,int col);
//排雷并判断输赢
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);

🍑3、函数定义-game.c

 #define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化雷盘
void Init(char board[ROWS][COLS], int rows, int cols, char x)
{
  int i = 0;
  for (i=0;i<rows;i++)
  {
    int j = 0;
    for (j=0;j<cols;j++)
    {
      board[i][j] = x;
    }
  }
}
//打印雷盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
  system("cls");
  printf("-----扫雷游戏-----\n");
  int i = 0;
  int j = 0;
  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 ",board[i][j]);
    }
    printf("\n");
  }
}
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col)
{
  int count = Easy_Count;
  while (count)
  {
    int i = rand() % row + 1;
    int j = rand() % col + 1;
    if (mine[i][j] == '0')
    {
      mine[i][j] = '1';
      count--;
    }

  }
}
//显示周围雷数
//方案一
static int Around_num1(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][y - 1] +
    mine[x][y + 1] + mine[x + 1][y] + 
    mine[x + 1][y - 1] + mine[x + 1][y + 1]-8*'0';
}
//方案二
static int Around_num2(char mine[ROWS][COLS], int x, int y)
{
  int i = 0;
  int count = 0;
  for (i = -1; i <= 1; i++)
  {
    int j = 0;
    for (j = -1; j <= 1; j++)
    {
      if (mine[x + i][y + j] == '1')
        count++;
    }
  }
  return count;
}
//标记雷
static void flag(char show[ROWS][COLS], int row, int col)
{

  while (1)
  {
    int x = 0;
    int y = 0;
    printf("请输入标记坐标(输入:0 0退出):>");
    scanf("%d %d",&x,&y);
    if (x >= 1 && x <= row && y >= 0 && y <= col)
    {
      if (show[x][y] != '#')
      {
        show[x][y] = '#';
        break;
      }
      else
      {
          printf("该坐标已经标记,请重新选择\n");
      }

    }
    else
    {
      printf("坐标越界,请重新输入\n");
    }
    if (x == y && x == 0)
      break;
  }
}
//取消标记
static void cancel_flag(char show[ROWS][COLS], int row, int col)
{
  while (1)
  {
    int x = 0;
    int y = 0;
    printf("请输入取消标记坐标(输入:0 0退出):>");
    scanf("%d %d", &x, &y);
    if (x >= 1 && x <= row && y >= 0 && y <= col)
    {
      if (show[x][y] == '#')//比较用双等号!!!
      {
        show[x][y] = '*';
        break;
      }
      else
      {
        printf("该坐标还未标记,请重新选择\n");
      }
    }
    else
    {
      printf("坐标越界,请重新输入\n");
    }
    if (x == y && x == 0)
      break;
  }
}
//如果排雷坐标周围雷数为零,递归展开
static void Digit_boom(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y, int row, int col, int* win)
{
  if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法性
  {
    int ret = Around_num2(mine, x, y);//接受坐标周围雷的数量

    if (ret == 0)//递归条件--周围雷数为0
    {
      (*win)++;//每排查一个坐标,排查次数加1,为判断输赢做准备
      show[x][y] = '0';
      int i = 0;
      int j = 0;
      //用两个循环遍历周围8个坐标
      for (i = -1; i <= 1; i++)
      {
        for (j = -1; j <= 1; j++)
        {
          if (show[x + i][y + j] == '*')//递归的坐标必须是未排查过的坐标,防止死递归
          {
            Digit_boom(show, mine, x + i, y + j, row, col,win);
          }
        }
      }
    }
    else
    {
      //条件不满足退出递归
      (*win)++;//排查坐标,次数加1
      show[x][y] = ret + '0';
    }
  }

}
//扫雷菜单
static void menu2()
{
  printf("┌-----------------------------┐\n"); 
  printf("├**********1.排雷*************┤\n");
  printf("├**********2.标记*************┤\n");
  printf("├**********3.取消标记*********┤\n");
  printf("└-----------------------------┘\n");

}
//扫雷并判断输赢

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
  int choice = -1;
  int x = 0;
  int y = 0;
  int win = 0;
  while (win < col * row - Easy_Count)
  {
    menu2();
    printf("请选择:>");
    scanf("%d", &choice);
    if (2 == choice)
    {
      flag(show, ROW, COL);
      DisplayBoard(show, ROW, COL);

    }
    else if (3 == choice)
    {
      cancel_flag(show, ROW, COL);
      DisplayBoard(show, ROW, COL);
    }
    else if(1==choice)
    {
      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 if(show[x][y]=='*')
        {
          Digit_boom(show, mine, x, y, row, col, &win);
          DisplayBoard(show, row, col);
        }
        else
        {
          printf("该坐标已排查,请重新选择\n");
        }

      }
      else
      {
        printf("输入坐标错误,请重新输入\n");
      }
    }
    else
    {
      printf("选择错误,请重新选择\n");
    }
  }
  if (win == col * row - Easy_Count)
  {
    DisplayBoard(mine, ROW, COL);
    printf("恭喜你,你赢了咯!\n");
  }
}

总结

由于作者水平有限,如笔下有误,敬请留言。

如果本文对您有所帮助,请给博主点赞👍关注🙏哦,笔者会持续更新干货教程,期待与君共勉!


相关文章
|
5月前
|
C语言
C语言学习记录——鹏哥扫雷项目实现及递归展开、记录雷坐标
C语言学习记录——鹏哥扫雷项目实现及递归展开、记录雷坐标
65 0
|
5月前
|
C语言
杨辉三角(代码直接呈现,便于理解)
杨辉三角(代码直接呈现,便于理解)
38 0
|
C语言 Windows
C语言实现扫雷(自动排查),递归展开
C语言实现扫雷(自动排查),递归展开
84 0
|
6月前
|
机器学习/深度学习 算法 C++
【算法 | 实验6-1】n*n的网格,从左上角开始到右下角结束遍历所有的方块仅一次,总共有多少种不同的遍历路径
前言 思路介绍中省略了关于如何进行回溯搜索的细节,而主要讨论回溯中所使用的剪枝策略。
140 0
|
11月前
|
机器学习/深度学习 算法 测试技术
C++前缀和算法的应用:用地毯覆盖后的最少白色砖块 原理源码测试用例
C++前缀和算法的应用:用地毯覆盖后的最少白色砖块 原理源码测试用例
|
12月前
|
C语言
【C语言】小游戏-扫雷(清屏+递归展开+标记)
【C语言】小游戏-扫雷(清屏+递归展开+标记)
51 0
|
C语言
扫雷小游戏 递归展开
扫雷小游戏 递归展开
|
C语言
C语言:扫雷小游戏(空白展开和标记雷点)
C语言:扫雷小游戏(空白展开和标记雷点)
射线法——判断一个点是否在多边形内部(适用于凸多边形和凹多边形)【关键原理解释+文字伪代码】
射线法——判断一个点是否在多边形内部(适用于凸多边形和凹多边形)【关键原理解释+文字伪代码】
669 0
|
JavaScript API 容器
彻底弄懂元素样式、位置、大小相关计算
在我们日常开发中偶尔会碰到获取元素样式、设置某元素样式、计算元素位置、计算滚动距离等需求。但是js中关于元素位置、样式、大小的api种类繁多,稍不留神就会搞不清楚。今天笔者就带你彻底弄清楚,让你在这类问题上不再迷茫。
215 0