C语言实现扫雷【经典】

前言
  本篇文章要实现的是扫雷游戏,其代码实现与上一篇的三子棋游戏类同,都是在棋盘的基础上,与电脑进行对抗,不同的是,扫雷游戏一开始电脑就已经随机布置好了所有“雷”。
在这里插入图片描述

请戳 --->三子棋

扫雷游戏

  • 1. 扫雷游戏玩法
  • 2. 设计思路
    • 2.1 准备工作
    • 2.2 主函数设计
    • 2.3 设计棋盘
      • 2.3.1 初始化棋盘
      • 2.3.2 打印棋盘
    • 2.4 布置雷
    • 2.5 排除雷
      • 2.5.1 代码实现
  • 3. 总结
    • 3.1 game.h文件所有内容
    • 3.2 game()游戏函数整体
  • 结束语


1. 扫雷游戏玩法

经典玩法:

扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败

游戏主区域由很多个方格组成。选择一个方格,方格即被打开并显示出方格中的数字

而方格中数字则表示其周围的8个方格隐藏了几颗雷;如果点开的格子为空白格,即其周围有0颗雷,则其周围格子会自动打开。

在这里插入图片描述

本机玩法:

游戏开始,玩家在棋盘格上输入正确的行列坐标选择位置,若选择到的是非地雷,就会显示出周围8个格子存在雷的数量,直到把所有非雷的格子都选出来,游戏胜利;若“踩雷”了,则游戏失败

看似简单的扫雷游戏,想要胜利,走的每一步都需要推算

2. 设计思路

游戏都需要一个开关去控制它,所以一个菜单界面是必不可少的,通过菜单去选择play还是exit

而对于游戏的实现:

1.首先需要创建一个n*n的棋盘格,可以用二维数组实现,自定义它的大小

2.在玩家选择位置前,就要布置好雷的数量,随机埋下雷的位置,并用一个二维数组来存放布置好的雷

3.玩家通过提示,输入正确的坐标选择位置,如果选择的是非雷坐标,就显示出周围雷的数量,用一个二维数组来存放排查出的雷的信息(数量)

坐标选择后的状态有两种:

  • 选择的坐标是非雷的,显示周围雷的数量,一直到排查完所有的雷,即所有的坐标都选择完了且没有踩雷,游戏胜利
  • 选择的坐标是有雷的,游戏失败

2.1 准备工作

🍥 建立 test.c 源文件 – 测试游戏代码
🍥 建立 game.c 源文件 – 游戏的实现
🍥 建立 game.h 头文件 – 游戏函数声明

2.2 主函数设计

为了控制游戏的进行,我们设置一个菜单选项,选1时玩游戏,选择0,则退出游戏。

🍤 代码实现:

//test.cint main()
{//菜单printf("----1. play----\n");printf("----0. exit----\n");//进行选择int input;printf("请选择:");scanf("%d", &input);switch (input){case 1:game();//游戏函数break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}return 0;
}

当玩家想要一直玩游戏,该怎么办呢? 加入循环
同时,为了使主函数简洁明了,我们将菜单放在主函数外面,使用menu函数来实现

//test.cvoid menu()
{printf("----1. play----\n");printf("----0. exit----\n");
}
int main()
{int input;srand((unsigned int)time(NULL));//设置随机种子do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}system("cls");Sleep(100);} while (input);return 0;
}

🍤 菜单显示:
在这里插入图片描述

2.3 设计棋盘

想打印一个9x9的棋盘格实现游戏,我们就需要先创建两个二维数组(11x11),一个存放布置好的雷,一个存放排查出的雷的信息。

为什么是11x11?
考虑到棋盘边缘的位置,周围并不能的格子不能都满足8个,所以为了防止在统计坐标周围的雷的个数的时候越界,所以让数组设计为11x11,这里的11x11并不会全部打印出来

在这里插入图片描述

char mine[ROWS][COLS];//存放布置好的雷
char show[ROWS][COLS];//存放排查出的雷的信息

仔细观察就会发现,这里的数组大小为什么是ROWSxCOLS***,而不是11x11*呢?

在下面设计棋盘时,我们的大小与这里是相同的,而为了后期可以方便的调整大小,我们就在game.h文件中就定义这两个全局变量的大小

