# -*- 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*寻路算法实现的更多相关文章

  1. A星寻路算法介绍

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  2. A*寻路算法探究

    A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...

  3. A*寻路算法

    对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...

  4. 算法:Astar寻路算法改进,双向A*寻路算法

    早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...

  5. 算法:Astar寻路算法改进

    早前写了一篇<RCP:gef智能寻路算法(A star)> 出现了一点问题. 在AStar算法中,默认寻路起点和终点都是N x N的方格,但如果用在路由上,就会出现问题. 如果,需要连线的 ...

  6. js实现A*寻路算法

    这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...

  7. 用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...

  8. A星寻路算法

    A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...

  9. A*寻路算法的探寻与改良(三)

    A*寻路算法的探寻与改良(三) by:田宇轩                                        第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细 ...

随机推荐

  1. Java中for each与正常for循环效率对比

    循环ArrayList时,普通for循环比foreach循环花费的时间要少一点:循环LinkList时,普通for循环比foreach循环花费的时间要多很多. 当我将循环次数提升到一百万次的时候,循环 ...

  2. C++入门经典-例6.18-数组的动态分配,动态获得斐波那契数列

    1:有时在获得一定的信息之前,我们并不确定数组的大小.动态分配数组则可以使用变量作为数组的大小,使数组的大小符合我们的要求. 2:科普一下斐波纳契数列:斐波那契数列指的是这样一个数列 1, 1, 2, ...

  3. es6 字符串 对象 拓展 及 less 的语法

    es6 字符串 对页面渲染的几种方式:字符串拼接 文档碎片 dom操作 模板 es6 又提供了一种新的对页面渲染的方式:字符串模板(高级版的字符串拼接) 模板字符串标识符是 反引号 ( `` ) 英文 ...

  4. 一、基础篇--1.1Java基础-equals与==的区别

    ==: ==比较的是变量内存中存放的对象的内存地址,用来判断两个对象地址是否相同,比较的是否是同一个对象. 1.两边的操作数必须是同一类型,不然编译不通过. 2.如果是基本数据类型比较,值相等则为tr ...

  5. csp2019 Emiya家今天的饭题解

    qwq 由于窝太菜了,实在是不会,所以在题解的帮助下过掉了这道题. 写此博客来整理一下思路 正文 传送 简化一下题意:现在有\(n\)行\(m\)列数,选\(k\)个数的合法方案需满足: 1.一行最多 ...

  6. DeepFaceLab错误:DLL Load failed 找不到指定模块!

    这个错误不知道多少人遇到了,我反正是看到过不少次了.但是一直没有花时间去研究. 今日有空帮群友远程了一下,虽然搞了一会儿,最终还是搞定了,分享一下经验. ​ 问题描述:在执行2号脚本,视频转图片的时候 ...

  7. linux(centOS7)的基本操作(四) 定时任务——crontab

    概述 对于Java开发人员,定时任务并不陌生,无非是让系统在特定时间执行特定的命令或程序.例如spring提供的@Scheduled注解.OpenSymphony提供的quartz框架,都可以实现定时 ...

  8. Vmware centos 虚拟机 磁盘扩容

    一,lvm ext4 扩容 1,首先关闭虚拟机,在vSphere Client 将硬盘大小增加或者新增一块硬盘 (从原来10G增加到50G) 2,开机 此时,df -hT只显示原来的磁盘大小 使用 f ...

  9. 关于Docx动态控制word模板文件的数据

    博客:https://www.cnblogs.com/24klr/ github: https://github.com/luoruiemail/Dynamic_Word_Web 参考资料:https ...

  10. [转帖]站点部署,IIS配置优化指南

    站点部署,IIS配置优化指南 https://www.cnblogs.com/heyuquan/p/deploy-iis-set-performance-guide.html 挺值得学习的 毕竟之前很 ...