【C语言6】数组和函数实践:扫雷游戏的简单实现

文章目录
- 一、扫雷游戏分析和设计
- 1.1 扫雷游戏的功能说明
- 1.2 游戏的分析和设计
- 1.2.1 数据结构的分析
- 1.2.2 文件结构设计
- 二、扫雷游戏的代码实现
- 三、扫雷游戏的扩展
- 总结
一、扫雷游戏分析和设计
1.1 扫雷游戏的功能说明
- 使用控制台实现经典的扫雷游戏
- 游戏可以通过菜单实现继续玩或者退出游戏
- 扫雷的棋盘是9*9的格子
- 默认随机布置10个雷
- 可以排查雷
◦ 如果位置不是雷,就显示周围有几个雷
◦ 如果位置是雷,就炸死游戏结束
◦ 把除10个雷之外的所有非雷都找出来,排雷成功,游戏结束
游戏的界面:



1.2 游戏的分析和设计
1.2.1 数据结构的分析
扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要一定的数据结构来存储这些信息。
因为我们需要在99的棋盘上布置雷的信息和排查雷,我们首先想到的就是创建一个99的数组来存放信息。

那如果这个位置布置雷,我们就存放1,没有布置雷就存放0

假设我们排查(2,5)这个坐标时,我们访问周围的一圈8个黄色位置,统计周围雷的个数是1
假设我们排查(8,6)这个坐标时,我们访问周围的一圈8个黄色位置,统计周围雷的个数时,最下面的三个坐标就会越界,为了防止越界,我们在设计的时候,给数组扩大一圈,雷还是布置在中间的99的坐标上,周围一圈不去布置雷就行,这样就解决了越界的问题。所以我们将存放数据的数组创建成1111是比较合适。


再继续分析,我们在棋盘上布置了雷,棋盘上雷的信息(1)和非雷的信息(0),假设我们排查了某一个位置后,这个坐标处不是雷,这个坐标的周围有1个雷,那我们需要将排查出的雷的数量信息记录存储,并打印出来,作为排雷的重要参考信息的。那这个雷的个数信息存放在哪里呢?如果存放在布置雷的数组中,这样雷的信息和雷的个数信息就可能或产生混淆和打印上的困难。
这里我们肯定有办法解决,比如:雷和非雷的信息不要使用数字,使用某些字符就行,这样就避免冲突了,但是这样做棋盘上有雷和非雷的信息,还有排查出的雷的个数信息,就比较混杂,不够方便。
这里我们采用另外一种方案,我们专门给一个棋盘(对应一个数组mine)存放布置好的雷的信息,再给另外一个棋盘(对应另外一个数组show)存放排查出的雷的信息。这样就互不干扰了,把雷布置到mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期排查参考。
同时为了保持神秘,show数组开始时初始化为字符 ‘*’,为了保持两个数组的类型一致,可以使用同一套函数处理,mine数组最开始也初始化为字符’0’,布置雷改成’1’。如下如:
mine数组布置雷后的状态

show输出初始化的状态

