Python3 A*寻路算法实现方式


Posted in Python onDecember 24, 2019

我就废话不多说了,直接上代码吧!

# -*- coding: utf-8 -*-
import math
import random
import copy
import time
import sys
import tkinter
import threading

# 地图
tm = [
'############################################################',
'#S............................#............#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#.........................#.....#.....#.........#',
'#..........#..................#......#.....#...............#',
'#..#########..................#......#.....#.....#.........#',
'#..#..........................#......#.....#.....#.........#',
'#..#..........................#......#.....#.....#.........#',
'#..############################......#.....#.....#.........#',
'#.............................#......#.....#.....#.........#',
'#.............................#......#...........#.........#',
'#######.##################################################.#',
'#....#........#.................#.............#............#',
'#....#........#........#........#.............#............#',
'#....####.#####........#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........####.#######.##............#',
'#.........#............#........#....#.......#.............#',
'#.........#............#........#....#.......#.............#',
'#......................#........#....#.......#.............#',
'#.........#............#........##.########..#.............#',
'#.........#............#..................#..########.######',
'#.........#............#..................#...............E#',
'############################################################']

# 存储搜索时的地图
test_map = []


#----------- 开放列表和关闭列表的元素类型,parent用来在成功的时候回溯路径 -----------
class Node_Elem:

 def __init__(self, parent, x, y, dist):
  self.parent = parent # 回溯父节点
  self.x = x # x坐标
  self.y = y # y坐标
  self.dist = dist # 从起点到此位置的实际距离


