使用python求解迷宫问题的三种实现方法


Posted in Python onMarch 17, 2022

前言

在迷宫问题中,给定入口和出口,要求找到路径。本文将讨论三种求解方法,递归求解、回溯求解和队列求解。

在介绍具体算法之前,先考虑将迷宫数字化。这里将迷宫用一个二维的list存储(即list嵌套在list里),将不可到达的位置用1表示,可到达的位置用0表示,并将已经到过的位置用2表示。

使用python求解迷宫问题的三种实现方法

递归求解

递归求解的基本思路是:

  • 每个时刻总有一个当前位置,开始时这个位置是迷宫人口。
  • 如果当前位置就是出口,问题已解决。
  • 否则,如果从当前位置己无路可走,当前的探查失败,回退一步。
  • 取一个可行相邻位置用同样方式探查,如果从那里可以找到通往出口的路径,那么从当前位置到出口的路径也就找到了。

在整个计算开始时,把迷宫的人口(序对)作为检查的当前位置,算法过程就是:

  • mark当前位置。
  • 检查当前位置是否为出口,如果是则成功结束。
  • 逐个检查当前位置的四邻是否可以通达出口(递归调用自身)。
  • 如果对四邻的探索都失败,报告失败。
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量
path=[]              #存找到的路径
 
def mark(maze,pos):  #给迷宫maze的位置pos标"2"表示“倒过了”
    maze[pos[0]][pos[1]]=2
 
def passable(maze,pos): #检查迷宫maze的位置pos是否可通行
    return maze[pos[0]][pos[1]]==0
 
def find_path(maze,pos,end):
    mark(maze,pos)
    if pos==end:
        print(pos,end=" ")  #已到达出口,输出这个位置。成功结束
        path.append(pos)
        return True
    for i in range(4):      #否则按四个方向顺序检查
        nextp=pos[0]+dirs[i][0],pos[1]+dirs[i][1]
        #考虑下一个可能方向
        if passable(maze,nextp):        #不可行的相邻位置不管
            if find_path(maze,nextp,end):#如果从nextp可达出口,输出这个位置,成功结束
                print(pos,end=" ")
                path.append(pos)
                return True
    return False
 
def see_path(maze,path):     #使寻找到的路径可视化
    for i,p in enumerate(path):
        if i==0:
            maze[p[0]][p[1]] ="E"
        elif i==len(path)-1:
            maze[p[0]][p[1]]="S"
        else:
            maze[p[0]][p[1]] =3
    print("\n")
    for r in maze:
        for c in r:
            if c==3:
                print('\033[0;31m'+"*"+" "+'\033[0m',end="")
            elif c=="S" or c=="E":
                print('\033[0;34m'+c+" " + '\033[0m', end="")
            elif c==2:
                print('\033[0;32m'+"#"+" "+'\033[0m',end="")
            elif c==1:
                print('\033[0;;40m'+" "*2+'\033[0m',end="")
            else:
                print(" "*2,end="")
        print()
 
if __name__ == '__main__':
    maze=[[1,1,1,1,1,1,1,1,1,1,1,1,1,1],\
          [1,0,0,0,1,1,0,0,0,1,0,0,0,1],\
          [1,0,1,0,0,0,0,1,0,1,0,1,0,1],\
          [1,0,1,0,1,1,1,1,0,1,0,1,0,1],\
          [1,0,1,0,0,0,0,0,0,1,1,1,0,1],\
          [1,0,1,1,1,1,1,1,1,1,0,0,0,1],\
          [1,0,1,0,0,0,0,0,0,0,0,1,0,1],\
          [1,0,0,0,1,1,1,0,1,0,1,1,0,1],\
          [1,0,1,0,1,0,1,0,1,0,1,0,0,1],\
          [1,0,1,0,1,0,1,0,1,1,1,1,0,1],\
          [1,0,1,0,0,0,1,0,0,1,0,0,0,1],\
          [1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
    start=(1,1)
    end=(10,12)
    find_path(maze,start,end)
    see_path(maze,path)

代码中see_path函数可以在控制台直观打印出找到的路径,打印结果如下:

使用python求解迷宫问题的三种实现方法

S是入口位置 ,E是出口位置,*代表找到的路径,#代表探索过的路径。

回溯求解

在回溯解法中,主要是用栈来存储可以探索的位置。利用栈后进先出的特点,在一条分路上探索失败时,回到最近一次存储的可探索位置。这是一种深度优先搜索的方法。

def maze_solver(maze,start,end):
    if start==end:
        print(start)
        return
    st=SStack()
    mark(maze,start)
    st.push((start,0))             #入口和方向0的序对入栈
    while not st.is_empty():      #走不通时回退
        pos,nxt=st.pop()           #取栈顶及其检查方向
        for i in range(nxt,4):     #依次检查未检查方向,算出下一位置
            nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][1]
            if nextp==end:
                print_path(end,pos,st)  #到达出口,打印位置
                return
            if passable(maze,nextp):    #遇到未探索的新位置
                st.push((pos,i+1))      #原位置和下一方向入栈
                mark(maze,nextp)
                st.push((nextp,0))      #新位置入栈
                break                   #退出内层循环,下次迭代将以新栈顶作为当前位置继续
    print("找不到路径")

队列求解

队列求解算法中,以队列存储可以探索的位置。利用队列先进先出的特点,实现在每个分支上同时进行搜索路径,直到找到出口。这是一种广度优先搜索的方法。

def maze_solver_queue(maze,start,end):
   path.append(start)
   if start==end:
       print("找到路径")
       return
   qu=SQueue()
   mark(maze,start)
   qu.enqueue(start)                #start位置入队
   while not qu.is_empty():        #还有候选位置
       pos=qu.dequeue()             #取出下一位置
       for i in range(4):           #检查每个方向
           nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][1]
           if passable(maze,nextp): #找到新的探索方向
               if nextp==end:       #是出口,成功
                   print("找到路径")
                   path.append(end)
                   return
               mark(maze,nextp)
               qu.enqueue(nextp)    #新位置入队
               path.append(nextp)
 
   print("未找到路径")

