【C语言】扫雷(递归展开 + 标记功能)

简介: 【C语言】扫雷(递归展开 + 标记功能)

1. 前言


扫雷,相信大家并不陌生,这是一款充斥着童年回忆的经典益智游戏。它能锻炼我们的思维,完成游戏也可以获得巨大的成就感。


本篇博客将采用C语言来模拟实现简单的扫雷游戏,以纪念我心目中的怀旧游戏No.1!


20220712134743.png



2. 整体思路



扫雷游戏棋盘大小:9 * 9


扫雷,不仅需要自动布置雷,而且需要输入坐标进行雷的排查,排查后需要在排查点展示周围八个点雷的个数。


所以我们需要用二维数组来表示扫雷的棋盘,但仅仅定义一个棋盘,那么在一个棋盘中需要表示的要素太多,且在排查雷时难度过大。


所以我们不妨换一种思路,使用两个棋盘,棋盘一用来放置雷,棋盘二用来存放排查后的数据。

棋盘分工:


   棋盘一:非雷用0表示,雷用1表示,此棋盘不暴露,仅仅用来布置雷而已。

   棋盘二:排查位置周围雷数用数字表示,未排查部分均用*表示,此棋盘需要在每次排查后展示。

示意图:

5813b4d51a2862376f494cee0862a9dc.png

但是进行排查时,对于边界部分。对周围元素进行访问时,如果大小定为9 * 9会出现数组访问越界的情况,所以我们将行和列的大小调整为11 * 11,最后打印时打印中间区域即可。

示意图:

99d138bdc34057b22304669738de150c.png


3. 游戏分工


该项目分为三个文件:

  1. test.c:游戏的逻辑
  2. game.h:函数声明,符号的定义
  3. game.c:游戏的实现

其中game.h,game.c为游戏模块,test.c为测试区域



4. 游戏菜单


依然是大家熟悉的菜单界面。

游戏开始前,需要有菜单来供玩家选择进入游戏,游戏至少进行一次,因此使用do...while循环。

对应代码:

void menu()
{
  printf("**********************************\n");
  printf("************* 1.play *************\n");
  printf("************* 0.exit *************\n");
  printf("**********************************\n");
}
int main()
{
  int input = 0;
  do
  {
    menu();
    printf("请选择:>");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("扫雷\n");
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("选择错误,请重新选择\n");
      break;
    }
  }while(input);
}


运行结果:

14ad2ba784debbd9e6b70505ecce2b59.png



5. 游戏功能



友情提示:

   以下模块均用于实现游戏功能,对应的功能均在test.c的game()函数中调用、game.h中进行声明和相关常量的定义,函数功能在game.c中实现。

   在.c文件中均需引自定义的头文件#include"game.h"。

   对于函数的声明我会省略,以下模块展示的内容主要为在game.c文件中实现的游戏功能。


5.1 前提准备


扫雷棋盘打印大小为 9 * 9,但在排查雷时,数组容易越界,为避免越界,我们将每个边界周围加上一行或一列,数组大小定义为11 * 11,打印时输出9 * 9即可:

#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW + 2 //11 * 11
#define COLS COL + 2



5.2 棋盘的初始化


  • 布置雷的棋盘的初始化:将元素都初始化为0
  • 排查雷的棋盘的初始化:将元素都初始化为*

思路:由于初始化的元素不同,所以在传参时可以把想初始化的元素传过去,在函数用字符类型进行接收。


test.c文件中的准备:

void game()
{
  //布置雷的棋盘
  char mine[ROWS][COLS] = { 0 };
  //排查雷的棋盘
  char show[ROWS][COLS] = { 0 };
  //初始化棋盘
  init_board(mine, ROWS, COLS, '0');//雷盘初始化为0
  init_board(show, ROWS, COLS, '*');//展示盘初始化为*
}

对应代码:

void init_board(char arr[ROWS][COLS], int rows, int cols, char set)
{
  int i = 0;
  for (i = 0; i < rows; i++)
  {
    int j = 0;
    for (j = 0; j < cols; j++)
    {
      arr[i][j] = set;
    }
  }
}

5.3 布置雷

思路

   对于雷的布置,我们仅需要布置9 * 9区域的雷即可。

   布置雷的个数为10个,我们采用定义的方式,方便随时修改雷的个数,雷的个数需要在头文件中定义:#define EASY_COUNT 10

   自动随机值的提供需要利用时间戳来完成,利用rand、srand、time函数来完成相关操作,srand函数在test中调用,布置雷的坐标为1-9,因此随机值表现形式为:rand() % row or col + 1

   雷的布置采用循环的方式

对应代码:


void set_mine(char mine[ROWS][COLS], int row, int col)
{
  int count = EASY_COUNT;
  int x = 0;
  int y = 0;
  while (count)
  {
    x = rand() % row + 1;//1-9
    y = rand() % col + 1;//1-9
    if (mine[x][y] == '0')
    {
      mine[x][y] = '1';
      count--;
    }
  }
}


5.4 打印棋盘


对于棋盘的打印,我们只需要打印出分隔线和对应的坐标即可。


思路


  • 棋盘打印依旧是 9 * 9。
  • 棋盘只需打印存放排查后数据的棋盘,不要暴露布置雷的棋盘,否则就被看到结果了。
  • 需要对棋盘对应的行列进行打印,方便玩家查看坐标。
  • 使用分隔线,避免上下棋盘黏在一起。

对应代码:


void show_board(char arr[ROWS][COLS], int row, int col)
{
  int i = 0;
  printf("------------扫雷------------\n");//分割线
  for (i = 0; i <= col; i++)
  {
    printf("%d ", i);//输出对应列信息
  }
  printf("\n");
  for (i = 1; i <= row; i++)
  {
    int j = 0;
    printf("%d ", i);//输出对应行信息
    for (j = 1; j <= col; j++)
    {
      printf("%c ", arr[i][j]);
    }
    printf("\n");
  }
  printf("------------扫雷------------\n");
}

打印效果:

15160728a3987ebe23553b4f33147410.png

相关文章
|
26天前
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
71 0
|
16天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
41 7
|
27天前
|
C语言
c语言回顾-函数递归(上)
c语言回顾-函数递归(上)
31 2
|
27天前
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
30 0
|
27天前
|
C语言
c语言回顾-函数递归(下)
c语言回顾-函数递归(下)
36 0
|
29天前
|
C语言
C语言扫雷游戏(详解)
C语言扫雷游戏(详解)
35 0
|
26天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
17天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
31 10
|
10天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
16天前
|
存储 编译器 程序员
【c语言】函数
本文介绍了C语言中函数的基本概念,包括库函数和自定义函数的定义、使用及示例。库函数如`printf`和`scanf`,通过包含相应的头文件即可使用。自定义函数需指定返回类型、函数名、形式参数等。文中还探讨了函数的调用、形参与实参的区别、return语句的用法、函数嵌套调用、链式访问以及static关键字对变量和函数的影响,强调了static如何改变变量的生命周期和作用域,以及函数的可见性。
25 4