#----------- A*算法 -----------
class A_Star:
 
 def __init__(self, root, s_x, s_y, e_x, e_y, w=60, h=30):

  self.s_x = s_x # 起点x
  self.s_y = s_y # 起点y
  self.e_x = e_x # 终点x
  self.e_y = e_y # 终点y
  
  self.open = [] # open表
  self.close = [] # close表
  self.path = [] # path表

  # 创建画布
  self.root = root # 画布根节点
  self.width = w # 地图w,默认60
  self.height = h # 地图h,默认30
  self.__r = 3 # 半径
  # Tkinter.Canvas
  self.canvas = tkinter.Canvas(
    root,
    width=self.width * 10 + 100,
    height=self.height * 10 + 100,
    bg="#EBEBEB", # 背景白色 
    xscrollincrement=1,
    yscrollincrement=1
   )
  self.canvas.pack(expand=tkinter.YES, fill=tkinter.BOTH)
  self.title("A*迷宫算法(e:开始搜索或退出)")
  self.__bindEvents()
  self.new()

 # 按键响应程序
 def __bindEvents(self):

  self.root.bind("e", self.quite) # 退出程序

 # 退出程序
 def quite(self, evt):
  self.root.destroy()

 # 更改标题
 def title(self, s):
  self.root.title(s)

 # 初始化
 def new(self):

  node = self.canvas.create_oval(100 - self.__r,
       20 - self.__r, 100 + self.__r, 20 + self.__r,
       fill="#ff0000",
       outline="#ffffff",
       tags="node",
      )
  self.canvas.create_text(130, 20,
       text=u'Wall',
       fill='black'
      )
  node = self.canvas.create_oval(200 - self.__r,
       20 - self.__r, 200 + self.__r, 20 + self.__r,
       fill="#00ff00",
       outline="#ffffff",
       tags="node",
      )
  self.canvas.create_text(230, 20,
       text=u'Path',
       fill='black'
      )
  node = self.canvas.create_oval(300 - self.__r,
       20 - self.__r, 300 + self.__r, 20 + self.__r,
       fill="#AAAAAA",
       outline="#ffffff",
       tags="node",
      )
  self.canvas.create_text(330, 20,
       text=u'Searched',
       fill='black'
      )

  for i in range(self.width):
   for j in range(self.height):
    # 生成障碍节点,半径为self.__r
    if test_map[j][i] == '#':
     node = self.canvas.create_oval(i * 10 + 50 - self.__r,
       j * 10 + 50 - self.__r, i * 10 + 50 + self.__r, j * 10 + 50 + self.__r,
       fill="#ff0000", # 填充红色
       outline="#ffffff", # 轮廓白色
       tags="node",
      )
    # 显示起点
    if test_map[j][i] == 'S':
     node = self.canvas.create_oval(i * 10 + 50 - self.__r,
       j * 10 + 50 - self.__r, i * 10 + 50 + self.__r, j * 10 + 50 + self.__r,
       fill="#00ff00", # 填充绿色
       outline="#ffffff", # 轮廓白色
       tags="node",
      )
     self.canvas.create_text(i * 10 + 50, j * 10 + 50 - 20, # 使用create_text方法在坐标处绘制文字 
       text=u'Start', # 所绘制文字的内容 
       fill='black' # 所绘制文字的颜色为灰色
      )
    # 显示终点
    if test_map[j][i] == 'E':
     node = self.canvas.create_oval(i * 10 + 50 - self.__r,
       j * 10 + 50 - self.__r, i * 10 + 50 + self.__r, j * 10 + 50 + self.__r,
       fill="#00ff00", # 填充绿色
       outline="#ffffff", # 轮廓白色
       tags="node",
      )
     self.canvas.create_text(i * 10 + 50, j * 10 + 50 + 20, # 使用create_text方法在坐标处绘制文字 
       text=u'End', # 所绘制文字的内容 
       fill='black' # 所绘制文字的颜色为灰色
      )
    # 生成路径节点,半径为self.__r
    if test_map[j][i] == '*':
     node = self.canvas.create_oval(i * 10 + 50 - self.__r,
       j * 10 + 50 - self.__r, i * 10 + 50 + self.__r, j * 10 + 50 + self.__r,
       fill="#0000ff", # 填充蓝色
       outline="#ffffff", # 轮廓白色
       tags="node",
      )
    # 生成搜索区域,半径为self.__r
    if test_map[j][i] == ' ':
     node = self.canvas.create_oval(i * 10 + 50 - self.__r,
       j * 10 + 50 - self.__r, i * 10 + 50 + self.__r, j * 10 + 50 + self.__r,
       fill="#AAAAAA", # 填充白色
       outline="#ffffff", # 轮廓白色
       tags="node",
      )
  
 # 查找路径的入口函数
 def find_path(self):
  # 构建开始节点
  p = Node_Elem(None, self.s_x, self.s_y, 0.0)
  while True:
   # 扩展节点
   self.extend_round(p)
   # 如果open表为空,则不存在路径,返回
   if not self.open:
    return
   # 取F值最小的节点
   idx, p = self.get_best()
   # 到达终点,生成路径,返回
   if self.is_target(p):
    self.make_path(p)
    return
   # 把此节点加入close表,并从open表里删除
   self.close.append(p)
   del self.open[idx]

 # 生成路径 
 def make_path(self, p):
  # 从结束点回溯到开始点,开始点的parent == None
  while p:
   self.path.append((p.x, p.y))
   p = p.parent

 # 判断是否为终点
 def is_target(self, i):
  return i.x == self.e_x and i.y == self.e_y

 # 取F值最小的节点
 def get_best(self):
  best = None
  bv = 10000000 # MAX值
  bi = -1
  for idx, i in enumerate(self.open):
   value = self.get_dist(i)
   if value < bv:
    best = i
    bv = value
    bi = idx
  return bi, best
  
 # 求距离
 def get_dist(self, i):
  # F = G + H
  # G 为当前路径长度,H为估计长度
  return i.dist + math.sqrt((self.e_x - i.x) * (self.e_x - i.x)) + math.sqrt((self.e_y - i.y) * (self.e_y - i.y))

 # 扩展节点
 def extend_round(self, p):
  # 八个方向移动
  xs = (-1, 0, 1, -1, 1, -1, 0, 1)
  ys = (-1, -1, -1, 0, 0, 1, 1, 1)
  # 上下左右四个方向移动
  xs = (0, -1, 1, 0)
  ys = (-1, 0, 0, 1)
  for x, y in zip(xs, ys):
   new_x, new_y = x + p.x, y + p.y
   # 检查位置是否合法
   if not self.is_valid_coord(new_x, new_y):
    continue
   # 构造新的节点,计算距离
   node = Node_Elem(p, new_x, new_y, p.dist + self.get_cost(
      p.x, p.y, new_x, new_y))
   # 新节点在关闭列表,则忽略
   if self.node_in_close(node):
    continue
   i = self.node_in_open(node)
   # 新节点在open表
   if i != -1:
    # 当前路径距离更短
    if self.open[i].dist > node.dist:
     # 更新距离
     self.open[i].parent = p
     self.open[i].dist = node.dist
    continue
   # 否则加入open表
   self.open.append(node)

 # 移动距离,直走1.0,斜走1.4
 def get_cost(self, x1, y1, x2, y2):
  if x1 == x2 or y1 == y2:
   return 1.0
  return 1.4
 
 # 检查节点是否在close表
 def node_in_close(self, node):
  for i in self.close:
   if node.x == i.x and node.y == i.y:
    return True
  return False
 
 # 检查节点是否在open表,返回序号 
 def node_in_open(self, node):
  for i, n in enumerate(self.open):
   if node.x == n.x and node.y == n.y:
    return i
  return -1

 # 判断位置是否合法,超出边界或者为阻碍 
 def is_valid_coord(self, x, y):
  if x < 0 or x >= self.width or y < 0 or y >= self.height:
   return False
  return test_map[y][x] != '#'

 # 搜寻过的位置
 def get_searched(self):
  l = []
  for i in self.open:
   l.append((i.x, i.y))
  for i in self.close:
   l.append((i.x, i.y))
  return l


