【迷宫大师】一个利用Qt/C++写的迷宫小游戏 (文末附源码下载链接)

您所在的位置:网站首页 迷宫的迷怎么写的 【迷宫大师】一个利用Qt/C++写的迷宫小游戏 (文末附源码下载链接)

【迷宫大师】一个利用Qt/C++写的迷宫小游戏 (文末附源码下载链接)

2024-07-16 00:05| 来源: 网络整理| 查看: 265

本文为我个人原创,首发于我的个人博客:http://migod.top/176.html,转载请注明出处!

项目介绍

迷宫大师是本人的C++程序设计的大作业,是一个可视化的迷宫小游戏。可视化界面基于Qt5,使用Qt Creator开发。

项目主要有如下特点:

对Qt自带的控件进行了二次封装,以实现更加美观的游戏效果; 为了更方便的设计关卡,配套开发了可视化的迷宫地图编辑器,并实现了复杂迷宫地图的深度优先生成; 迷宫游戏实现了文件的读写,实现了导出和读取玩家自制地图,并加入了通过DFS绘制迷宫出路的功能;

项目的设计树形图如下:

1597290324959

演示截图 主界面

img

选择关卡界面

img

游玩界面

img

游玩界面 – 自动寻路

(注明:左下角的终点无法到达,寻找到了右上角的终点)

img

游玩界面 – 胜利/失败

imgimg

编辑地图界面(可以用鼠标点击Tile来更改地图图块的状态)

img

编辑地图界面 – 随机生成

img

开发思路 使用Qt GUI框架

Qt是一个成熟的跨平台的C++图形用户界面应用程序框架。选择Qt的作为GUI框架相对于选择OpenGL可以节省很多不必要的开发时间,提升开发效率的同时保证稳定性。Qt提供了一些工具类,比如QString,QDebug等。笔者选择使用Qt自带的这些类而不是C++本身提供的string,cin,cout这些工具类,以保证程序内部信息流交互更加方便。

封装图片按钮类 ImgButton

我们手动封装一个自己的图片按钮类:ImgButton。这个类继承QPushButton。

利用这个类和笔者自己用Photoshop制作的按钮图片素材,我们可以实现比Qt自带的QPushButton更美观的按钮。笔者还为按钮添加了音效。

笔者利用Photoshop自己制作的部分按钮素材如下(具体见源代码res文件夹):

主窗口(标题界面)MainWindow

主窗口将选关窗口和地图编辑窗口作为数据成员,便于进行与这些界面间的切换。

封装地图图块类 Tile

我们继承QPushButton封装一个地图图块类Tile,之后利用这个类和图片素材绘制迷宫地图。利用网上的图像素材,笔者制作的地图图块如下(按顺序为墙、路、起点、终点):

1597290698871 1597290704402 1597290713146 1597290716907

 

迷宫数据工具类 MazeData

设计迷宫数据文件:Unicode编码的文本文件,第一行n为迷宫大小(迷宫宽高相等),之后n行是迷宫地图信息。

如:

110300000000001111111110000000000100111111101001000001010010111110100101000101001010211010010100000100101111111000000000000

为了方便我们在编辑窗口和游玩窗口快速读写迷宫文件,笔者设计了一个迷宫数据工具类MazeData。我们利用二维数组保存迷宫数据。

地图编辑窗口 MapEditWindow

加入地图编辑窗口,既方便笔者自己制作迷宫关卡,也为玩家提供了扩展游戏玩法和难度的可能性。通过笔者封装的Tile类,可以实现鼠标点击绘制。

地图编辑窗口类包含了本程序的核心难点之一:迷宫地图深度优先生成算法。这个算法使用在此类的createMaze成员函数里。算法的伪代码如下:

设置 迷宫内所有点 为 墙壁设置 (1,1)点 为 路把 (1,1)点 入栈设置 迷宫连通标志 为 未连通如果  迷宫连通标志 为 未连通,执行循环: 设置 当前点 为 栈内最后一个点 #因为最后一个储存的是最深的 寻找 当前点 潜在的邻居 #潜在邻居上下左右的墙都是未打通的,且和当前点只隔了一个墙 如果 存在潜在的邻居: 设置 任意一个 潜在的邻居 为 真邻居 打通 当前点 与 真邻居 之间的墙 把  真邻居 入栈 否则:#该路径没有合适的邻居,去除最后一个不满足要求的,往上一个点寻找 出栈 判断地图是否连通,把结果储存到 迷宫连通标志

