jjzjj

基于python实现的迷宫游戏【源码+文档】

老杨没掉头发 2023-12-14 原文

目录

一、项目概述与编译环境

二、问题的数学建模

三、算法实现

3.1 迷宫的创建

3.2 搜索算法描述

四、项目架构与GUI设计

五、搜索算法效率对比

六、实验心得与体会

七、源代码


一、项目概述与编译环境

    本次大作业选题为小兔子找胡萝卜的迷宫游戏。

    该项目在windows下编译通过,所需环境为python3,编写GUI所用的库为pygame,在运行作业前,需要配置依赖项,即在main.py的路径下打开cmd,并运行:

       pip install –r requirement.txt

配置完依赖项后即可运行游戏:

       python main.py

为了方便测试不同搜索算法的效率,编写了脚本test.py进行测试:

       python test.py --maze_size 10 (设置为需要的迷宫大小,建议为5-25,否则可能超过递归上界) 

二、问题的数学建模

       由于迷宫的实质为一个由0,1构成的矩阵

       其中1代表可行走的区域,0代表障碍物

       由于穴居人生活区域中存在冰面,因此设置了随机道路中存在冰块,在冰块上穴居人会打滑,导致行走的代价*2。

       在本问题中,设置穴居人初始位置处的值为10,宝藏处的值为1,则迷宫求解转化为该矩阵中10处到1处的带权连通路径。    

三、算法实现

3.1 迷宫的创建

    事实上,本次大作业中的一大难点在于迷宫如何创建,在实现过程中进行了如下尝试:

(1)对每一小格随机添加障碍物

(2)限定障碍物的形状,并在地图中随机放置障碍物,如(L型,H型)

       但实际的创建结果均不理想(迷宫的样子不像迷宫:出现大量空白/障碍堆积现象)

       最后经过查阅资料,采取递归回溯的算法生成迷宫,算法如下:

①每次把新找到的未访问迷宫单元作为优先

②寻找其相邻的未访问过的迷宫单元,直到所有的单元都被访问到

通俗的说,就是从起点开始随机走,走不通了就返回上一步,从下一个能走的地方再开始随机走。

在创建完迷宫后,再在迷宫中随机指定人物的初始位置与宝藏,以及随机冰面的位置。

该迷宫创建算法可以创建不同长、宽、障碍物、初始\终点位置,具体代码详见:maze.py

3.2 搜索算法描述

本次实验中采取了四种搜索算法进行求解,实现方式均为迭代:

(1)深度优先搜索

       利用stack实现,先让起点入栈,之后进行如下迭代

①栈弹出顶点I,并标记I为已访问的

②检查I是否为宝藏,若为宝藏,迭代结束

③依次检查I的领域,将其中未访问过的顶点入栈

(2)宽度优先搜索

       利用queue实现,先让起点入列,之后进行如下迭代

①队列出列顶点I,并标记I为已访问的

②检查I是否为宝藏,若为宝藏,迭代结束

③依次检查I的领域,将其中未访问过的顶点入队列

(3)一致代价搜索

       利用PriorityQueue实现,实现Maze_unit类对顶点进行包装,并重新定义优先级队列的排序方法,在本次实现的一致代价搜索中,h(n)为路径代价之和,g(n)为0

       先让起点入列,之后进行如下迭代

①优先级队列出列顶点I,并标记I为已访问的

②检查I是否为宝藏,若为宝藏,迭代结束

③依次检查I的领域,将其中未访问过的顶点入优先级队列

       由于代价为路径长度,因此在本项目中,一致代价搜索的结果与宽度优先搜索基本一致。

(4)A*搜索

       利用PriorityQueue实现,实现Maze_unit类对顶点进行包装,并重新定义优先级队列的排序方法,在本次实现的一致代价搜索中,h(n)为路径代价之和,g(n)为顶点距离宝藏的曼哈顿距离乘以相关系数

       先让起点入列,之后进行如下迭代