🍤 代码实现:

#define ROW 9//显示的棋盘大小
#define COL 9#define ROWS ROW+2//棋盘真正大小
#define COLS COL+2

2.3.1 初始化棋盘

//game.cvoid InitBoard(char board[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++){board[i][j] = set;}}
}

🍤 调用:

//test.cvoid game()
{char mine[ROWS][COLS];//存放布置好的雷char show[ROWS][COLS];//存放排查出的雷的信息//初始化棋盘//1.mine数组最开始全‘0’、//2.show数组最开始全‘*’InitBoard(mine,ROWS,COLS,'0');InitBoard(show,ROWS,COLS,'*');
}

2.3.2 打印棋盘

DisplayBoard函数实现棋盘打印,为了玩家有更好的游戏体验,我们在棋盘格的最顶端和最左边提示坐标信息,方便玩家快速的锁定行列数。

//game.cvoid DisplayBoard(char board[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++){printf("%d ", i);//最左边打印行数int j = 0;for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}

打印棋盘时,只用打印出9x9大小的棋盘格

//打印棋盘
DisplayBoard(show, ROW, COL);//打印棋盘函数调用

🍤运行结果:

在这里插入图片描述

2.4 布置雷

在game.h文件中先定义全局变量EASY_COUNT,控制雷的数量

#define EASY_COUNT 10

在布置雷时,要先生成随机坐标,然后判断该坐标是否可以放雷

  • rand函数产生随机值
  • 每一个格子只能存放一个雷,前面初始化棋盘时,已经将所有的格子(11x11)全初始化为’0’,所以在布置雷,只能在为’0’的格子中存放
//game.cvoid SetMine(char board[ROWS][COLS], int row, int col)
{//布置雷//生成随机的坐标,布置雷int count = 10;while (count){int x = rand() % row + 1;//为了控制随机值大小,防止越界,范围:1-9int y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';count--;}}
}

🍤 调用头文件:

//game.h#include<stdlib.h>
#include<time.h>

2.5 排除雷

玩游戏选择坐标时,会有三种结果:

1. 选择存放了雷的坐标,游戏结束

玩家先输入坐标,该坐标行列大小在定义的范围内,然后判断是否是存放了雷的坐标。

在之前我们已经初始化了所有位置都是‘0’,只有随机存放了雷的位置,会变为‘1’,而当输入的坐标的内容为‘1’时,即玩家踩雷了,游戏结束。

2. 选择了安全的坐标,且显示周围8个坐标的雷的数量

如果输入的坐标的内容为‘0’,则计算出周围8个位置的雷的数量,并打印在此坐标上。

在这里,我们用GetMineCount函数单独计算,返回雷的数量

假设已知坐标x,y,其他周围的坐标就可以表示为:
在这里插入图片描述

🍤 代码实现:

//game.cint GetMineCount(char mine[ROWS][COLS],int x,int y)
{return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]+ mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0');
}

🍩游戏胜利的实现

定义一个变量win,在每次选择非雷的坐标后累加1,当win=棋盘总个数(9x9)-存放了雷的个数,即win==row* col - EASY_COUNT,也就排除了所有的雷,游戏胜利。

3. 坐标选择错误

当我们选择的行列坐标超出设定的范围,就提示玩家输入错误,重新输入。

printf("坐标非法,重新输入!\n");

2.5.1 代码实现

//game.cvoid FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0, y = 0;int win = 0;while (win<row*col-EASY_COUNT){printf("请输入要排查的坐标,如:1 2:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了");DisplayBoard(mine, ROW, COL);break;}else{int count=GetMineCount(mine, x, y);//统计周围8个位置的雷的数量show[x][y] = count + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("坐标非法,重新输入!\n");}}if(win == row* col - EASY_COUNT){printf("恭喜你,排雷成功…^-^…");DisplayBoard(mine, ROW, COL);}
}

3. 总结

3.1 game.h文件所有内容

#include<stdlib.h>
#include<time.h>
#include<windows.h>//声明Sleep函数
#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);

3.2 game()游戏函数整体