算法流程图如下:

1597290914326

选关窗口 ChooseLevelWindow

选关窗口将游玩窗口为该类的数据成员,便于窗口间切换。除了内置关卡,笔者在选关窗口增加了读取地图的按钮,以期拓展游戏的可玩性。

游玩窗口 PlayWindow

游玩窗口是游戏的核心窗口。游玩窗口实现玩家移动功能、判定是否存在通路功能、绘制通路功能、游戏倒计时功能,还增加了成功或者失败时的简单动画。

地图编辑窗口类包含了本程序的另一个难点:深度优先搜索迷宫通路(笔者采用了利用栈的非递归的实现)。这个算法使用在此类的findPosssibleWay成员函数里。算法的思路如下:

首先起点入栈pos_stack,只要pos_stack中有值,说明还有待遍历的位置,继续遍历 进入循环体,说明该点被遍历,该点加入possible_path栈 判断该点是否为出口,如果是,已经发现一条可行路线,返回true`,函数结束 如果循环向下执行,说明不是终点,将该点标记为已经走过 从该点探索与该点连接的,其他可走的位置,入栈 如果没有任何点入栈,说明是死路或者正在回退中,进行一步回溯,即出栈 如果离开循环体,说明没有通路,返回false

以上为各模块功能介绍及设计思路,具体实现见源代码。

总结

1、大作业完成过程中存在的问题、解决方法以及我的心得体会

在设计迷宫大师时,我计划要添加一个GUI的迷宫编辑的功能,但一开始一直没有想清楚要如何实现非文本输入的方式编辑迷宫。后来我在对Qt有一定了解之后,我发现我可以对QPushButton做一次二次封装,做成我自己的地图图块。这个图块可以开启或者关闭按钮功能,如果开启按钮功能,点击就能更换为其他状态(比如从墙变成路),于是问题就迎刃而解了。

在程序的地图绘制方面,我利用采取循环动态生成这个自己封装的地图图块Tile,并把图块保存在了31*31的二维数组里。实际上这个部分可以改用二维Vector或者QVector保存,可以在节省内存空间的同时解除地图大小的限制。

迷宫寻路采用常规的DFS,并且尝试使用了少见的非递归DFS解决了问题。

迷宫生成算法一开始没有思路,但是在网上查阅之后,我发现深度优先生成迷宫算法的效果比较好,于是在理解了算法之后将其添加到了程序里,实现了在编辑窗口自动生成迷宫的功能。

2、查阅文献的过程

我是从零开始学习Qt GUI框架的,所以一开始并没有急着开始着手迷宫大师的制作,而是先进行对Qt基本语法的学习。我购买了一本《Qt5开发及实例》,在快速看完了前五章之后才开始着手制作自己的迷宫程序。

另外,我在开发时也遇到了C++上的一些问题,这些问题我除了直接搜索,还经常在C++ Reference这个英文网站(http://www.cplusplus.com/reference/)上进行参考查阅。C++ Reference对C++各个类和功能的完整说明给了我很大帮助。在学习Qt时,我还发现我对Qt经常使用的C++ lambda表达式不太熟练,遇上我查阅了《C++ Primer》10.3.2.节 Lambda Expressions的内容——这对我理解C++ 11的lambda表达式起到了一定帮助。

除此之外,Qt官方的Qt5说明文档也是我在完成大作业时参考频率非常高的文献。

3、通过本门课程实验和大作业,自己对软件维护的认识

(1) 面向对象的程序设计思想是很重要的。设计程序时,根据现实情况将程序封装成一个个对象,能够有效地帮助我梳理程序结构;并且由于面向对象后的class对功能的封装,提高了我的代码复用率和可扩充性,而且让我在添加新功能的时候能够减少一些不必要的考虑。

(2) 代码注释是很有必要的。对代码进行规范的注释,可以让程序员可以更好的理解代码的思路和用途。在本次大作业中,我进行了大量标注,尤其是在涉及到核心算法的部分更是有详细标注,这对我进行功能扩展和后期Debug起到了很大帮助。

(3) 良好的缩进与代码风格可以减少我写代码时的阅读疲劳。

源代码及可执行程序下载/Clone

github:

https://github.com/migodz/Qt-MazeMaster

如果这个项目有帮助到你,还请点个Star,拜托啦!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3