但队列求解方法,不能直接得出找到的具体路径,要得到找到的路径还需要其他存储结构(如链表)。

总结

到此这篇关于使用python求解迷宫问题的三种实现方法的文章就介绍到这了,更多相关python求解迷宫问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python 图片验证码代码分享
Jul 04 Python
使用python加密自己的密码
Aug 04 Python
python 判断是否为正小数和正整数的实例
Jul 23 Python
python实现用户管理系统
Jan 10 Python
Python使用matplotlib填充图形指定区域代码示例
Jan 16 Python
分析python动态规划的递归、非递归实现
Mar 04 Python
python实现最长公共子序列
May 22 Python
Pandas:Series和DataFrame删除指定轴上数据的方法
Nov 10 Python
python 提取文件指定列的方法示例
Aug 07 Python
Django自定义用户表+自定义admin后台中的字段实例
Nov 18 Python
pyhton中__pycache__文件夹的产生与作用详解
Nov 24 Python
Python实现不规则图形填充的思路
Feb 02 Python
Python超详细分步解析随机漫步
yolov5返回坐标的方法实例
Mar 17 #Python
PyTorch中的torch.cat简单介绍
Mar 17 #Python
Python Pygame实战在打砖块游戏的实现
python超详细实现完整学生成绩管理系统
Mar 17 #Python
Python Pygame实战之塔防游戏的实现
pytorch中的 .view()函数的用法介绍
Mar 17 #Python
You might like
php中调用其他系统http接口的方法说明
2014/02/28 PHP
laravel5.0在linux下解决.htaccess无效和去除index.php的问题
2019/10/16 PHP
jQuery修改CSS伪元素属性的方法
2014/07/30 Javascript
用js提交表单解决一个页面有多个提交按钮的问题
2014/09/01 Javascript
AngularJS初始化过程分析(引导程序)
2014/12/06 Javascript
JS实现按比例缩放图片的方法(附C#版代码)
2015/12/08 Javascript
全面理解JavaScript中的闭包
2016/05/12 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
AngularJS自定义过滤器用法经典实例总结
2018/05/17 Javascript
angularJs在多个控制器中共享服务数据的方法
2018/09/30 Javascript
countUp.js实现数字动态变化效果
2019/10/17 Javascript
JS实现拼图游戏
2021/01/29 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
[02:43]2014DOTA2国际邀请赛 官方Alliance战队纪录片
2014/07/14 DOTA
python中abs&map&reduce简介
2018/02/20 Python
python使用代理ip访问网站的实例
2018/05/07 Python
django解决跨域请求的问题详解
2019/01/20 Python
python基于SMTP协议发送邮件
2019/05/31 Python
Python Tensor FLow简单使用方法实例详解
2020/01/14 Python
Python bisect模块原理及常见实例
2020/06/17 Python
英国品牌男装折扣网站:Brown Bag
2018/03/08 全球购物
香港百佳网上超级市场:PARKNSHOP.com
2020/06/10 全球购物
外贸公司实习自我鉴定
2013/09/24 职场文书
留学推荐信怎么写
2014/01/25 职场文书
超市采购员岗位职责
2014/02/01 职场文书
万年牢教学反思
2014/02/15 职场文书
学校读书活动总结
2014/06/30 职场文书
领导班子对照检查材料
2014/09/22 职场文书
机动车登记业务委托书
2014/10/08 职场文书
关于职业道德的心得体会
2016/01/18 职场文书
2016年度师德标兵先进事迹材料
2016/02/26 职场文书
2016年感恩父亲节活动总结
2016/04/01 职场文书
理解深度学习之深度学习简介
2021/04/14 Python
在前女友婚礼上,用Python破解了现场的WIFI还把名称改成了
2021/05/28 Python
Golang数据类型和相互转换
2022/04/12 Golang
Windows Server 2016 配置 IIS 的详细步骤
2022/04/28 Servers