【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

相关文章
|
C语言
扫雷游戏(用C语言实现)
扫雷游戏(用C语言实现)
238 0
|
10月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
498 16
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
345 7
|
C语言
c语言回顾-函数递归(上)
c语言回顾-函数递归(上)
117 2
|
C语言
初学者指南:使用C语言实现简易版扫雷游戏
初学者指南:使用C语言实现简易版扫雷游戏
186 0
|
C语言
c语言回顾-函数递归(下)
c语言回顾-函数递归(下)
141 0
|
2月前
|
存储 C语言
`scanf`是C语言中用于按格式读取标准输入的函数
`scanf`是C语言中用于按格式读取标准输入的函数,通过格式字符串解析输入并存入指定变量。需注意输入格式严格匹配,并建议检查返回值以确保读取成功,提升程序健壮性。
904 0
|
4月前
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
297 15
|
10月前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
518 23
|
9月前
|
人工智能 Java 程序员
一文彻底搞清楚C语言的函数
本文介绍C语言函数:函数是程序模块化的工具,由函数头和函数体组成,涵盖定义、调用、参数传递及声明等内容。值传递确保实参不受影响,函数声明增强代码可读性。君志所向,一往无前!
308 1
一文彻底搞清楚C语言的函数