Python实现迷宫自动寻路实例

目录
  • 背景
  • 预处理
  • 寻路算法
  • 测试
  • 优化
  • 绘制路径
  • 结语

背景

我打开手机,发现有人在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)。我们每次让这个点尝试四种动作,如果能走就让它走。判断是否不能走是看下一步的坐标是否是墙或者是足迹。把新的点放进pathfootprint里,成为新的足迹。

确定四个动作的优先级,即下、右、左、上,能下则下,不能下则右,不能右则左,不能左则上。这样它就不会在一个空地上平白无故地乱转,而是具有一定方向性地探索。

接下来,让算法具备自动回退的能力。我们想象一个简单情景:

这个图不准确,不满足本文的优先级设定,但也足以表意

遇到这样的死胡同,假如进来的时候足迹把出去的路给封死了,那么这个点就没办法再出来了。一旦我们发现这个点陷入了绝境,哪里都不能走了,这时候我们就得让它原路返回。实迷途其未远,回到上一个路口也很简单,无非就是删掉这一段路线。方法就是把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能直接到达的地方。这样我们就能对这条路线进行最大优化了。

绘制路径

最终,我们得到了正确而简洁的路径,也记录了曾经走过的错路和多走的路。

根据矩阵和图片的对应关系,我们把图片里对应的像素改变颜色,其它点不作更改。

绘制路径:

优化之前:

全部足迹:

结语

至此,我们已经把这个问题解决得差不多了。整个程序在我的电脑上运行下来大概需要三五分钟这个样子,毕竟是只用for循环的暴力方法。

(0)

