揭开谜底:用 C 语言打造你的扫雷游戏!

目录

1. 功能概述

用户界面

2. 游戏分析与设计

2.1 数据结构分析

地雷存储:

玩家视图:

2.2 文件结构设计

3. 代码实现

game.h

game.c

test.c

 亮点功能与创新

智慧的较量:核心游戏循环

进阶功能:让游戏更加与众不同


还记得那款经典的扫雷游戏吗?它是否曾让你欲罢不能?现在,你有机会成为这款烧脑游戏的设计师!下面将带你一步步实现一个完整的扫雷游戏!!!!

  扫雷游戏的功能说明
使⽤控制台实现经典的扫雷游戏
游戏可以通过菜单实现继续玩或者退出游戏
扫雷的棋盘是9*9的格⼦
默认随机布置10个雷
可以排查雷
如果位置不是雷,就显⽰周围有⼏个雷
如果位置是雷,就炸死游戏结束
把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束

1. 功能概述

这款扫雷游戏是一个基于控制台的经典游戏实现。核心功能包括:

  • 游戏模式:提供菜单以选择继续游戏或退出。
  • 9x9 网格:默认的游戏棋盘大小为 9x9,随机放置 10 个地雷。
  • 地雷检测
    • 如果选择的位置不是地雷,游戏将显示周围的地雷数量。
    • 如果选择的位置是地雷,游戏结束,玩家失败。
    • 游戏胜利条件为揭开所有非地雷的格子。

用户界面

  • 初始屏幕:显示未触碰的棋盘,等待玩家选择。
  • 扫雷界面:展示玩家的进度,揭示地雷数量或结束游戏(触雷)。
  • 游戏结束屏幕:要么祝贺玩家扫清所有地雷,要么告知玩

          

               初始化界面                                排雷界面                           排雷失败界面

2. 游戏分析与设计

2.1 数据结构分析

游戏依赖于几个关键数据结构来存储地雷的位置和玩家的游戏进度。

  • 因为我们需要在9*9的棋盘上布置雷的信息和排查雷,我们⾸先想到的就是创建⼀个9*9的数组来存放
    信息。
  • 那如果这个位置布置雷,我们就存放1,没有布置雷就存放0.
  • 假设我们排查(2,4)这个坐标时,我们访问周围的⼀圈8个蓝色位置,统计周围雷的个数是1
    假设我们排查(8,6)这个坐标时,我们访问周围的⼀圈8个蓝色位置,统计周围雷的个数时,最下⾯的三 个坐标就会越界,为了防⽌越界,我们在设计的时候,给数组扩⼤⼀圈,雷还是布置在中间的9*9的坐
    标上,周围⼀圈不去布置雷就⾏,这样就解决了越界的问题。所以我们将存放数据的数组创成11*11 是⽐较合适。
  再继续分析,我们在棋盘上布置了雷,棋盘上雷的信息(1)和⾮雷的信息(0),假设我们排查了某 ⼀个位置后,这个坐标处不是雷,这个坐标的周围有1个雷,那我们需要将排查出的雷的数量信息记录存储,并打印出来,作为排雷的重要参考信息的。那这个雷的个数信息存放在哪⾥呢?如果存放在布 置雷的数组中,这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。
这⾥我们肯定有办法解决,⽐如:雷和⾮雷的信息不要使⽤数字,使⽤某些字符就⾏,这样就避免冲突了,但是这样做棋盘上有雷和⾮雷的信息,还有排查出的雷的个数信息,就⽐较混杂,不够⽅便。这⾥我们采⽤另外⼀种⽅案,我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。同时为了保持神秘,show数组开始时初始化为字符 '*',为了保持两个数组的类型⼀致,可以使⽤同⼀ 套函数处理,mine数组最开始也初始化为字符'0',布置雷改成'1':
           

 

地雷存储:
  • 一个 9x9 的数组用于存储地雷信息(1 表示有地雷,0 表示无地雷)。
  • 棋盘设计:9x9 的棋盘用于存储地雷位置和玩家输入。然而,为了避免在计算周围地雷时需要边界检查,棋盘扩展为 11x11。地雷仅放置在内层的 9x9 区域,外层的格子为空,以防止越界错误。
玩家视图:
  • 另一个数组用于追踪玩家的进度,初始状态为 '*',随着游戏进展更新为地雷数量或结束游戏的结果。
char mine[11][11] = {0}; // 存储地雷信息
char show[11][11] = {0}; // 存储玩家揭示的信息

2.2 文件结构设计

遵循最佳实践,游戏代码组织成三个文件:

  • test.c:包含游戏逻辑和测试代码。
  • game.c:实现核心游戏功能。
  • game.h:声明必要的数据结构和函数。

这种分离提升了代码的可维护性和可读性,符合模块化设计原则。

3. 代码实现

game.h

此头文件定义了游戏中的常量(如棋盘大小、地雷数量),并声明了初始化棋盘、显示棋盘、设置地雷和寻找地雷的核心函数。

