揭开谜底:用 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.xdnf.cn/news/1536718.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 中的 GROUP BY 和 HAVING 子句:特性、用法与注意事项

在 MySQL 数据库的查询操作中&#xff0c;GROUP BY 和 HAVING 子句是非常强大的工具&#xff0c;它们能够帮助我们对数据进行分组和筛选&#xff0c;从而更好地分析和处理数据。今天&#xff0c;我们就来深入了解一下 GROUP BY 和 HAVING 子句的特性、用法及注意事项。 一、GR…

二叉树OJ题——另一棵树的子树

文章目录 一、题目链接二、解题思路三、解题代码 一、题目链接 另一棵树的子树 题目描述&#xff1a;判断当前树A是否是树B的子树。 二、解题思路 时间复杂度&#xff1a;O(n*m) 三、解题代码

深度学习之微积分预备知识点

极限&#xff08;Limit&#xff09; 定义&#xff1a;表示某一点处函数趋近于某一特定值的过程&#xff0c;一般记为 极限是一种变化状态的描述&#xff0c;核心思想是无限靠近而永远不能到达 公式&#xff1a; 表示 x 趋向 a 时 f(x) 的极限。 知识点口诀解释极限的存在左…

文件误删除后的数据救援实战指南

在数字化时代&#xff0c;文件误删除成为了许多用户心头挥之不去的阴影。无论是手误点击了“删除”键&#xff0c;还是系统崩溃导致的数据丢失&#xff0c;文件一旦从我们的视线中消失&#xff0c;往往伴随着重要信息的流失和工作的中断。本文将深入探讨文件误删除的现象&#…

数据中台建设(六)—— 数据资产管理

数据资产管理 随着企业数据越来越大&#xff0c;企业意识到数据是一种无形的资产&#xff0c;通过对企业各业务线产生的海量数据进行合理管理和有效应用&#xff0c;能盘活并充分释放数据的巨大价值。如果不能对海量数据进行有效管理和应用&#xff0c;企业堆积如山的数据给企…

使用 release key 对 LineageOS 进行编译和签名

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 为什么需要使用 release key test-key 是一个公开的、众所周知的开发测试密钥&#xff0c;广泛用于测试阶段。这意味着任何人都可以获取这个密钥&#xff0c;…

R语言学习全攻略:从入门到精通的详细指南

目录 一、引言 1. R语言的背景和发展 2. 学习R语言的意义 二、R语言的核心特性 1. 开源和跨平台 2. 专业的统计分析功能 3. 强大的数据可视化能力 4. 丰富的扩展包 三、R语言基础语法 1. 基本数据类型 2. 数据结构 向量&#xff08;Vector&#xff09; 矩阵&#x…

Vue.js魔法书:前端开发者的终极指南

个人名片&#xff1a;&#x1f60a;作者简介&#xff1a;一个为了让更多人看见许舒雅的宝贝的小白先生 &#x1f921;个人主页&#xff1a;许舒雅的宝贝 &#x1f43c;座右铭&#xff1a;深夜两点半的夜灯依旧闪烁&#xff0c;凌晨四点的闹钟不止你一个。 &#x1f385;学习目标…

UML 类图(提供 Java 实现)

文章目录 UML 类图概述及作用类图表示法类&#xff08;接口&#xff09;的表示类与类之间关系的表示关联关系&#xff08;Association&#xff09;单向关联&#xff08;Unidirectional Association&#xff09;双向关联&#xff08;Bidirectional Association&#xff09;自关联…

Acwing 栈

1.数组模拟栈 主要思想&#xff1a;先进后出&#xff0c;设置一个数组存储数据&#xff0c;一个栈顶指针指向栈顶&#xff08;初始化为0&#xff09; 注意&#xff1a;数据出栈&#xff0c;只需将指针单纯前移&#xff0c;无需在意数组还存储数据造成浪费。 下面是需要背过的…

Linux部署Servlet代码

文章目录 一、为何要部署网站二、如何部署2.1 准备Java web的环境如何安装 为什么要准备环境安装JDK安装Tomcat 并启动Tomcat&#xff1a;安装Mysql 2.2 在云服务器上部署网站 其他查看Tomcat日志访问Tomcat的欢迎页面访问MariaDB 一、为何要部署网站 我们做出的网站是希望这…

2024永久激活版 Studio One 6 Pro for mac 音乐创作编辑软件 完美兼容

Studio One 6是一款功能强大的音乐制作软件&#xff0c;由PreSonus公司开发。它提供了全面的音频录制、编辑、混音和母带处理工具&#xff0c;适用于音乐制作人、音频工程师和创作人员。 Studio One 6拥有直观的用户界面&#xff0c;使用户能够快速而流畅地进行音乐创作。它采…

谷粒商城のElasticsearch

文章目录 前言一、前置知识1、Elasticsearch 的结构2、倒排索引 (Inverted Index)2.1、 索引阶段2.2、查询阶段 二、环境准备1、安装Es2、安装Kibana3、安装 ik 分词器 三、项目整合1、引入依赖2、整合业务2.1、创建索引、文档、构建查询语句2.2、整合业务代码 后记 前言 本篇介…

[内网渗透]---msf基础-永恒之蓝-ms17-010

what Metasploit&#xff08;通常简称为MSF&#xff09;是一个开源的渗透测试框架&#xff0c;包含大量的已知漏洞利用模块&#xff0c;可以用来攻击目标系统并获取控制权。 how 实验环境&#xff1a;Kali、带有永恒之蓝漏洞的虚拟机且开启445端口(两个虚拟机同一子网) 1.信…

进阶SpringBoot之异步任务、邮件任务和定时执行任务

SpringBooot 创建 Web 项目 异步任务&#xff1a; service 包下创建 AsyncService 类 Async 异步方法 Thread.sleep(3000) 停止三秒&#xff0c;捕获异常 package com.demo.task.service;import org.springframework.scheduling.annotation.Async; import org.springfram…

matlab DFT的点数与周期

只需要0——N-1个点就可以算得另一个域全部的信号 周期 时域信号的全部长度时一个周期&#xff0c;所以时域的周期化没有混叠 频域的周期与采样率有关&#xff0c;会混叠。 取一个周期进行傅里叶变换都是对于周期化后的信号取得&#xff0c;由于时域周期化不混叠&#xff0c;所…

句子成分——每日一划(九)

人民英雄&#xff0c;永垂不朽&#xff01; 目录 一、原句 二、主语 三、谓语 四、介词短语 一、原句 Eternal glory to the heroes of the people who from 1840 laid down their lives in the many struggles against domestic and foreign enemies and for national i…

思维训练900

思路&#xff1a; 假设答案用x表示&#xff0c;则x&a[i]要尽可能小&#xff0c;那就让x遍历一遍数组&#xff0c;每次进行&操作&#xff0c;直到尽可能多的位数变成0&#xff0c;所得到的x就是最后答案 代码; vector<int> a(n);int ans;for(int i 0; i < n…

磁盘写入缓存区太大,如何清理C盘缓存

针对“磁盘写入缓存区太大&#xff0c;如何清理C盘缓存”的问题&#xff0c;我们可以从多个角度进行专业解答。首先&#xff0c;需要明确的是&#xff0c;“磁盘写入缓存区太大”这一表述可能涉及硬盘缓存的设置或系统缓存管理&#xff0c;但通常用户面对的问题更多是关于C盘空…

【网络安全的神秘世界】csrf客户端请求伪造

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 一、概述 跨站请求伪造&#xff0c;是一种挟持用户在当前已登陆的web应用程序上执行非本意操作的攻击方法&#xff0c;允许攻…