对应的数组是:
char mine[11][11] = {0};//用来存放布置好的雷的信息
char show[11][11] = {0};//用来存放排查出的雷的个数信息
1.2.2 文件结构设计
之前学习了多文件的形式对函数的声明和定义,这里我们实践一下,我们设计三个文件:
test.c //文件中写游戏的测试逻辑
game.c //文件中写游戏中函数的实现等
game.h //文件中写游戏需要的数据类型和函数声明等
二、扫雷游戏的代码实现
game.h
#pragma once#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define EASY_COUNT 10#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2//初始化棋盘
void initBoard(char board[ROWS][COLS], int rows, int cols, char set);//打印棋盘
void printBoard(char board[ROWS][COLS], int row, int col);//布置雷
void setMine(char board[ROWS][COLS], int row, int col);//排查雷
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS#include "game.h"void initBoard(char board[ROWS][COLS], int rows, int cols, char set)
{for (int i = 0; i < rows; ++i){for (int j = 0; j < cols; ++j){board[i][j] = set;}}
}void printBoard(char board[ROWS][COLS], int row, int col)
{printf("------扫雷游戏------\n");for (int i = 0; i <= row; ++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 ", board[i][j]);}printf("\n");}
}void setMine(char mine[ROWS][COLS], int row, int col)
{//随机设置10个雷int count = EASY_COUNT;while (count){int x = rand() % ROW + 1; //1-9的随机x.yint y = rand() % COL + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}static int get_Mine_count(char mine[ROWS][COLS], int x, int y)
{return mine[x + 1][y + 1] + mine[x + 1][y - 1] + 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] - 8 * '0';
}void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x, y;int win = 0;while (win < ROW * COL - EASY_COUNT){printf("请选择要排查的坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了!\n");printBoard(mine, ROW, COL);break;}else{if (show[x][y] == '*'){show[x][y] = get_Mine_count(mine, x, y) + '0';printBoard(show, ROW, COL);win++;}}}else{printf("您输入的坐标不合法,请重新输入\n");}}if (win == ROW * COL - EASY_COUNT){printf("恭喜你!排雷成功!\n\n");printBoard(mine, ROW, COL);}
}
test.c
#define _CRT_SECURE_NO_WARNINGS#include "game.h"static void menu()
{printf("*************************************\n");printf("************ 1. play ************\n");printf("************ 0. exit ************\n");printf("*************************************\n");
}static void game()
{char mine[ROWS][ROWS];char show[ROWS][ROWS];//初始化//1. mine数组最开始是全'0'//2. show数组最开始是全'*'initBoard(mine, ROWS, COLS, '0');initBoard(show, ROWS, COLS, '*');//设置雷setMine(mine, ROW, COL);//打印//printBoard(mine, ROW, COL);printBoard(show, ROW, COL);//排雷findMine(mine, show, ROW, COL);
}int main()
{srand((unsigned int)time(NULL));int input = -1;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;
}
三、扫雷游戏的扩展
- 是否可以选择游戏难度
◦ 简单 99 棋盘,10个雷
◦ 中等 1616棋盘,40个雷
◦ 困难 30*16棋盘,99个雷 - 如果排查位置不是雷,周围也没有雷,可以展开周围的一片
- 是否可以标记雷
- 是否可以加上排雷的时间显示
在线扫雷游戏:http://www.minesweeper.cn/
总结
今天结合前面的知识实现了一个小的扫雷游戏,基本功能可以实现,扩展部分有待补充…