#define _CRT_SECURE_NO_WARNINGS	
#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 DisplayBoard(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 DisplayBoard(char board[ROWS][COLS], int row, int col) {printf("   ");for (int i = 1; i <= col; i++) {printf("%d ", i);  // 打印列号}printf("\n");for (int i = 1; i <= row; i++) {printf("%2d ", i);  // 打印行号for (int j = 1; j <= col; j++) {printf("%c ", board[i][j]);  // 打印棋盘状态}printf("\n");}
}// 随机放置地雷
void SetMine(char board[ROWS][COLS], int row, int col) {int count = EASY_COUNT;while (count) {int x = rand() % row + 1;int y = rand() % col + 1;// 如果当前位置没有地雷,则放置一个地雷if (board[x][y] == '0') {board[x][y] = '1';  // '1' 表示地雷count--;}}
}// 计算指定位置周围地雷的数量
int GetMineCount(char mine[ROWS][COLS], 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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {int x, y;while (1) {printf("请输入要排查的坐标(行 列):");scanf("%d%d", &x, &y);// 检查输入的有效性if (x >= 1 && x <= row && y >= 1 && y <= col) {// 如果选择的是地雷if (mine[x][y] == '1') {printf("很遗憾,踩到地雷,游戏结束!\n");DisplayBoard(mine, row, col);  // 显示所有地雷位置break;}else {// 计算周围地雷数量并更新玩家视图int count = GetMineCount(mine, x, y);show[x][y] = count + '0';  // 显示地雷数量// 显示当前棋盘状态DisplayBoard(show, row, col);}}else {printf("输入无效,请重新输入有效的坐标。\n");}// 检查游戏胜利条件int uncovered = 0;for (int i = 1; i <= row; i++) {for (int j = 1; j <= col; j++) {if (show[i][j] == '*') {uncovered++;}}}if (uncovered == EASY_COUNT) {printf("恭喜你,扫清了所有地雷,游戏胜利!\n");break;}}
}

test.c

test.c 文件包括主游戏循环和菜单逻辑,允许玩家选择游戏或退出。

#include "game.h"void menu() {printf("***********************\n");printf("***** 1. play *****\n");printf("***** 0. exit *****\n");printf("***********************\n");
}void game() {// 核心游戏循环
}int main() {// 程序入口,处理菜单选择和游戏启动
}

 

 亮点功能与创新
  • 三种游戏模式:为了增加趣味性,提供了三个不同难度的选择:

    1. 简单:9x9 棋盘,10 个雷
    2. 中等:16x16 棋盘,40 个雷
    3. 困难:30x16 棋盘,99 个雷!

    玩家可以根据自己的水平选择挑战难度,从入门级别到高难度扫雷应有尽有。

  • 安全区扩展:如果你选择了一个安全的格子,并且其周围没有地雷,那么它周围的安全区域会自动展开。这一创新功能帮助玩家更快地排查大块区域,就像是一次连锁反应!

  • 标记地雷:玩家可以标记怀疑是雷的格子,这样在排查时能更好地记住危险区域,为游戏策略增添了更多可能性。

  • 时间显示功能:为了增加紧张感,增加了一个计时器,显示玩家清除雷区的耗时。你可以和朋友比拼,看看谁能更快完成任务!

智慧的较量:核心游戏循环

扫雷游戏的魅力在于未知的探索。每一次点击都有可能揭示一个安全通道,也可能引爆地雷!以下是游戏的核心循环,玩家输入坐标,棋盘揭示相应的信息。

 

进阶功能:让游戏更加与众不同
  • 分数系统:引入一个基于时间和操作步数的评分系统,增加挑战性,吸引玩家反复挑战刷新纪录。
  • 自定义雷区:允许玩家自己设计雷区布局,使每次游戏都充满未知和挑战。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54192.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang学习笔记18——golang 访问 mysql 数据库全解析

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…

人工智能GPT____豆包使用的一些初步探索步骤 体验不一样的工作

豆包工具是我使用比较频繁的一款软件&#xff0c;其集合了很多功能。对话 图像 AI搜索 伴读等等使用都非常不错。电脑端安装集合了很多功能。 官网直达&#xff1a;豆包 使用我的文案创作能力&#xff0c;您可以注意以下几个技巧&#xff1a; 明确需求&#xff1a; 尽可能具…

Vue3实现打印功能

1、安装插件 npm i vue3-print-nb --save 2、main.js全局配置 import print from vue3-print-nb app.use(print) 3、设置打印区域 为打印区域设置 id 选择器 <div id"printData"><el-table border :data"tableData" style"width: 100%…

和笔记相关的页面:编辑笔记和展示笔记 以及相关的viewmodel

1. 编辑笔记 EditNotesScreen&#xff1a;这是一个可编辑笔记的屏幕&#xff0c;它接收一个NavController对象、一个书籍的bookId和一个可选的modifier参数。它使用了LocalNotesViewModel来管理笔记的数据。 它首先定义了几个状态变量&#xff0c;包括是否显示对话框、编辑内…

C++ ——string的模拟实现

目录 前言 浅记 1. reserve&#xff08;扩容&#xff09; 2. push_back&#xff08;尾插&#xff09; 3. iterator&#xff08;迭代器&#xff09; 4. append&#xff08;尾插一个字符串&#xff09; 5. insert 5.1 按pos位插入一个字符 5.2 按pos位插入一个字符串 …

后端入门 (JQuery基础) 01

引入jQuery资源&#xff08;https://cdn.staticfile.net/jquery/1.10.2/jquery.min.js&#xff09; <script src"jquery.js"></script> <!-- 引入jQuery资源 --> 绑定事件的方式&#xff1a; 1. 直接使用事件函数 $("p").click(func…

C++第五十一弹---IO流实战:高效文件读写与格式化输出

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1. C语言的输入与输出 2. 流是什么 3. CIO流 3.1 C标准IO流 3.2 C文件IO流 3.2.1 以写方式打开文件 3.2.1 以读方式打开文件 4 stringstre…

flask框架

Flask 1 flask简介 我们之所以在浏览器中输入localhost:8080然后就可以把webapps下面的项目文件以浏览器的方式打开&#xff0c;功臣在与tomcat。python语言写的项目&#xff0c;转换为web&#xff0c;Flask框架 轻量级web应用框架。 环境准备&#xff1a; pip install fl…

【C语言】内存函数详细讲解

文章目录 前言strerror的声明和使用字符串分类函数字符转换函数内存拷贝函数&#xff08;memcpy)memcpy的声明和使用memcpy函数的模拟实现 内存拷贝函数&#xff08;memmove&#xff09;memmove的声明和使用memmove模拟实现 内存比较函数&#xff08;memcmp&#xff09;memcmp的…

UDP_SOCKET编程实现

文章目录 socket编程接口认识struct sockaddr类 编写一个server服务Client代码查看启动结果代码修正1.获取内核分配给客户端的信息2.修正不匹配ip不能访问的问题 不同机器之间的通信利用xftp将udp_client传给wsl的ubuntu机器进行演示现在模拟在windows下的udp_client代码: 对方…

时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测

时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测 目录 时序预测 | MATLAB实现BKA-XGBoost(黑翅鸢优化算法优化极限梯度提升树)时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 Matlab实现BKA-XGBoost时间序列预测&a…

WPF UpdateSourceTrigger属性

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;UpdateSourceTrigger 是一个属性&#xff0c;通常用于数据绑定中&#xff0c;它控制着何时将绑定目标&#xff08;即UI元素&#xff09;的值更新到绑定源&#xff08;即数据对象&#xff09;。当UI…

Go语言现代web开发08 if和switch分支语句

if语句 If is the most common conditional statement in programming languages. If the result of the condition caculation is positive(true), the code inside if statement will be executed. In the next example, value a will be incremented if it is less than 10…

《黑神话:悟空》:中国游戏界的新篇章

引言&#xff1a; 在数字娱乐的浪潮中&#xff0c;游戏已成为连接全球文化的重要媒介。 《黑神话&#xff1a;悟空》的问世&#xff0c;不仅是中国游戏产业的一个里程碑&#xff0c;更是文化自信的闪耀展现。 这款游戏以其独特的艺术风格和深刻的文化内涵&#xff0c;在全球范…

k8s中的认证授权

目录 一、kubernetes API 访问控制 1.1 UserAccount与ServiceAccount 1.1.1 ServiceAccount 1.1.2 ServiceAccount示例 二、认证(在k8s中建立认证用户) 2.1 创建UserAccount 2.2 RBAC&#xff08;Role Based Access Control&#xff09; 2.2.1 基于角色访问控制授权&…

RT-DETR改进策略:BackBone改进|使用StarNet改进RT-DERT,显著提升性能与效率

摘要 本文介绍了我们如何将最新的StarNet模型成功应用于实时目标检测任务中,特别是用于改进RT-DERT(一种高效的实时目标检测网络)的主干网络部分。通过详尽的实验和理论分析,我们证明了StarNet不仅能够显著增强RT-DERT的检测精度,同时保持了高效的计算性能和低延迟特性。…

C++从入门到起飞之——继承下篇(万字详解) 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、派⽣类的默认成员函数 1.1 四个常⻅默认成员函数 1.2 实现⼀个不能被继承的类 ​编辑 2. 继承与友…

力扣题解2390

大家好&#xff0c;欢迎来到无限大的频道。 今日继续给大家带来力扣题解。 题目描述​&#xff08;中等&#xff09;&#xff1a; 从字符串中移除星号 给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。 移除星号…

力扣刷题(6)

两数之和 II - 输入有序数组 两数之和 II - 输入有序数组-力扣 思路&#xff1a; 因为该数组是非递减顺序排列&#xff0c;因此可以设两个左右下标当左右下标的数相加大于target时&#xff0c;则表示右下标的数字过大&#xff0c;因此将右下标 - -当左右下标的数相加小于targ…

HashMap线程不安全|Hashtable|ConcurrentHashMap

文章目录 常见集合线程安全性HashMap为什么线程不安全&#xff1f;怎么保证HashMap线程安全 HashtableConcurrentHashMap 引入细粒度锁代码中分析总结 小结 常见集合线程安全性 ArrayList、LinkedList、TreeSet、HashSet、HashMap、TreeMap等都是线程不安全的。 HashTable是线…