【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

相关文章
|
1月前
|
存储 编译器 C语言
爱上C语言:函数递归,青蛙跳台阶图文详解
爱上C语言:函数递归,青蛙跳台阶图文详解
|
6天前
|
C语言
【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)
【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)
7 0
|
17天前
|
机器学习/深度学习 C语言
函数递归深入解析(C语言)
函数递归深入解析(C语言)
|
20天前
|
C语言 索引
c语言的函数与递归
c语言的函数与递归
14 1
|
20天前
|
C语言
以c语言为基础实现的简易扫雷游戏(游戏代码附在文章最后,如有需要请自取)
以c语言为基础实现的简易扫雷游戏(游戏代码附在文章最后,如有需要请自取)
41 1
|
1月前
|
搜索推荐 C语言 C++
【排序算法】C语言实现归并排序,包括递归和迭代两个版本
【排序算法】C语言实现归并排序,包括递归和迭代两个版本
|
17天前
|
C语言
C语言:内存函数(memcpy memmove memset memcmp使用)
C语言:内存函数(memcpy memmove memset memcmp使用)
|
2天前
|
存储 编译器 C语言
C语言:字符函数 & 字符串函数 & 内存函数
C语言:字符函数 & 字符串函数 & 内存函数
11 2
|
11天前
|
缓存 安全 编译器
【C 言专栏】C 语言函数的高效编程技巧
【5月更文挑战第1天】本文探讨了C语言中函数的高效编程技巧,包括函数的定义与作用(如代码复用和提高可读性)、设计原则(单一职责和接口简洁)、参数传递方式(值传递、指针传递和引用传递)、返回值管理、调用约定、嵌套与递归调用,以及函数优化技巧和常见错误避免。掌握这些技巧能提升C语言代码的质量和效率。
【C 言专栏】C 语言函数的高效编程技巧
|
13天前
|
C语言
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)
pta浙大版《C语言程序设计(第3版)》 习题6-4 使用函数输出指定范围内的Fibonacci数 (20分)