①优先级队列出列顶点I,并标记I为已访问的

②检查I是否为宝藏,若为宝藏,迭代结束

③依次检查I的领域,将其中未访问过的顶点入优先级队列

       搜索算法的代码详见:solution.py

四、项目架构与GUI设计

(1)项目架构

       本次项目将核心部分与GUI部分分离,各py文件内容如下:

       maze:迷宫创建

       solution:问题求解

       people: GUI中的类:人物

       wall:GUI中的类:墙壁

       main:主函数,基于pygame的GUI编写

       test:测试脚本,直接统计各算法1000次所需的时间与扩展节点数

(2)GUI设计

       为了方便运行与直观观看搜素过程,

       在迷宫游戏的右侧有五个按键,利用鼠标点击,可以分别观看不同搜索算法的搜索过程,点击View path可以观看利用A*搜索得到的通向终点的最短路径,此外玩家可以直接使用wsad按键控制上下左右进行游戏。若不想手动控制抵达终点,也可以直接选中skip按钮跳过该关卡。

       同时在进行游戏的过程中,该迷宫求解的结果会显示在画面的右侧,包括open表大小,closed表大小与搜索得到的路径的代价之和(正常路为2,冰面为4,终点为1)

View path

       GUI画面设计:

       GUI的素材均位于子文件夹images中,其中人物行走过程的上下左右利用数字图像处理的方法进行了不同对待:

       同时您也可以在游戏时打开系统的声音,感受bgm带来的不同体验

       Bgm:music.ogg

五、搜索算法效率对比

利用test.py对不同的搜索算法效率进行了对比结果如下:

迷宫大小:7*7

搜索算法

DFS

BFS

UCS

A*

总时间(s)

0.11

0.18

0.21

0.23

平均节点数

   10.17

10.39

9.51

6.85

迷宫大小:21*21

搜索算法

DFS

BFS

UCS

A*

总时间(s)

1.24

8.09

5.45

3.14

平均节点数

114.60

118.23

112.92

49.72

迷宫大小:35*35

搜索算法

DFS

BFS

UCS

A*

总时间(s)

5.64

82.20

44.69

9.78

平均节点数

  349.26

344.87

335.22

125.99

       从时间角度来说,由于python的stack与queue运行效率差距较大,因此实际结果中深度优先搜索的速度高于其余三种。

       从扩展节点数的角度来说,对于大型迷宫来说,A*算法扩展节点数相对于其他三种算法来说要小很多,也从某一方面验证了,当代价函数一致时,A*算法是最优的。而对于BFS与DFS,在迷宫大小变大的情况下,节点扩展数较大,并不具有很高的空间效率。

       从路径平均代价来看,DFS几乎不能找到路径最优解,而A*搜索与一致代价搜索在合理设置cost的情况下,可以得到最短路径。

六、实验心得与体会

       本次大作业工程量较大,不仅复习了不同搜索算法的实现思路,完成了对迷宫问题的建模,还锻炼了代码能力。

       由于这是第一次尝试利用pygame库进行游戏的编写,而不是用传统的pyqt,花费的学习时间较长,也感受了真实的游戏制作过程的复杂与艰难,游戏素材图片(字体,音乐)寻找的困难。

       此外,在自己观看不同算法的搜索过程中,也对之前略有混淆的概念进行了理解,例如,在第一次小作业中回答错误的下列命题:

如:宽度优先搜索是一种特殊的一致代价搜索

       从手动实现的角度对概念解进行了复习,收获颇丰。

七、源代码

基于python实现的迷宫游戏【源码+文档】.zip-Python文档类资源-CSDN下载本次大作业选题为小兔子找胡萝卜的迷宫游戏。工程量较大,不仅复习了不同搜索算法的实现思路,完成了对迷宫更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/vx1271487114/85860604?spm=1001.2014.3001.5503

有关基于python实现的迷宫游戏【源码+文档】的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  6. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

  7. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  8. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

随机推荐