Python实现迷宫自动寻路实例
作者:程序媛小本 发布时间:2021-12-22 10:00:44
背景
我打开手机,发现有人在QQ空间里叫嚣。
看他得意的样子,显然是在家里呆久了,已经忘了天有多高。
预处理
设计一个迷宫自动寻路算法并不难,但是对于当下这个任务而言,第一个棘手的地方在于,如何把这个迷宫变成计算机认识的样子,也就是迷宫图片的矩阵化。
图片的大小是397×390
。先把四周的白边裁掉,再把这幅图中的每一个像素二值化,再根据颜色赋值,黑色用0
表示,白色用1
表示,建立一个0/1
矩阵。考虑到迷宫的边界都是封闭的,为了防止由于图片质量问题导致某些看上去是0
的地方其实是1
,在之后走迷宫的过程中造成一些可预知的影响,比如列表的越界等,我们再把四条边上的元素全部强制变成0
。这时,对迷宫的预处理已经基本完成,如果我们把1
隐藏,把所有的0
打印出来,经过放缩之后,就得到了这样的结果:
寻路算法
得到了这个迷宫矩阵之后,我们需要找到一条从左上角到右下角的路。
印象中我与有关走迷宫的方法有过一面之缘,那是在一节算法选修课上,老师在台上深情地讲着深度优先搜索与广度优先搜索,我在台下忘我地抄着大物实验报告。至今,提起这两个概念,我唯一的印象只有它俩的英文缩写一个是D开头一个是B开头。
不过没关系。当年陈刀仔他能用20块赢到3700万,我用for循环
搞定这个小迷宫,没有问题。
一般来说,迷宫的内部是不封闭的,我从任意一个地方倒水,总能把整个迷宫填满。因此,假定我们有一个小老鼠,把它放在起点,如果它能够保证自动避障、不踩走过的路、遇死胡同回退,那么它总能找到终点。
因此,我们定义一个点(x,y)
,初始位置为(1,1)
,也就是边界内左上角的第一个点。
定义两个列表,一个是path
,用来存放它最终确定下来的路径(也就是那个最终走到终点的路径)中的每一个点;另一个是footprint
,用来存放所有它走过的地方,包括它走的错路。两个列表形如[(1,1),(1,2),(2,2),......,(m,n)]
。
再定义四种动作,分别是:向下走一步(y=y+1)
,向右走一步(x=x+1)
,向左走一步(x=x-1)
和向上走一步(y=y-1)
。我们每次让这个点尝试四种动作,如果能走就让它走。判断是否不能走是看下一步的坐标是否是墙或者是足迹。把新的点放进path
和footprint
里,成为新的足迹。
确定四个动作的优先级,即下、右、左、上
,能下则下,不能下则右,不能右则左,不能左则上。这样它就不会在一个空地上平白无故地乱转,而是具有一定方向性地探索。
接下来,让算法具备自动回退的能力。我们想象一个简单情景:
这个图不准确,不满足本文的优先级设定,但也足以表意
遇到这样的死胡同,假如进来的时候足迹把出去的路给封死了,那么这个点就没办法再出来了。一旦我们发现这个点陷入了绝境,哪里都不能走了,这时候我们就得让它原路返回。实迷途其未远,回到上一个路口也很简单,无非就是删掉这一段路线。方法就是把path
列表里的最后一个元素逐一弹出列表,由于我们有footprint
记录,所有它走过的地方都不能再走第二遍,所以只要这条错误的路没有完全退出去,退到哪一步都是四个方向都不能走的,因为附近都被它走过了。这样它就会一直退到我们期望的那个地方,也就是它误入歧途的那个路口。
测试
下面,我们让它开始循环。只要它的坐标不等于终点的坐标,我们就一直让它不断地探索。运行结束后,我们得到了一条迂回的曲线,如图(局部)。
程序成功得到了一条可以通往终点的路径,但这条路径过于冗杂,以上图为例,所有宽度不为1
的地方都是这个点绕来绕去所导致的。因此,该路径还有待优化。
优化
我们考虑如下一种简单情况:
在这条路线中,显然4
~9
属于没有意义的兜圈,正确的路线应该是从3
直接到10
。
我们的优化方法是:如果第n步
在(x,y)
,从第n+2步
(也就是下一步的下一步),一直到最后一步,这中间只要有一步落在(x,y)
一步之遥的地方,就把从第n+1步
到这一步的所有路径点都删掉。拿上面这个例子来说,我们从第1步
开始检查。检查到第3步
时,我们从第5步
开始看,一直看到第10步
发现10
落在3
一步就能到达的地方,这时我们把中间的4-9
全部删掉,直接把10
接在3
的后面。
不过,考虑到后面可能还会有更优的情况,比如说从12
开始继续绕,绕到20
发现20
刚好落在3
的上面,那我们事实上应该直接把20
接在3
后面,12
也要丢掉,之前的方法有些缺陷。因此,为了避免这种情况,我们逆着循环,对于第3步
而言,我们从第20步
往前循环,一直循环到第5步
,看是否有3能直接到达的地方。这样我们就能对这条路线进行最大优化了。
绘制路径
最终,我们得到了正确而简洁的路径,也记录了曾经走过的错路和多走的路。
根据矩阵和图片的对应关系,我们把图片里对应的像素改变颜色,其它点不作更改。
绘制路径:
优化之前:
全部足迹:
来源:https://blog.csdn.net/m0_59236127/article/details/122804899


