| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 两百行代码实现简易扫雷 (详解) -> 正文阅读 |
|
[C++知识库]两百行代码实现简易扫雷 (详解) |
首先进行规化,三子棋的实现中已说明过的点在此处不在赘述 一.菜单 相关作用在实现三子棋时已进行过概述,此处直接上代码:
二.菜单选项基本运行逻辑 同上,直接上代码
三.game()函数-游戏的实现 扫雷游戏的实现同样可分为以下几个部分:? 1.棋盘实现 ?2.输入实现-玩家 3.输赢判断 一.棋盘实现 1.那么效仿三子棋,直接定义一个棋盘,然后进行初始化,放置地雷,打印......等等,是否有哪里不对?? 我们玩一次扫雷时,地雷的位置应该是确定的,但是作为玩家我们应该是看不见的,而我们要做的就是进行排雷。试想一下,假如就这么定义一个棋盘实现功能,那地雷位置生成后,要进行棋盘打印,如何让地雷对玩家来说不可视呢? 比较好的思路是,创建两个相同大小的棋盘,一个为"实际棋盘",存放着地雷的信息,一个为"影棋盘",用于在每次排雷后打印出来给玩家提供信息。
此处需要注意的是棋盘大小的设置。假如我们需要对9*9的棋盘进行排雷,那么我们应该创建多大的数组呢? 9*9??如果我们这样创建的话,试想一下,当我们进行排雷时,应对周围8个格子中的地雷数目进行检视并打印,若排查格位于中央,自然写个函数对周围8格计数即可。但若排查格位于边缘,此时想通过这个函数对周围8格计数,就会造成数组越界! 因此最好的做法是,创建一个11*11的数组,使外面形成一圈"保护圈",虽然我们并不需要对其进行打印和排查。 2.棋盘初始化,遍历数组即可,不再赘述,上代码
需注意对2个数组均应调用此函数初始化 3.棋盘打印,与三字棋思路一致,依旧是分割线与棋盘列,只不过样式稍有差异 注意我们的数组大小为(ROW+2)*(COL+2),而实际上我们想要的雷阵大小为(ROW)*(COL),最外圈元素为无效元素。因此我们只需产生(1~ROW)*(1~COL)的随机数即可,下标为1即为数组第2行,下标为ROW即为倒数第2行,正好为除去外圈的雷阵
不同点在于,为了方便玩家输入坐标,在最开头采用简单循环实现列数信息打印,循环内printf语句实现行数信息打印,效果如下: ?4.随机生成雷
此处为便于修改,地雷数目也用标识符变量定义 以下为随机产生地雷函数:
?与三子棋类似,用rand()函数产生随机数并判断合法性,若合法(即此处还未放置地雷),则修改数组元素,此处将字符'*'作为地雷。每修改一次count计数器自减1,当count==0时,则说明指定地雷数已全部放置,循环结束。 二.玩家输入/判断输赢 由于扫雷只需玩家输入->判断输赢->玩家输入->判断输赢,而非三子棋玩家和电脑均需判断输赢,此处将玩家输入和判断输赢集成为一个函数。即玩家输入后,判断输赢。若胜负未分,则继续输入,否则给出结果。
基本逻辑即:玩家输入,判断合法性,若不合法则重新输入 若合法,则检视其是否为雷,若为雷,则玩家输,游戏结束。 否则不为雷,需要检视这个排雷格周围的8个元素,并将其打印在"影棋盘"上给玩家提供信息,即修改"影棋盘"->打印"影棋盘" 此处先岔开话题,让我们来实现这个检视周围雷数的功能。只需遍历周围8格即可,若为存在格中元素为'*',则计数器count自增1,最终返回计数器count的值 (此处循环对本排查格中元素也进行了检索,此时本格必不为雷,不影响结果)
回到前文,调用此函数获得周边雷数信息后,直接修改"真实棋盘"和"影棋盘"的值,注意棋盘为字符数组创建,而此函数返回值为整型int,因此修改时应为x=y+48; 48为字符0的ascii码值,则x为整型变量y的字符形式。 之后判断是否满足排雷成功条件,即"影棋盘"中剩余' '元素的个数是否已经等于雷数Num_Boom,若已经相等,那么剩下的' '必然全都是雷(不然游戏在此之前就结束了),用is_full()函数进行计数
至此,若满足胜利条件,则进入下方的if语句,提示扫雷成功,跳出循环,简单的扫雷已经可以运行起来了 但是,当我们玩玩后就会发现,我们平时玩的扫雷,有时候我们排查一个坐标,电脑会自动在附近展开一大片,给了更多的有效信息,而我们的代码至此并没有自动展开功能。如何实现此功能呢? 首先我们要明白自动展开的条件:当排查坐标周围雷数为0时,即对周围8个待排格进行检索并排查,不为0时则直接提供信息。?那么当对周围待排格进行排查操作时,同样有当排查坐标周围雷数为0时,即又对周围8个待排格进行检索并排查......... 这显然形成了一个递归。因此我们用递归算法来实现。 当雷数为0时和不为0时情况不同,故需要if语句进行判断。雷数不为0时则进行前文操作即可,若雷数为0时则调用自动展开函数
即这一段代码。 接下来对自动展开函数auto_open进行实现,由于需要对2个棋盘进行修改,故需传参2个函数及坐标x,y。下面为实现:
实现逻辑为:1.判断坐标是否合法(否则递归会到棋盘外圈,因此棋盘所有元素都将被自动排查,就是这个一开始没写,忽略了外圈元素,使我绞尽脑汁的想bug出在哪了?) 2.判断此元素是否为雷 若坐标不合法或元素为雷,那当然不需要自动展开 若坐标合法且不为雷,则此时对此坐标进行排查,并将信息输入数组,接下来判断,若雷数不为0,则不需要自动展开,此次函数结束。雷数为0,则对周围8个元素进行函数递归即可 至此自动展开函数auto_open便已经实现
game()函数对这些功能的函数进行调用,完美的实现了扫雷的功能。 最后附上头文件:
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 7:16:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |