【C language】扫雷

简介: 【C language】扫雷

1.概要

为了提高C初学者对C语言基本语法的掌控能力,一个极简版的扫雷游戏是十分适合锻炼代码能力的。下面分享仅用数组、函数这些C语言基本语法实现的一个小游戏——“Minesweeper”。

我需要说明的是仅仅是用来练习简单C语言基础语法代码能力的,而并非去尽力完善这个游戏,当然自己有时间有能力也可以去自己完善一下。

2.实现核心思想

用两个二维数组,一个数组用来对外展示,我们称之为show,另一个mine数组记录"雷"与"非雷"。

  • 对于show数组,默认是’*'状态,用来模拟未扫描的区域;倘若已经扫过了,且没有雷我们将其替换为该位置周围雷的数量。
  • 对于mine数组,我们’0’标识非雷,'1’标识雷。

    同时,因为要在下文统计到某个位置周围雷的个数,为了防止数组越界,因而对该棋盘周围多加一圈。

3.实现过程

我们设计的小游戏,整体用三个文件来进行设计的。

  • game.c文件:用来实现具体核心游戏函数
  • game.h文件:用来作为该游戏的小目录,包括一些宏定义和函数声明
  • Test.c文件:用来实现游戏的整体框架以及测试

3.1游戏框架

设计一个很简单的游戏框架是一个游戏设计的开始。该内容没有什么重点,略。

// Test.c文件中
void menu()
{
  printf("---------------------\n");
  printf("-----1.play game-----\n");
  printf("-----0.exit game-----\n");
  printf("---------------------\n");
}
TestGame()
{
  srand((unsigned int)time(0));
  int input = 0;
  do
  {
    menu();
    printf("Input options, please:\n");
    scanf("%d", &input);
    switch (input)
    {
    case 1:
      printf("Minesweeper begins!\n");
      game();
      break;
    case 0:
      printf("Successfully exited the game\n");
      break;
    default:
      printf("The input value is invalid\n");
      break;
    }
  } while (input);
}
int main()
{
  TestGame();
  return 0;
}

实现好了游戏的整体框架,我们要来想一想这个游戏该怎么做了。

3.2游戏逻辑

  • 初始化棋盘:首先我们得准备两个二维数组来当作棋盘,并初始化其值。
  • 打印show棋盘:打印要对外展示的棋盘。
  • 设置雷:在mine棋盘中设置雷,用’1’进行标识
  • 扫雷:玩家输入坐标并接收,然后作出反馈

然后对于我们要在上面框架中写的game(),我们就得出下面游戏逻辑:

#include"game.h"
void game()
{
  char Mine[ROWS_MAX][COLS_MAX];
  char show[ROWS_MAX][COLS_MAX];
  MineInit(Mine, ROWS_MAX, COLS_MAX, '0');
  MineInit(show, ROWS_MAX, COLS_MAX, '*');
  printf("----------Minesweeper interface-----------\n");
  //MinePrint(Mine, ROW_MAX, COL_MAX);
  MinePrint(show, ROW_MAX, COL_MAX);
  SetMines(Mine, ROW_MAX, COL_MAX);
  ClearMines(Mine, show, ROW_MAX, COL_MAX);
}

具体的game.h文件内容如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define ROW_MAX 9
#define COL_MAX 9
#define ROWS_MAX ROW_MAX + 2
#define COLS_MAX COL_MAX + 2
#define MINE_COUNT 5
void MineInit(char(*arr)[COLS_MAX], int rows, int cols, char val);
void MinePrint(char(*arr)[COLS_MAX], int row, int col);
void SetMines(char(*arr)[COLS_MAX], int row, int col);
void ClearMines(char(*Mine)[COLS_MAX], char(*Show)[COLS_MAX], int row, int col);

初始化棋盘 MineInit

那如何进行初始化棋盘呢?因为有两个棋盘,一个需要置0,另一个需要置✳

这里需要指出的是不需要写两个函数哈,只需要把需要初始化的值当作参数传入函数里就可以通过一个函数来处理了。

void MineInit(char(*arr)[COLS_MAX], int rows, int cols, char val)
{
  for (int i = 0; i < rows; i++)
  {
    for (int j = 0; j < cols; j++)
    {
      *(*(arr + i) + j) = val;
    }
  }
}

打印棋盘 MinePrint

对棋盘里的值进行打印即可,双重嵌套循环即可。

其中,第一个循环是为了打印显示中的行号。