相关文章:
【C语言6】数组和函数实践:扫雷游戏的简单实现
文章目录 一、扫雷游戏分析和设计1.1 扫雷游戏的功能说明1.2 游戏的分析和设计1.2.1 数据结构的分析1.2.2 文件结构设计 二、扫雷游戏的代码实现三、扫雷游戏的扩展总结 一、扫雷游戏分析和设计 1.1 扫雷游戏的功能说明 使用控制台实现经典的扫雷游戏游戏可以通过菜单实现继续…...
LeetCode 热题 100----1.两数之和
LeetCode 热题 100----1.两数之和 题目描述 我的解法 语言:js 思路就是:用双重循环去找哪两个数字相加等于target,目前的时间复杂度为O(n2),之后右优化思路再更新。...
《模式和状态管理》知识总结三-EcuM与BswM模块的交互
前言 这篇文章主要搞清楚在模式管理中,BswM和EcuM各自的分工。距离学完模式管理也有几天时间了,写这篇文章算是复习一下。 EcuM及BswM交互总览 EcuM负责Ecu的上下电状态的处理,当Ecu处于正常运行状态的时候,EcuM会将Ecu的控制权…...
RK3568平台(网络篇)RTL8111网卡
RTL8111 是 Realtek 推出的一款高性能千兆以太网控制器芯片,广泛应用于 PCIE 网卡中。 其工作原理涉及 数据链路层 和 物理层 的协同工作,以下是其核心原理的详细说明: 一.网卡的基本功能 1.数据封装与解封装: 网卡负责将计算机中的数据封装成网络传输的帧(Frame),并…...
客户需求模糊或频繁变更怎么办
应对客户需求模糊或频繁变更的关键在于 明确沟通、敏捷应对、科学决策。其中,明确沟通尤为重要,因为通过有效沟通,不仅能迅速厘清客户真实需求,还能及时发现隐藏问题,降低项目风险,为后续调整提供有力数据支…...
动静态库-Linux 学习
在软件开发中,程序库是一组预先编写好的程序代码,它们存储了常用的函数、变量和数据结构等。这些库可以帮助开发者节省大量的时间和精力,避免重复编写相同的代码。当我们在 Linux 系统中开发程序时,经常会用到两种类型的程序库&am…...
DeepSeek 系列模型:论文精读《A Survey of DeepSeek Models》
引言:一篇快速了解 DeepSeek 系列的论文。我在翻译时加入了一些可以提高 “可读性” 的连词 ✅ NLP 研 2 选手的学习笔记 笔者简介:Wang Linyong,NPU,2023级,计算机技术 研究方向:文本生成、大语言模型 论文…...
Python解决“找出整形数组中占比超过一半的数”问题
这里写目录标题 问题描述测试样例解决思路代码法1法2 问题描述 小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。 测试样例 样例1: 输入&…...
机器人学习模拟框架 robosuite (3) 机器人控制代码示例
Robosuite框架是一个用于机器人模拟和控制的强大工具,支持多种类型的机器人。 官方文档:Overview — robosuite 1.5 documentation 开源地址:https://github.com/ARISE-Initiative/robosuite 目录 1、通过键盘或SpaceMouse远程控制机器人…...
kakfa-3:ISR机制、HWLEO、生产者、消费者、核心参数负载均衡
1. kafka内核原理 1.1 ISR机制 光是依靠多副本机制能保证Kafka的高可用性,但是能保证数据不丢失吗?不行,因为如果leader宕机,但是leader的数据还没同步到follower上去,此时即使选举了follower作为新的leaderÿ…...
【微知】如何查看Mellanox网卡上的光模块的信息?(ethtool -m enp1s0f0 看型号、厂商、生产日期等)
背景 服务器上插入的光模块经常被忽略,往往这里是定位问题最根本的地方。如何通过命令查看? 命令 ethtool提供了-m参数,m是module-info的意思,他是从光模块的eeprom中读取数据。(应该是用i2c协议读取的)…...
yum源选要配置华为云的源,阿里云用不了的情况
curl -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo...
nginx accesslog 打印自定义header
比如我在请求的header中添加了一个path-match-type,那我现在nginx的accesslog 中打印出来,应该如何配置呢? rootnginx-59f5d66df6-jw5k8:/# cat /etc/nginx/nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/erro…...
好数——前缀和思想(题目分享)
今天我的舍友去参加“传智杯”广东省的省赛,跟我说了这样一道题,他说他想不出来怎么去优化代码,怎么做都是套用两层for循环超时,下面我就根据题意,使用前缀和的算法去优化一下思路,题目本身是不难的&#x…...
MWC 2025 | 移远通信大模型解决方案加速落地,引领服务机器人创新变革
随着人工智能、大模型等技术的蓬勃发展,生成式AI应用全面爆发。在此背景下,服务机器人作为大模型技术在端侧落地的关键场景,迎来了前所未有的发展机遇。 作为与用户直接交互的智能设备,服务机器人需要应对复杂场景下的感知、决策和…...
【大模型基础_毛玉仁】0.概述
更多内容:XiaoJ的知识星球 【大模型基础_毛玉仁】 系列文章参考 系列文章 【大模型基础_毛玉仁】0.概述 【大模型基础_毛玉仁】1.1 基于统计方法的语言模型 更新中。。。。。。 参考 书籍:大模型基础_完整版.pdf Github:https://github.co…...
ADB、Appium 和 大模型融合开展移动端自动化测试
将 ADB、Appium 和 大模型(如 GPT、LLM) 结合,可以显著提升移动端自动化测试的智能化水平和效率。以下是具体的实现思路和应用场景: 1. 核心组件的作用 ADB(Android Debug Bridge): 用于与 Android 设备通信,执行设备操作(如安装应用、获取日志、截图等)。Appium: 用…...
springboot425-基于SpringBoot的BUG管理系统(源码+数据库+纯前后端分离+部署讲解等)
💕💕作者: 爱笑学姐 💕💕个人简介:十年Java,Python美女程序员一枚,精通计算机专业前后端各类框架。 💕💕各类成品Java毕设 。javaweb,ssm…...
Ubuntu系统上部署Node.js项目的完整流程
以下是在Ubuntu系统上部署Node.js项目的完整流程,分为系统初始化、环境配置、项目部署三个部分: 一、系统初始化 & 环境准备 bash # 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y# 2. 安装基础工具 sudo apt install -y buil…...
X Window---图形接口
摘抄自 鸟哥的linux私房菜 基础篇 第四版 有鉴于图形用户接口(Graphical User Interface, GUI) 的需求日益加重,在 1984 年由 MIT 与其他第三方首次发表了 X Window System ,并且更在 1988 年成立了非营利性质的 XFree86 这个组织。所谓的XFree86 其实是…...
数据序列化协议 Protobuf 3 介绍(Go 语言)
Protobuf 3 入门 1. 什么是序列化? 1.1 概念 序列化(Serialization 或 Marshalling) 是指将数据结构或对象的状态转换成可存储或传输的格式。反向操作称为反序列化(Deserialization 或 Unmarshalling),它…...
FineReport 操作注意
1.父单元格重复的时候,如何取消合并 效果如下: 只需要在单元格中,将数据设置为【列表】即可。 2.待定...
3D手眼标定转换详细实施步骤及原理概述
3D手眼标定转换详细实施步骤及原理概述 一、手眼标定的核心目标二、3D手眼标定的原理概述一、基本概念与坐标系定义**二、数学建模与方程推导****1. 坐标变换的齐次矩阵表示****2. 手眼标定方程推导** **三、方程求解方法****1. 分离旋转与平移****2. 旋转矩阵求解****3. 平移向…...
Verilog:SCCB控制器
目录 一、SCCB协议 (1)SCCB时序 (2)与I2C的区别 二、Verilog 实现 (1)设计要求 (2)设计要点 (3)模块完整代码 三、功能验证 (1)写…...
维度建模基础篇:从理论到核心组件解析
维度建模基础篇:从理论到核心组件解析 引言 在数据仓库与商业智能(BI)领域,维度建模(Dimensional Modeling)作为一种经典的数据组织方法论,自Kimball提出以来,已成为构建高效分析型系统的核心范式1,2,3。其以业务需求为导向,通过事实表与维度表的组合,实现对复杂…...
与中国联通技术共建:通过obdiag分析OceanBase DDL中的报错场景
中国联通软件研究院(简称联通软研院)在全面评估与广泛调研后,在 2021年底决定采用OceanBase 作为基础,自研分布式数据库产品CUDB(即China Unicom Database,中国联通数据库)。目前,该…...
大数据与网络安全讲座
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 大数据的价值为大家公认。业界通常以4个“V”来概括大数据的基本特征——Volume(数据体量巨大)、Variety(数据类型繁多)、Value(价值密度低)、Velocity(处理速度快…...
AtCoder Beginner Contest 395 E
点我写题 题意:给个有向图,从1出发,每次可以走一条有向边,花费为1,也可以选择把全部有向边翻转,花费x,问到n的最小花费 思路:最短路dp,定义dis[i][0/1]表示走到i为止&…...
Linux进程管理6 - CFS调度
0、CFS调度器 CFS调度器使用完全公平调度算法。 完全公平调度算法引入虚拟运行时间的概念:虚拟运行时间 = 实际运行时间 * nice_0_weight / 进程的权重。完全公平调度算法使用红黑树把进程按虚拟运行时间从小到大排序,每次调度选择虚拟运行时间最小的进程。时间片 操作系统进…...
张驰咨询:用六西格玛重构动力电池行业的BOM成本逻辑
在动力电池行业,BOM(物料清单)成本每降低1%,都可能改写企业的利润曲线。某头部企业的三元锂电池BOM成本曾较行业标杆高出11%,单电芯利润率被压缩至3%的生死线。然而,通过张驰咨询的六西格玛方法论ÿ…...