# 获取起点坐标
def get_start_XY():
 return get_symbol_XY('S')


# 获取终点坐标
def get_end_XY():
 return get_symbol_XY('E')


# 查找特定元素
def get_symbol_XY(s):
 for y, line in enumerate(test_map):
  try:
   x = line.index(s)
  except:
   continue
  else:
   break
 return x, y

  
# 标记路径位置 
def mark_path(l):
 mark_symbol(l, '*')


# 标记已搜索过的位置 
def mark_searched(l):
 mark_symbol(l, ' ')


# 标记函数
def mark_symbol(l, s):
 for x, y in l:
  test_map[y][x] = s

  
# 标记起点和终点
def mark_start_end(s_x, s_y, e_x, e_y):
 test_map[s_y][s_x] = 'S'
 test_map[e_y][e_x] = 'E'


# 将地图字符串转化为表
def tm_to_test_map():
 for line in tm:
  test_map.append(list(line))

  
# 寻找路径  
def find_path():
 s_x, s_y = get_start_XY()
 e_x, e_y = get_end_XY()
 # A*算法
 a_star = A_Star(tkinter.Tk(), s_x, s_y, e_x, e_y)
 a_star.root.mainloop()
 a_star.find_path()
 searched = a_star.get_searched()
 path = a_star.path
 # 标记已搜索过的位置
 mark_searched(searched)
 # 标记路径位置 
 mark_path(path)
 # 标记起点和终点
 mark_start_end(s_x, s_y, e_x, e_y)
 print(u"路径长度:%d" % (len(path)))
 print(u"搜索过的区域:%d" % (len(searched)))
 a_star = A_Star(tkinter.Tk(), s_x, s_y, e_x, e_y)
 a_star.root.mainloop()
 
#----------- 程序的入口处 -----------

    
if __name__ == '__main__':

 print (u""" 
--------------------------------------------------------
 程序:A*迷宫问题程序 
 作者:Gm
 日期:2019-7-08
 语言:Python 3.7 
-------------------------------------------------------- 
 """)
 # 载入地图
 tm_to_test_map()
 # 寻找路径
 find_path()