//test.cvoid game()
{char mine[ROWS][COLS];//存放布置好的雷char show[ROWS][COLS];//存放排查出的雷的信息//初始化棋盘//1.mine数组最开始全‘0’、//show数组最开始全‘*’InitBoard(mine,ROWS,COLS,'0');InitBoard(show,ROWS,COLS,'*');//打印棋盘DisplayBoard(show, ROW, COL);//1.布置雷SetMine(mine,ROW,COL);//2.排查雷FindMine(mine, show, ROW, COL);
}

🍩注: 每一个.c文件最前面,需要用 #include "game.h" 进行声明

QQ录屏20230714001524


结束语

扫雷的实现就到这里了,感觉这篇文章有帮到你的话,点赞支持一下哟。
  我们下一篇文章再见。
在这里插入图片描述

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

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

相关文章

MySQL每日一练——MySQL多表查询进阶挑战

目录 1、首先创建表 t_dept: t_emp: 2、插入数据 t_dept表&#xff1a; t_tmp表: 3、修改表 4、按条件查找 1、首先创建表 t_dept: CREATE TABLE t_dept (id INT(11) NOT NULL AUTO_INCREMENT,deptName VARCHAR(30) DEFAULT NULL,address VARCHAR(40) DEFAULT NULL,P…

Python结巴中文分词笔记

&#x1f4da; jieba库基本介绍 &#x1f310; jieba库概述 Jieba是一个流行的中文分词库&#xff0c;它能够将中文文本切分成词语&#xff0c;并对每个词语进行词性标注。中文分词是自然语言处理的重要步骤之一&#xff0c;它对于文本挖掘、信息检索、情感分析等任务具有重要…

Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论

Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论 我们使用Linux作为服务器操作系统时&#xff0c;为了达到高并发处理能力&#xff0c;充分利用机器性能&#xff0c;经常会进行一些内核参数的调整优化&#xff0c;但不合理的调整常常也会引起意想不到的其他问题&#x…

Elasticsearch原理剖析

一、 Elasticsearch结构 Elasticsearch集群方案由EsMaster、EsClient和EsNode1、EsNode2、EsNode3、EsNode4、EsNode5、EsNode6、EsNode7、EsNode8、EsNode9进程组成&#xff0c;如下图所示&#xff0c;模块说明如表下所示。 说明如表&#xff1a; 名称说明ClientClient使用H…

Android系统启动流程分析

当按下Android系统的开机电源按键时候&#xff0c;硬件会触发引导芯片&#xff0c;执行预定义的代码&#xff0c;然后加载引导程序(BootLoader)到RAM&#xff0c;Bootloader是Android系统起来前第一个程序&#xff0c;主要用来拉起Android系统程序&#xff0c;Android系统被拉起…

C# Linq 详解四

目录 概述 二十、SelectMany 二十一、Aggregate 二十二、DistinctBy 二十三、Reverse 二十四、SequenceEqual 二十五、Zip 二十六、SkipWhile 二十七、TakeWhile C# Linq 详解一 1.Where 2.Select 3.GroupBy 4.First / FirstOrDefault 5.Last / LastOrDefault C# Li…

排序子序列,倒置字符串讲解(图文并茂)

目录 1.排序子序列 2.倒置字符串 1.排序子序列 排序子序列_牛客笔试题_牛客网 (nowcoder.com) 首先题干中提到非递增序列和非递减序列&#xff0c;那么我们就要先弄明白什么是上述2种序列&#xff1a; 非递增序列&#xff1a;a[i] > a[i1] 如&#xff1a;3 2 1 或者 3 3 …

使用docker简单创建一个python容器

/root/docker_python目录结构&#xff1a; . |-- demo | -- main.py -- docker-compose.ymlmain.py内容&#xff1a; # codingutf-8 # -*- coding: utf-8 -*-if __name__ __main__:print("hello world")docker-compose.yml内容&#xff1a; version: "3&q…

注册中心技术Eureka、Nacos

说明&#xff1a;在微服务框架中&#xff0c;各个服务之间都是独立的。理论上来说&#xff0c;各个服务之间是可以直接通信的&#xff0c;但实际上因为服务之间通信需要管理和规划&#xff0c;如请求怎么负载均衡、请求怎么降级处理等等&#xff0c;所以就需要使用一个技术&…

