如何解决A *路径查找算法有时即使在存在路径的情况下也找不到路径Python
我用Python创建了一个自定义路径A *寻路算法,但有时即使明显存在路径,它有时甚至找不到到末端节点的路径。这是我的实现。
# this is my Node class. I am representing the whole maze as a matrix and every cell
# of that matrix is a Node Object
class Node():
def __init__(self,i,j):
self.i = i
self.j = j
self.isWall = False
self.isOpen = None
self.f = 0
self.g = 0
self.h = 0
self.neighbors = []
self.prevIoUs = None
def __repr__(self):
return f'< i = {self.i},j = {self.j},prevIoUs = {self.prevIoUs} >'
def add_neighbors(self,grid,diagonal):
i = self.i
j = self.j
if i > 0:
self.neighbors.append(grid[i - 1][j])
if i < len(grid) - 1:
self.neighbors.append(grid[i + 1][j])
if j > 0:
self.neighbors.append(grid[i][j - 1])
if j < len(grid) - 1:
self.neighbors.append(grid[i][j + 1])
if diagonal:
# for diagonal neighbors
# down and right
if i < len(grid) - 1 and j < len(grid) - 1:
self.neighbors.append(grid[i + 1][j + 1])
# up and right
if i > 0 and j < len(grid) - 1:
self.neighbors.append(grid[i - 1][j + 1])
#down and left
if i < len(grid) - 1 and j > 0:
self.neighbors.append(grid[i + 1][j - 1])
#up and left
if i > 0 and j > 0:
self.neighbors.append(grid[i - 1][j - 1])
反复浏览并设置节点
def make_grid(length):
main_grid = []
for i in range(length):
lst = []
for j in range(length):
node = Node(i,j)
# 30 % chance that the current node will be set as a wall
if random.randrange(1,101) > 70 and i != 0 and j != 0: node.isWall = True
lst.append(node)
main_grid.append(lst)
for i in range(length):
for j in range(length):
main_grid[i][j].add_neighbors(main_grid,diagonal = True)
return main_grid
# Below is how the above function 'make_grid' is called
# making the grid
grid_len = 25
main_grid = make_grid(grid_len)
path = [] # to reconstruct the optimal path
# Hscore function
def getHscore(node,endNode):
return sqrt(abs(node.i - endNode.i)**2 + abs(node.j - endNode.j)**2)
下面是实际的算法实现
# A* PATHFINDING ALGORITHM
def aStar(start_node,end_node):
# node.f = node.g + node.h
# node.g = distance of current node from the starting node
# node.h = distance of current node from the end node
start_node.g = 0
start_node.h = getHscore(start_node,end_node)
start_node.f = start_node.g + start_node.h
open_set = [start_node]
closed_set = []
if start_node.isWall:
print("The start node is a wall")
return
while True:
if len(open_set) < 1:
print('No Solutions Found')
break
current_node = open_set[0]
for node in open_set:
if node.f < current_node.f:
current_node = node
current_node.isOpen = True
# print(f'current_node = {current_node.i,current_node.j}',end = " ")
if current_node == end_node:
temp = end_node
path.append(temp)
while temp.prevIoUs is not None:
path.append(temp.prevIoUs)
temp = temp.prevIoUs
print("DONE")
colorFinalPath(main_grid)
break
# current_node.isPath = True
current_node.isOpen = False
open_set.remove(current_node)
closed_set.append(current_node)
for neighbor in current_node.neighbors:
# assuming 1 as the distance btw two neighbouring points that aren't diagonally
# neighbors
# need to add 1.14 if neighbor is diagonal. add propery to node class to check if neighbor is diagonal
if neighbor in closed_set:
continue
tempG = current_node.g + getHscore(current_node,neighbor)
if neighbor not in open_set and not neighbor.isWall:
neighbor.g = tempG
open_set.append(neighbor)
neighbor.isOpen = True
neighbor.prevIoUs = current_node
if tempG >= neighbor.g:
continue # there is no better path
# neighbor was found in the open set,so we check if we can get to it in
# a better way as tempG is Now less than neighbor.g
neighbor.prevIoUs = current_node
neighbor.g = tempG
neighbor.h = getHscore(neighbor,end_node)
neighbor.f = neighbor.g + neighbor.h
show_steps(main_grid,start_node,end_node)
一些屏幕截图 在第三张图中,显然在起始节点(左上)和结束节点(右下)之间有一条路径,但是找不到任何解决方案。
请告诉我我的实现有什么问题。感谢您的帮助
解决方法
我在这段代码中看到了一些问题:
tempG = current_node.g + getHScore(current_node,neighbor)
if neighbor not in open_set and not neighbor.isWall:
neighbor.g = tempG
open_set.append(neighbor)
neighbor.isOpen = True
neighbor.previous = current_node
if tempG >= neighbor.g:
continue # there is no better path
-
当邻居是一堵墙时,您应该立即跳过它。因此,在顶部添加:
if neighbor.isWall: continue
这也意味着您可以从已经拥有的
if
上取下墙面支票 -
当您第一次设置
g
组件(即执行中间部分)时,检查路径是否存在更好的条件也将成立。这不应该发生。因此,将if
更改为elif
:if neighbor not in open_set: # ... etc ... elif tempG >= neighbor.g: continue # there is no better path
-
您的
make_grid
代码可能会将结束节点标记为墙。您不会拒绝这种情况,然后您的代码将continue
并作为邻居跳过该代码以放入开放集中。从图像中还不清楚这是否发生,因为您将结束节点涂成了蓝色。
那么,问题就少了,但是您有时会为同一节点多次调用getHScore
。显然,该函数将为每个调用返回相同的值。因此,您可以对此进行改进。例如,通过在if
条件下移动该行:
if neighbor.h == 0:
neighbor.h = getHScore(neighbor,end_node)
我不知道这是否有意,但对角台阶的成本为2(1²+1²),与步行到同一广场的2步相比没有优势。这是一个很小的细节,因为您将首先通过对角线步骤访问那些节点,然后忽略具有相同成本的路径。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。