Python3 A*寻路算法实现方式

以上这篇Python3 A*寻路算法实现方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中操作MySQL入门实例
Feb 08 Python
Linux下使用python自动修改本机网关代码分享
May 21 Python
详解Python多线程
Nov 14 Python
Windows下Python2与Python3两个版本共存的方法详解
Feb 12 Python
Python守护线程用法实例
Jun 23 Python
使用Python-OpenCV向图片添加噪声的实现(高斯噪声、椒盐噪声)
May 28 Python
Python 分享10个PyCharm技巧
Jul 13 Python
python3连接mysql获取ansible动态inventory脚本
Jan 19 Python
Python字典添加,删除,查询等相关操作方法详解
Feb 07 Python
基于python实现坦克大战游戏
Oct 27 Python
Python爬虫后获取重定向url的两种方法
Jan 19 Python
Python打包exe时各种异常处理方案总结
May 18 Python
python logging添加filter教程
Dec 24 #Python
python打印异常信息的两种实现方式
Dec 24 #Python
numpy实现神经网络反向传播算法的步骤
Dec 24 #Python
python异常处理和日志处理方式
Dec 24 #Python
Python 音频生成器的实现示例
Dec 24 #Python
Python concurrent.futures模块使用实例
Dec 24 #Python
Python hmac模块使用实例解析
Dec 24 #Python
You might like
PHP实现按之字形顺序打印二叉树的方法
2018/01/16 PHP
对JavaScript的eval()中使用函数的进一步讨论
2008/07/26 Javascript
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
2011/06/21 Javascript
jQuery 事件的命名空间简单了解
2013/11/22 Javascript
Javascript 多物体运动的实现
2014/12/24 Javascript
JavaScript中的立即执行函数表达式介绍
2015/03/15 Javascript
javascript Array 数组常用方法
2015/04/05 Javascript
JavaScript字符串删除重复字符的方法
2015/12/25 Javascript
JS实现为排序好的字符串找出重复行的方法
2016/03/02 Javascript
JS未跨域操作iframe里的DOM
2016/06/01 Javascript
vue从使用到源码实现教程详解
2016/09/19 Javascript
javaScript中封装的各种写法示例(推荐)
2017/07/03 Javascript
JavaScript实现旋转轮播图
2020/08/18 Javascript
EasyUI框架 使用Ajax提交注册信息的实现代码
2017/09/27 Javascript
Bootstrap Tooltip显示换行和左对齐的解决方案
2017/10/11 Javascript
JS代码实现电脑配置检测功能
2018/03/21 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
2019/07/17 Javascript
微信小程序实现Swiper轮播图效果
2019/11/22 Javascript
Django中对数据查询结果进行排序的方法
2015/07/17 Python
python 根据字典的键值进行排序的方法
2019/07/24 Python
Python tkinter实现简单加法计算器代码实例
2020/05/13 Python
python爬虫用mongodb的理由
2020/07/28 Python
python遍历路径破解表单的示例
2020/11/21 Python
HTML5 背景的显示区域实现
2020/07/09 HTML / CSS
中国综合网上购物商城:苏宁易购
2016/08/09 全球购物
Topshop美国官网:英国快速时尚品牌
2019/05/16 全球购物
屈臣氏泰国官网:Watsons TH
2021/02/23 全球购物
老干部工作先进集体事迹材料
2014/05/21 职场文书
法定授权委托证明书
2014/09/27 职场文书
2014年仓管员工作总结
2014/11/18 职场文书
学校光盘行动倡议书
2015/04/28 职场文书
旗帜观后感
2015/06/08 职场文书
幼儿园保育员随笔
2015/08/14 职场文书
微信小程序实现录音Record功能
2021/05/09 Javascript
css如何把元素固定在容器底部的四种方式
2022/06/16 HTML / CSS