void MinePrint(char(*arr)[COLS_MAX], int row, int col)
{
  for (int i = 0; i <= col; i++)
  {
    printf("%d ", i);
  }
  printf("\n");
  for (int i = 1; i <= row; i++)
  {
    printf("%d ", i);
    for (int j = 1; j <= col; j++)
    {
      printf("%c ", *(*(arr + i) + j));
    }
    printf("\n");
  }
  printf("----------Minesweeper interface-----------\n");
}

设置雷 SetMines

这里用一个随机数即可,需要注意设置雷的条件是之前不是雷才行,重复设置(同一位置)的不算。

void SetMines(char(*arr)[COLS_MAX], int row, int col)
{
  size_t count = 0;
  while (count < MINE_COUNT)
  {
    int x = rand() % 9 + 1;
    int y = rand() % 9 + 1;
    if (*(*(arr + x) + y) == '0')
    {
      *(*(arr + x) + y) = '1';
      count++;
    }
  }
}

扫雷 ClearMines

扫雷的话要一边展示show信息,一边接收用户输入的行号列号并给出对应的反馈即可。

这里需要注意的是拿到一个位置多少个雷后要用char的形式存入show中,而不是int的形式。

int GetMines(char(*Mine)[COLS_MAX], int x, int y)
{
  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');
}
void ClearMines(char (*Mine)[COLS_MAX], char(*Show)[COLS_MAX], int row, int col)
{
  int sum = ROW_MAX * COL_MAX - MINE_COUNT;
  int count = 0;
  while (count < sum)
  {
    //MinePrint(Mine, row, col);
    MinePrint(Show, row, col);
    printf("Enter the coordinates you want to check\n");
    
    int x = 0, y = 0;
    scanf("%d%d", &x, &y);
    if (x >= 1 && y <= 9)
    {
      if (Mine[x][y] == '1')
      {
        printf("Sorry, you were killed.\n");
        printf("Below is the mine layout diagram for this game:\n");
        MinePrint(Mine, row, col);
        //MinePrint(Show, row, col);
        break;
      }
      else
      {
        int z_count = GetMines(Mine, x, y);
        if (Show[x][y] == '*') count++;
        else printf("This location has been scanned and is invalid.\n");
        Sleep(1000);
        Show[x][y] = z_count + '0';
        //MinePrint(Mine, row, col);
        MinePrint(Show, row, col);
      }
    }
    else
    {
      printf("The coordinates you entered are out of bounds\n");
    }
  }
  
  if (count == sum)
  {
    printf("Congratulations, the mine clearance was successful!!!\n");
  }
}

4.总结

整体来说,该游戏是用来复习基本语法知识的,比较简单,游戏逻辑清晰明了,功能单一,适合C初学者。


EOF


相关文章
|
移动开发 前端开发 Shell
《HTML5 Canvas核心技术 图形、动画与游戏开发》 读书笔记
《HTML5 Canvas核心技术 图形、动画与游戏开发》 读书笔记
|
4月前
|
安全 Windows
系统恢复厂商设置工具,系统备份,系统还原工具推荐
本文介绍了两款系统备份与恢复工具:傲梅一键还原和联想一键恢复。傲梅一键还原支持所有电脑,通过按F11键快速还原系统,避免重装系统及程序;联想一键恢复则是联想设备专用工具,可恢复出厂设置或自定义备份,适用于Windows 7至Windows 10系统。两者均可有效应对“启动失败”、“找不到操作系统”等常见问题。
132 0
|
人工智能 搜索推荐 大数据
元宇宙游戏:沉浸式体验的新纪元
【10月更文挑战第27天】元宇宙游戏正开启沉浸式体验的新纪元,通过集成VR、AR、AI和区块链等技术,提供高度沉浸、个性化、社交与经济系统的综合数字平台。本文探讨其定义、技术特点、发展趋势及对游戏产业和社会文化的深远影响。
262 43
|
API C# Windows
【C#】在winform中如何实现嵌入第三方软件窗体
【C#】在winform中如何实现嵌入第三方软件窗体
684 0
|
Web App开发 缓存 自然语言处理
60 个神级 VS Code 插件!(2)
60 个神级 VS Code 插件!(2)
557 0
60 个神级 VS Code 插件!(2)
|
测试技术 Nacos 开发工具
灰度发布:揭秘背后的原理与实践浅见
揭秘灰度发布背后的原理与实践浅见
775 2
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现深度学习模型:智能环境监测与预警
【8月更文挑战第11天】 使用Python实现深度学习模型:智能环境监测与预警
1302 2
|
关系型数据库 MySQL 数据库
MySQL8报错:Public Key Retrieval is not allowed
MySQL8报错:Public Key Retrieval is not allowed
6491 1
|
17天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
下一篇
开通oss服务