相关推荐

  • Python实现随机生成迷宫并自动寻路

    Python深搜版: 核心在于带随机的深搜(见代码第23到27行,其实也可以用22行代替这几行代码,你可以试着把第24行的数字4改大或者改小,即调整随机程度) import os import random from queue import Queue import numpy import colorama from colorama import Fore, Back, Style import sys from bmpEditor import bmp colorama.init() #

  • 一道python走迷宫算法题

    前几天逛博客时看到了这样一道问题,感觉比较有趣,就自己思考了下方案顺便用python实现了一下.题目如下: 用一个二维数组表示一个简单的迷宫,用0表示通路,用1表示阻断,老鼠在每个点上可以移动相邻的东南西北四个点,设计一个算法,模拟老鼠走迷宫,找到从入口到出口的一条路径. 如图所示: 先说下我的思路吧: 1.首先用一个列表source存储迷宫图,一个列表route_stack存储路线图,一个列表route_history存储走过的点,起点(0,0),终点(4,4). 2.老鼠在每个点都有上下左右

  • Python使用Tkinter实现机器人走迷宫

    这本是课程的一个作业研究搜索算法,当时研究了一下Tkinter,然后写了个很简单的机器人走迷宫的界面,并且使用了各种搜索算法来进行搜索,如下图: 使用A*寻找最优路径: 由于时间关系,不分析了,我自己贴代码吧.希望对一些也要用Tkinter的人有帮助. from Tkinter import * from random import * import time import numpy as np import util class Directions: NORTH = 'North' SOU

  • Python实现迷宫自动寻路实例

    目录 背景 预处理 寻路算法 测试 优化 绘制路径 结语 背景 我打开手机,发现有人在QQ空间里叫嚣. 看他得意的样子,显然是在家里呆久了,已经忘了天有多高. 预处理 设计一个迷宫自动寻路算法并不难,但是对于当下这个任务而言,第一个棘手的地方在于,如何把这个迷宫变成计算机认识的样子,也就是迷宫图片的矩阵化. 图片的大小是397×390.先把四周的白边裁掉,再把这幅图中的每一个像素二值化,再根据颜色赋值,黑色用0表示,白色用1表示,建立一个0/1矩阵.考虑到迷宫的边界都是封闭的,为了防止由于图片质

  • 详解如何利用Python绘制迷宫小游戏

    目录 构思 绘制迷宫 走出迷宫 完整代码 更大的挑战 关于坐标系设置 周末在家,儿子闹着要玩游戏,让玩吧,不利于健康,不让玩吧,扛不住他折腾,于是想,不如一起搞个小游戏玩玩! 之前给他编过猜数字 和 掷骰子 游戏,现在已经没有吸引力了,就对他说:“我们来玩个迷宫游戏吧.” 果不其然,有了兴趣,于是和他一起设计实现起来,现在一起看看我们是怎么做的吧,说不定也能成为一个陪娃神器~ 先一睹为快: 构思 迷宫游戏,相对比较简单,设置好地图,然后用递归算法来寻找出口,并将过程显示出来,增强趣味性. 不如想

  • Python 模拟购物车的实例讲解

    1.功能简介 此程序模拟用户登陆商城后购买商品操作.可实现用户登陆.商品购买.历史消费记查询.余额和消费信息更新等功能.首次登陆输入初始账户资金,后续登陆则从文件获取上次消费后的余额,每次购买商品后会扣除相应金额并更新余额信息,退出时也会将余额和消费记录更新到文件以备后续查询. 2.实现方法 架构: 本程序采用python语言编写,将各项任务进行分解并定义对应的函数来处理,从而使程序结构清晰明了.主要编写了六个函数: (1)login(name,password) 用户登陆函数,实现用户名和密码

  • Python文件和流(实例讲解)

    1.文件写入 #打开文件,路径不对会报错 f = open(r"C:\Users\jm\Desktop\pyfile.txt","w") f.write("Hello,world!\n") f.close() 2.文件读取 #读取 f = open(r"C:\Users\jm\Desktop\pyfile.txt","r") print(f.read()) f.close() 输出: Hello,world

  • python实现rsa加密实例详解

    python实现rsa加密实例详解 一 代码 import rsa key = rsa.newkeys(3000)#生成随机秘钥 privateKey = key[1]#私钥 publicKey = key[0]#公钥 message ='sanxi Now is better than never.' print('Before encrypted:',message) message = message.encode() cryptedMessage = rsa.encrypt(messag

  • Python 迭代器与生成器实例详解

    Python 迭代器与生成器实例详解 一.如何实现可迭代对象和迭代器对象 1.由可迭代对象得到迭代器对象 例如l就是可迭代对象,iter(l)是迭代器对象 In [1]: l = [1,2,3,4] In [2]: l.__iter__ Out[2]: <method-wrapper '__iter__' of list object at 0x000000000426C7C8> In [3]: t = iter(l) In [4]: t.next() Out[4]: 1 In [5]: t.

  • Python 私有函数的实例详解

    Python 私有函数的实例详解 与大多数语言一样,Python 也有私有的概念: • 私有函数不可以从它们的模块外面被调用 • 私有类方法不能够从它们的类外面被调用 • 私有属性不能够从它们的类外面被访问 与大多数的语言不同,一个 Python 函数,方法,或属性是私有还是公有,完全取决于它的名字. 如果一个 Python 函数,类方法,或属性的名字以两个下划线开始 (但不是结束),它是私有的:其它所有的都是公有的. Python 没有类方法保护 的概念 (只能用于它们自已的类和子类中).类方

  • python读取二进制mnist实例详解

    python读取二进制mnist实例详解 training data 数据结构: <br>[offset] [type] [value] [description] 0000 32 bit integer 0x00000803(2051) magic number 0004 32 bit integer 60000 number of images 0008 32 bit integer 28 number of rows 0012 32 bit integer 28 number of co

  • Python三级菜单的实例

    要求: 打印省.市.县三级菜单 可返回上一级 可随时退出程序 版本1 # _author : Ahern Li # @_date : 2017/9/12 menu = { '浙江省':{ '杭州市':{ '余杭区':{'中泰':{},'临平':{}}, '西湖区':{'西湖':{},'留下':{}} }, '温州市':{ '苍南县':{'灵溪':{},'龙港':{}}, '瑞安县':{'安阳':{},'锦湖':{}} } }, '广东省':{ '广州市':{ '越秀区':{'人民路':{},'北

  • Python实现类继承实例

    Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,本文就举一例Python类继承的实例. 实例代码如下: #! /usr/bin/python # Filename: inherit.py # Author: yanggang class SchoolMember: def __init__(self,name,age): self.name = name self.age = age print 'init SchoolMember: ', self.name def tel

随机推荐