Linux 常用命令

认识 Linux 目录结构 Linux 系统中&#xff0c;磁盘上的文件和目录被组成一棵目录树&#xff0c;每个节点都是目录或文件 Linux 是一个树形目录结构。Linux 上没有盘符概念&#xff0c;不分 C 盘等&#xff0c;根目录 \ 的地位相当与 Java 的 Object ——几个特殊的目录&…

uniapp快速开发小程序全流程

uniapp快速开发小程序全流程 完整项目代码&#xff1a;https://gitee.com/Zifasdfa/ziyi-app 欢迎fork与star 1 项目效果及环境准备 1.1 项目效果 本文主要使用uniapp实现一个简单的app应用 1.2 环境准备&项目初始化 ①node环境&#xff1a;去node.js官网下载稳定版的nod…

微服务之Eureka服务注册中⼼

关于务注册中⼼服 服务注册中⼼本质上是为了解耦服务提供者和服务消费者,尽可能量使两者联系可控在一定的范围外 1.在父项目下下引入 Spring Cloud 依赖 <dependencyManagement> <dependencies> <!-- SCN --> <dependency> <groupId> org.sp…

【网站 全选和单选】js 实现-点击全选按钮时,所有的按钮都会被选中或取消选中。

要实现的效果如图&#xff1a; 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…

Loki+promtail+Grafana监控docker容器日志

目标&#xff1a;监控docker容器的日志&#xff0c;适用于生产环境 效果&#xff1a; 需要的工具&#xff1a;Loki&#xff0c;promtail&#xff0c;Grafana 通过安装promtail容器收集日志&#xff0c;并把日志发送给loki存储处理&#xff0c;由Grafana展示日志。 参考官网的…

Windows bat隐藏运行窗口的几种方案

文章目录 一、背景二、测试数据三、隐藏bat运行窗口方案1. 使用VBScript脚本2. 使用mshta调用js或vbs脚本3. 将bat编译为exe程序4. 使用任务计划程序 一、背景 有些程序在执行批处理脚本时&#xff0c;可能会看到dos窗口&#xff0c;或者看到窗口一闪而过。如果批处理脚本执行…

(EMQX)STM32L+BC20+MQTT协议传输温湿度,ADC,电压,GPS数据到EMQX

1、材料准备 准备以下材料 2、设备连接 2.1 插入物联网卡&#xff0c;天线 首先把BC20核心板从开发板上拆下来 然后将物联卡放置在BC20核心板内 物联卡放置完成将BC20核心板重新插入到开发板内&#xff08;注意不要弄错方向&#xff09; 同时接入天线 2.2 连接ST-Link仿真…

Python 算法基础篇:大O符号表示法和常见时间复杂度分析

Python 算法基础篇&#xff1a;大 O 符号表示法和常见时间复杂度分析 引言 1. 大 O 符号表示法 a ) 大 O 符号的定义 b ) 示例代码 2. 常见时间复杂度分析总结 引言 在分析和比较算法的性能时&#xff0c;时间复杂度是一项重要的指标。而大 O 符号表示法是用来描述算法时间复杂…

动态规划01背包之416分割等和子集(第10道)

题目&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例&#xff1a; 解法&#xff1a; 先复习一下01背包问题&#xff1a; dp[i][j]的含义&#xff1a;从下标为[0-i]的物品里…

Linux->初识计算机网络

目录 前言&#xff1a; 1 网络发展背景 2 协议 2.1 网络协议初识 2.2 协议分层 2.3 OSI、TCP/IP层状模型 2.4 协议和操作系统的关系 2.5 根据协议栈的通信 3 网络中的地址管理 前言&#xff1a; 本篇当中没有任何关于网络编程的讲解&#xff0c;全部是对网络的宏观理解…

【数学建模】 灰色预测模型

数学建模——预测模型简介 https://www.cnblogs.com/somedayLi/p/9542835.html 灰色预测模型 https://blog.csdn.net/qq_39798423/article/details/89283000?ops_request_misc&request_id&biz_id102&utm_term%E7%81%B0%E8%89%B2%E9%A2%84%E6%B5%8B%E6%A8%…