猜你喜欢
- 使用Python进行数据分析,大家都会多少学习一本经典教材《利用Python进行数据分析》,书中作者使用了Ipython的交互环境进行了书中
- 导语Hey!下午好,我是木木子,关注我,一起玩游戏吧~微信小游戏很久之前刮起了一股切水果热潮,还记得嘛?我记得纯粹是因为这个游戏家里的孩子依
- 1. 语句块:{ }之间的部分即为BLOCK语句块。2. 条件语句:if ( expression ) BLOCK;if ( e
- 说在前面和word的文本相比PDF更类似于一张张图片,图上放着一个个文字。对其的解析是将图片上的文字提取到text文件中,方便之后的分析。添
- 本文实例讲述了Python使用Flask-SQLAlchemy连接数据库操作。分享给大家供大家参考,具体如下:需要安装flaskpip in
- go协程上下文contextgolang的context 主要用来在 goroutine 之间传递上下文信息,包括:取消信号、超时时间、截止
- 项目背景最近在做的项目,涉及到数据库的操作了,之前做的是直接调用接口,不用做存库操作。因此要增加大量特殊格式的实体类。比如我们用的是 JPA
- 前言 MySQL 5.5版本之前默认的复制是异步(Asynchronous )模式的, MySQL 5
- 并发安全和锁有时候在Go代码中可能会存在多个goroutine同时操作一个资源(临界区),这种情况会发生竞态问题(数据竞态)。类比现实生活中
- 前言Django项目本身就可以启动运行,为什么还需要部署到Apache或者Nginx上呢?初学者都会遇到这个问题,我们来看看官方解释:It&
- 当用cmd命令行运行python文件时,我们知道可以通过>python pyfile.py来运行python文件,此时的输出会直接打印
- 最近的一些疫情信息很让人揪心,为了方便大家掌握疫情信息,在空闲之余做了一个关于 nCoV 的疫情监控小助手。主要的功能是通过企业微信的 We
- tkinter获取复选框(Checkbutton)的值定义GUI:from tkinter import *# 初始化Tk()myWindo
- 编码格式常见的编码格式:Python的解释器使用的是Unicode(内存).py文件在磁盘上使用UTF-8(外存)更改编码格式一般形式为在程
- 前言最近有人对自动上传与发布很感兴趣,都私下找我说了好几次了。今天,必须把他安排,必须实力宠粉。“本篇依次介绍目前主流的
- 1. 随机数np.random.random()是最常用的随机数生成函数,该函数生成的随机数随机均匀分布于[0, 1)区间。如果不提供参数,
- Python3实现旋转数组的3种算法下面是Python3实现的旋转数组的3种算法。一、题目给定一个数组,将数组中的元素向右移动 k 个位置,
- Fedora5下配置MySQL (很有参考价值的 MySQL资料 包括如何在linux文件系统移动MySQL数据库的位置) 一、下载MySQ
- 楔子由于之前电脑上安装的MySQL版本是比较老的了,大概是5.1的版本,不支持JSON字段功能。而最新开发部门开发的的编辑器产品,使用到了J
- 引言在使用SqlServer Express 版本的时候发现,这个版本不支持通过数据库的代理方式进行数据库的维护。解决方案使用SQL语句加w