Python3 A*尋路算法實現(xiàn)方式
更新時間:2019年12月24日 19:08:42 作者:gmHappy
今天小編就為大家分享一篇Python3 A*尋路算法實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
我就廢話不多說了,直接上代碼吧!
# -*- coding: utf-8 -*-
import math
import random
import copy
import time
import sys
import tkinter
import threading
# 地圖
tm = [
'############################################################',
'#S............................#............#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#..................#......#.....#.....#.........#',
'#..........#.........................#.....#.....#.........#',
'#..........#..................#......#.....#...............#',
'#..#########..................#......#.....#.....#.........#',
'#..#..........................#......#.....#.....#.........#',
'#..#..........................#......#.....#.....#.........#',
'#..############################......#.....#.....#.........#',
'#.............................#......#.....#.....#.........#',
'#.............................#......#...........#.........#',
'#######.##################################################.#',
'#....#........#.................#.............#............#',
'#....#........#........#........#.............#............#',
'#....####.#####........#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........#.............#............#',
'#.........#............#........####.#######.##............#',
'#.........#............#........#....#.......#.............#',
'#.........#............#........#....#.......#.............#',
'#......................#........#....#.......#.............#',
'#.........#............#........##.########..#.............#',
'#.........#............#..................#..########.######',
'#.........#............#..................#...............E#',
'############################################################']
# 存儲搜索時的地圖
test_map = []
#----------- 開放列表和關(guān)閉列表的元素類型,parent用來在成功的時候回溯路徑 -----------
class Node_Elem:
def __init__(self, parent, x, y, dist):
self.parent = parent # 回溯父節(jié)點
self.x = x # x坐標(biāo)
self.y = y # y坐標(biāo)
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表
# 創(chuàng)建畫布
self.root = root # 畫布根節(jié)點
self.width = w # 地圖w,默認(rèn)60
self.height = h # 地圖h,默認(rèn)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()
# 按鍵響應(yīng)程序
def __bindEvents(self):
self.root.bind("e", self.quite) # 退出程序
# 退出程序
def quite(self, evt):
self.root.destroy()
# 更改標(biāo)題
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):
# 生成障礙節(jié)點,半徑為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方法在坐標(biāo)處繪制文字
text=u'Start', # 所繪制文字的內(nèi)容
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方法在坐標(biāo)處繪制文字
text=u'End', # 所繪制文字的內(nèi)容
fill='black' # 所繪制文字的顏色為灰色
)
# 生成路徑節(jié)點,半徑為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", # 填充藍(lán)色
outline="#ffffff", # 輪廓白色
tags="node",
)
# 生成搜索區(qū)域,半徑為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",
)
# 查找路徑的入口函數(shù)
def find_path(self):
# 構(gòu)建開始節(jié)點
p = Node_Elem(None, self.s_x, self.s_y, 0.0)
while True:
# 擴(kuò)展節(jié)點
self.extend_round(p)
# 如果open表為空,則不存在路徑,返回
if not self.open:
return
# 取F值最小的節(jié)點
idx, p = self.get_best()
# 到達(dá)終點,生成路徑,返回
if self.is_target(p):
self.make_path(p)
return
# 把此節(jié)點加入close表,并從open表里刪除
self.close.append(p)
del self.open[idx]
# 生成路徑
def make_path(self, p):
# 從結(jié)束點回溯到開始點,開始點的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值最小的節(jié)點
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 為當(dāng)前路徑長度,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))
# 擴(kuò)展節(jié)點
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
# 構(gòu)造新的節(jié)點,計算距離
node = Node_Elem(p, new_x, new_y, p.dist + self.get_cost(
p.x, p.y, new_x, new_y))
# 新節(jié)點在關(guān)閉列表,則忽略
if self.node_in_close(node):
continue
i = self.node_in_open(node)
# 新節(jié)點在open表
if i != -1:
# 當(dāng)前路徑距離更短
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
# 檢查節(jié)點是否在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
# 檢查節(jié)點是否在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
# 獲取起點坐標(biāo)
def get_start_XY():
return get_symbol_XY('S')
# 獲取終點坐標(biāo)
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
# 標(biāo)記路徑位置
def mark_path(l):
mark_symbol(l, '*')
# 標(biāo)記已搜索過的位置
def mark_searched(l):
mark_symbol(l, ' ')
# 標(biāo)記函數(shù)
def mark_symbol(l, s):
for x, y in l:
test_map[y][x] = s
# 標(biāo)記起點和終點
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'
# 將地圖字符串轉(zhuǎn)化為表
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
# 標(biāo)記已搜索過的位置
mark_searched(searched)
# 標(biāo)記路徑位置
mark_path(path)
# 標(biāo)記起點和終點
mark_start_end(s_x, s_y, e_x, e_y)
print(u"路徑長度:%d" % (len(path)))
print(u"搜索過的區(qū)域:%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*尋路算法實現(xiàn)方式就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
python 遺傳算法求函數(shù)極值的實現(xiàn)代碼
今天小編就為大家分享一篇python 遺傳算法求函數(shù)極值的實現(xiàn)代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
對django 模型 unique together的示例講解
今天小編就為大家分享一篇對django 模型 unique together的示例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
Python調(diào)用REST API接口的幾種方式匯總
這篇文章主要介紹了Python調(diào)用REST API接口的幾種方式匯總,幫助大家更好的利用python進(jìn)行自動化運(yùn)維,感興趣的朋友可以了解下2020-10-10
PyCharm實現(xiàn)遠(yuǎn)程調(diào)試的全過程(附圖文講解)
這篇文章主要介紹了PyCharm實現(xiàn)遠(yuǎn)程調(diào)試的全過程,文中通過圖文結(jié)合的方式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-05-05
python網(wǎng)絡(luò)編程示例(客戶端與服務(wù)端)
這篇文章主要介紹了python網(wǎng)絡(luò)編程示例,提供了客戶端與服務(wù)端,需要的朋友可以參考下2014-04-04
深度學(xué)習(xí)入門之Pytorch 數(shù)據(jù)增強(qiáng)的實現(xiàn)
這篇文章主要介紹了深度學(xué)習(xí)入門之Pytorch 數(shù)據(jù)增強(qiáng)的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02

