实现Windows经典游戏——扫雷

扫雷游戏以前是windows的内置小游戏,相信不少人都玩过这么一款游戏。

1.扫雷游戏规则

以9*9的简单模式为例,游戏开始时系统会生成10颗雷随机分布在这9*9的格子当中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yv29OzCb-1720367081560)(https://i-blog.csdnimg.cn/direct/c1409f3976d3488fa524df816802e513.png)]

当你点开其中的一格,将会显示该点周围8格的雷的数量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mxlAwFER-1720367081562)(https://i-blog.csdnimg.cn/direct/011bc53e7d6d476ba2704bac277ef768.png)]
游戏的胜利条件就是排查所有的雷。

2.游戏实现

每次游戏都是要有菜单的,下面会写一次功能简单的菜单.仅支持游玩和退出。

2.1 简单的游戏菜单

#include <stdio.h>
void menu()
{printf("***********************\n");printf("******** 1.play    ****\n");printf("******** 0.exit    ****\n");printf("***********************\n");
}
int main()
{int input = 0;do{menu();//打印菜单printf("请输入>");scanf("%d",&input);switch(input){case 1:break;case 0:break;default:printf("请重新输入\n");break;}}while(input);return 0;
}

2.2游戏逻辑

当玩家通过菜单进入到游戏中,我们要创建一个棋盘来玩游戏啊,那么棋盘要怎么生成呢?利用字符数组来输出,以9*9的棋盘为例,我们将字符数组的长和宽定义为11*11.为什么要这么写呢,目的是为了方便后续对棋盘位置周围雷数的计算。我们先画一个棋盘。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4M7t12lU-1720367081563)(https://i-blog.csdnimg.cn/direct/56973bea09754273b0fa2293c0507b93.png)]
统计图中标有红色圆圈周围有多少雷,难道我们还要去特别判断一下位置吗,这样会让游戏的实现变得繁琐且无意义,所以我们要改变思路,为这个棋盘加上两行两列。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Jgm4waT-1720367081563)(https://i-blog.csdnimg.cn/direct/11b891dc76ad4dab8ac49ae35a0c772e.png)]
加上的两行两列上不会布置雷,这样统计棋盘位置周围有多少颗雷就很方便了,所有的棋盘位置都是一样计算。

//test.c
void game()
{char mine[11][11];//利用字符型数组表示棋盘char show[11][11];
}

为什么要用到两个字符型数组呢?

我们要知道扫雷棋盘中的每个格子都是有两种信息的,在没点开前每个格子就已经存放了周围8格的雷的数量的信息,除此之外还有要隐藏信息的字符格覆盖信息。两种信息在不使用结构体的情况下是无法表示的,所以我使用了两格字符数组,一个存放地雷信息,一个存放覆盖信息的字符。

为了后续代码的可维护性我们要定义标识常量

//game.h
#define Row 9
#define Col 9#define Rows Row+2
#define Cols Col+2//test.c
void game()
{char mine[Rows][Cols] = {0};//利用字符型数组表示棋盘char show[Rows][Cols] = {0};
}
//...

2.3 棋盘初始化

我们将棋盘分为两个,一个是展示棋盘(给玩家看的),一个是藏雷棋盘(不给玩家看的)。
展示棋盘的初始化我们全初始化为’*’ 藏雷棋盘全部初始化为‘0’.

//game.c
//初始化展示棋盘
void InitBoard(char board[Rows][Cols],int rows,int cols,char ch)
{for(int i = 0;i<rows;++i){for(int j = 0;j<cols;++j){board[i][j] = ch;//ch == '*'}}
}
//初始化藏雷棋盘
void InitBoard(char board[Rows][Cols],int rows,int cols,char ch)
{for(int i = 0;i<rows;++i){for(int j = 0;j<cols;++j){board[i][j] = ch;//ch == '0'}}
}
//test.c
void game()
{char mine[Rows][Cols] = {0};//利用字符型数组表示棋盘char show[Rows][Cols] = {0};//初始化棋盘InitBoard(mine,Rows,Cols,'0');InitBoard(show,Rows,Cols,'*');
}

2.4 打印棋盘

为方便玩家找到棋盘各个位置的坐标,我们会打印相应的数字对玩家进行提示,便于玩家找到坐标。

void PrintBoard(char board[Rows][Cols],int row,int col)
{printf("0 1 2 3 4 5 6 7 8 9\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");}
}

2.5 随机布雷

初始化完棋盘后我们要往藏雷棋盘里面开始布置地雷了,为了达到随机布置的效果,我们要利用到rand函数。因为这了我们用了rand函数,所以我必须在前面写上srand来给rand函数提供随机种子,为此我们还需要用到time为srand提供数字来帮助它输出随机种子.

int main()
{int input = 0;srand((unsigned int)time(NULL));//为rand提供随机种子do{menu();//打印菜单printf("请输入>");scanf("%d",&input);switch(input){case 1:break;case 0:break;default:printf("请重新输入\n");break;}}while(input);return 0;
}

开始布置雷

//game.h
#define Row 9
#define Col 9#define Rows Row+2
#define Cols Col+2#define MineNum 10//藏雷个数//game.c
void SetMine(char mine[Rows][Cols],int row,int col)
{int count = MineNum;//布置10颗雷int x = 0;int y = 0;while(count){x = rand()%row+1;//产生的x范围为1~9y = rand()%col+1;if(mine[x][y]=='0'){mine[x][y] = '1';count-=1;}}
}

2.6 玩家操作

布置完了雷后玩家就可以开始操作了,玩家扫雷利用的棋盘的坐标来排雷。

void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col)
{int x = 0;int y = 0;int count = row * col - MineNum;//正常格子的数目while (count){printf("利用坐标进行排雷>");scanf("%d %d", &x, &y);if (x<1 || y<1 || x>row || y>col){printf("坐标非法!\n");}else if (show[x][y] != '*'){printf("该坐标已被选择\n");}else{//判断所选坐标是不是雷,如果是雷则游戏失败if (mine[x][y] == '1'){printf("你被炸死了!\n");PrintBoard(mine, row, col);break;}else{//不是雷就开始计算周围雷的数目count -= 1;int ret = MineCount(mine, x, y);show[x][y] = '0' + ret;//打印棋盘展示PrintBoard(show, row, col);}}}if (count == 0){printf("扫雷成功!\n");}else{printf("扫雷失败!\n");}
}//计算周围雷的数目
int MineCount(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] - '0' * 8;
}

3.代码整合

//game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define Row 9
#define Col 9#define Rows Row+2
#define Cols Col+2#define MineNum 10void InitBoard(char board[Rows][Cols], int rows, int cols, char ch);void PrintBoard(char board[Rows][Cols], int row, int col);void SetMine(char mine[Rows][Cols], int row, int col);void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col);int MineCount(char mine[Rows][Cols], int x, int y);//game.c
#include "game.h"void InitBoard(char board[Rows][Cols], int rows, int cols, char ch)
{for (int i = 0; i < rows; ++i){for (int j = 0; j < cols; ++j){board[i][j] = ch;//ch == '*'}}
}void PrintBoard(char board[Rows][Cols], int row, int col)
{printf("0 1 2 3 4 5 6 7 8 9\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)
{int count = MineNum;//布置10颗雷int x = 0;int y = 0;while (count){x = rand() % row + 1;//产生的x范围为1~9y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count -= 1;}}
}void Demining(char mine[Rows][Cols], char show[Rows][Cols], int row, int col)
{int x = 0;int y = 0;int count = row * col - MineNum;//正常格子的数目while (count){printf("利用坐标进行排雷>");scanf("%d %d", &x, &y);if (x<1 || y<1 || x>row || y>col){printf("坐标非法!\n");}else if (show[x][y] != '*'){printf("该坐标已被选择\n");}else{//判断所选坐标是不是雷,如果是雷则游戏失败if (mine[x][y] == '1'){printf("你被炸死了!\n");PrintBoard(mine, row, col);break;}else{//不是雷就开始计算周围雷的数目count -= 1;int ret = MineCount(mine, x, y);show[x][y] = '0' + ret;//打印棋盘展示PrintBoard(show, row, col);}}}if (count == 0){printf("扫雷成功!\n");}else{printf("扫雷失败!\n");}
}int MineCount(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] - '0' * 8;
}//test.c
void game()
{char mine[Rows][Cols] = { 0 };//利用字符型数组表示棋盘char show[Rows][Cols] = { 0 };//初始化InitBoard(mine, Rows, Cols, '0');InitBoard(show, Rows, Cols, '*');//打印棋盘PrintBoard(show, Row, Col);//布置地雷SetMine(mine, Row, Col);//PrintBoard(mine, Row, Col);Demining(mine, show, Row, Col);
}
void menu()
{printf("***********************\n");printf("******** 1.play    ****\n");printf("******** 0.exit    ****\n");printf("***********************\n");
}
int main()
{int input = 0;srand((unsigned int)time(NULL));//为rand提供随机种子do{menu();//打印菜单printf("请输入>");scanf("%d", &input);switch (input){case 1:game();break;case 0:break;default:printf("请重新输入\n");break;}} while (input);return 0;
}

效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qL1oHQKD-1720367081564)(https://i-blog.csdnimg.cn/direct/6f19b7271d3c4f1caa055b9dc1c2fff5.gif)]
关于为什么没有展开
对于让周围没有雷的个格子展开,你们可以来实现,展开格子的特点就是:

  1. 该坐标不是雷,周围没有雷 该坐标也没有被展开过(用递归展开)

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

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

相关文章

中英双语介绍意大利(Italy):有哪些著名景点、出名品牌?

中文版 意大利概述 意大利&#xff0c;位于欧洲南部&#xff0c;是一个以其悠久的历史、丰富的文化遗产和美丽的自然风光而闻名的国家。意大利不仅是文艺复兴的发源地&#xff0c;还拥有众多世界著名的城市、景点和品牌。 著名城市 罗马&#xff08;Rome&#xff09;&#x…

DataWhale AI夏令营 对话分角色要素提取挑战赛 学习笔记

大模型技术概览 大模型技术是指利用庞大的数据集训练出的深度学习模型&#xff0c;这些模型在处理复杂自然语言处理&#xff08;NLP&#xff09;任务方面表现出色&#xff0c;例如文本分类、情感分析、机器翻译等。在对话系统中&#xff0c;大模型技术通过理解和生成更加自然和…

CosyVoice多语言、音色和情感控制模型,one-shot零样本语音克隆模型本地部署(Win/Mac),通义实验室开源

近日&#xff0c;阿里通义实验室开源了CosyVoice语音模型&#xff0c;它支持自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;在多语言语音生成、零样本语音生成、跨语言声音合成和指令执行能力方面表现卓越。 CosyVoice采用了总共超15万小时的数据训练&#…

【2024_CUMCM】时间序列算法ARMA

目录 2023-c-问题二 问题分析 介绍 单位根检验 白噪声检验 自相关和偏自相关图 利用信息准则定阶 构建AMIMA模型 D-W检验 预测 代码 2023-c-问题二 问题分析 ARMA适合多个领域的时间序列分析&#xff0c;不同时间的定价策略属于这类问题。 介绍 ARMA模型&…

C++入门7——string类详解

目录 1.什么是string类&#xff1f; 2.string类对象的常见构造 2.1 string(); 2.2 string (const char* s); 2.3 string (const string& str); 2.4 string (const string& str, size_t pos, size_t len npos); 2.5 string (const char* s, size_t n); 2.7 验证…

vue2项目迁移vue3与gogocode的使用

#背景 公司有个项目使用vue2jswebpack框架开发的&#xff0c;由于该项目内部需要安扫&#xff0c;导致很多框架出现了漏洞需要升级&#xff0c;其中主要需要从vue2升vue3,但是重新搭框架推翻重做成本太高&#xff0c;于是找到了gogocode。 #升级步骤踩坑 1. 安装 gogocode插…

牛客链表题:BM2 链表内指定区间反转

描述 将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转&#xff0c;要求时间复杂度 &#x1d442;(&#x1d45b;)O(n)&#xff0c;空间复杂度 &#x1d442;(1)O(1)。 例如&#xff1a; 给出的链表为 1→2→3→4→5→&#x1d441;&#x1d448;&#x1d43f;&#x…

分表分库是一种数据库架构的优化策略,用于处理大规模数据和高并发请求,提高数据库的性能和可扩展性。

分表分库是一种数据库架构的优化策略&#xff0c;用于处理大规模数据和高并发请求&#xff0c;提高数据库的性能和可扩展性。以下是一些常见的分表分库技术方案&#xff1a; 1. **水平分表&#xff08;Horizontal Sharding&#xff09;**&#xff1a; - 将单表数据根据某个…

【机器学习】基于线性回归的医疗费用预测模型

文章目录 一、线性回归定义和工作原理假设表示 二、导入库和数据集矩阵表示可视化 三、成本函数向量的内积 四、正态方程五、探索性数据分析描述性统计检查缺失值数据分布图相关性热图保险费用分布保险费用与性别和吸烟情况的关系保险费用与子女数量的关系保险费用与地区和性别…

GDP播放器 驱动视频播放器 PHP 系统源码 v4.4.3

最重要的是我们自己开发了源代码&#xff0c;因此无论您在使用此工具时遇到什么问题&#xff0c;我们都会快速解决。这个版本演示 分别支持PHP7.4/8.1/8.2三个版本 演示地址

轻松驾驭开发之旅:Maven配置阿里云CodeUp远程私有仓库全攻略

文章目录 引言一、为什么选择阿里云CodeUp作为远程私有仓库&#xff1f;二、Maven配置阿里云CodeUp远程私有仓库的步骤准备工作配置Maven的settings.xml文件配置项目的pom.xml文件验证配置是否成功 三、使用阿里云CodeUp远程私有仓库的注意事项 引言 在软件开发的世界里&#…

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日&#xff0c;阿里通义实验室发布开源语音大模型项目FunAudioLLM&#xff0c;而且一次包含两个模型&#xff1a;SenseVoice和CosyVoice。 CosyVoice专注自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;支持中英日粤韩5种语言的生成&#xff0c;效果显著优于…

强化学习与控制模型结合例子

强化学习与模型控制结合 强化学习(Reinforcement Learning, RL)与控制模型结合,可以通过整合传统控制理论和现代RL算法,利用控制模型提供的动态信息和稳定性保障,同时利用RL的学习能力优化控制策略。这种结合的方式被称为模型辅助强化学习(Model-Assisted Reinforcement…

分子AI预测赛Task4笔记(结束)

话不多说&#xff0c;直接上官方链接&#xff1a;‌​​​‍&#xfeff;​⁠​‌​‍​​&#xfeff;​‌​⁠‬​&#xfeff;‬​​‌​​​​‬‬​​​​‍⁠‍‌​&#xfeff;⁠Task3&#xff1a;进阶baseline详解 - 飞书云文档 (feishu.cn)Task4&#xff1a;持续尝试&…

计算机项目介绍汇总——项目展示及购买

计算机项目介绍汇总 本文没有具体的项目内容介绍&#xff0c;只罗列我所发布的所有的项目的代码&#xff0c;主要包括Java和Python两门语言开发的相关项目&#xff0c;由于时间和个人精力问题&#xff0c;部分项目将在后续逐步更新。由于发布的项目都是投入了本人精力和时间&am…

C++左值右值

在C中&#xff0c;左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09;是表达式分类的关键概念&#xff0c;它们主要影响表达式的赋值、函数调用以及操作符的使用方式。这些概念在C11及以后的版本中变得更加重要&#xff0c;因为引入了移动语义和右值引用…

妈妈带女儿美在心里

在这个充满温情与惊喜的午后&#xff0c;阳光温柔地洒落在每一个角落&#xff0c;仿佛连空气弥漫着幸福的味道。就在这样一个平凡的时刻&#xff0c;一段关于爱与成长的温馨画面&#xff0c;悄然在网络上绽放&#xff0c;引爆了无数人的心弦——#奚梦瑶2岁女儿身高#&#xff0c…

Android高级——智能指针

智能指针 智能指针是一种能够自动维护对象引用计数的技术 引用了一个实际使用的对象&#xff0c;而不是一个指针智能指针构造时&#xff0c;增加它所引用的对象的引用计数智能指针析构时&#xff0c;减少它所引用的对象的引用计数 但智能指针无法解决循环引用问题&#xff0…

【CSharp】获得结构体内字段占用的内存大小

【CSharp】获得结构体内字段占用的内存大小 1.背景2.代码3.说明1.背景 C#结构体:从C/C++时代迁移过来的经典。 struct结构体和class类非常相似,他们都能定义数据结构。 可以理解成class类是struct结构体的升级版。 博主以为最大的区别:struct结构体是值类型,而class类是引…

【Linux进程】命令行参数 环境变量(详解)

目录 前言 1. 命令行参数 什么是命令行参数? 2. 环境变量 常见的环境变量 如何修改环境变量? 获取环境变量 环境变量的组织方式 拓展问题 导入环境变量 3. 本地变量* 总结 前言 在使用Linux指令的时候, 都是指令后边根命令行参数, 每个指令本质都是一个一个的可执行程…