递归寻路算法不断返回 None
Recursive pathfinding algorithm keeps returning None
为了在 2D 地图中找到路径,我在 Person
实例上调用 get_building_path()
,但它一直返回 None
。我不知道出了什么问题,因为我是 Python.
的新手
下面我提供了重现该问题所需的代码。我已经尝试了很多东西,但我仍然不明白为什么它一直返回 None
:
from random import randint
width = 1400
height = 700
gridSize = 20
people = []
buildings = []
map = [['' for c in range(int(width/gridSize))] for r in range(int(height/gridSize))]
class Person():
def __init__(self,row,col):
self.row = row
self.col = col
def getMin(self,paths): # find shortest path
if (len(paths) == 0): return [] # if nothing was found, return an empty list
min = paths[0]
for n in range(1,len(paths),1):
if ((paths[n] != None and len(paths[n]) < len(min)) or min==[None]): # make sure [None] is not returned since that would be the shortest
min = paths[n]
return min
def path_helper(self,visited,path,row,col,destR,destC): # destR and destC are the row and col of the target position
if ((row,col) in visited or map[row][col] != 'road' or row < 0 or row > len(map)-1 or col < 0 or col > len(map[0])-1):
return None # make sure the current position has not been visited, and is in bounds of the map
path.append([row,col]) # add current position to the path
visited.append((row,col)) # mark current position as visited
if (row == destR and col == destC): # return the path if we found the destination
return path
others=[] # look in all four directions from the current position
others.append(self.path_helper(visited,path[:],row-1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row+1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row,col-1,destR,destC))
others.append(self.path_helper(visited,path[:],row,col+1,destR,destC))
others.remove(None) # remove any path that did not find anything
return self.getMin(others)
def get_path(self,row,col):
return self.path_helper([],[],self.row,self.col,row,col) #call to recursive helper function
def get_building_path(self,type):
all = []
for b in buildings:
if (b.type == type):
all.append(b)
target = all[randint(0,len(all)-1)] #get a random buildings of type 'type'
return self.get_path(target.row,target.col)
class Building():
def __init__(self,type,row,col):
self.type = type
self.row = row
self.col = col
midrow = int(height/gridSize/2) #get midpoint of the map
midcol = int(width/gridSize/2)
people.append(Person(midrow+1,midcol+2))
for n in range(0,3,2): #add new buildings to buildings list, along with the map
buildings.append(Building('house',midrow+n,midcol-2))
map[midrow+n][midcol-2] = buildings[len(buildings)-1]
buildings.append(Building('school',midrow+n,midcol-1))
map[midrow+n][midcol-1] = buildings[len(buildings)-1]
buildings.append(Building('workplace',midrow+n,midcol))
map[midrow+n][midcol] = buildings[len(buildings)-1]
buildings.append(Building('store',midrow+n,midcol+1))
map[midrow+n][midcol+1] = buildings[len(buildings)-1]
buildings.append(Building('restaurant',midrow+n,midcol+2))
map[midrow+n][midcol+2] = buildings[len(buildings)-1]
for n in range(-2,3,1): #add roads to connect the buildings together
map[midrow+1][midcol+n] = 'road'
testPath = people[0].get_building_path('house')
print(testPath)
如果您想直观地看到建筑物和道路的位置,这里有一张图片:
从左到右,建筑物是'house'、'school'、'workplace'、'store'、'restaurant'。
蓝色圆圈代表人物。
(左上角建筑物的位置为(17,33) (row,col)
几个问题:
others.remove(None)
仅删除第一次出现的 None
map[row][col] != 'road'
到达目标时将为 True,因此此测试应仅在 确认您尚未到达目标后进行。
当 row
或 col
超出范围时,map[row][col] != 'road'
可能会出错,因此您应该 首先 进行范围检查
所以path_helper
应该更正为:
def path_helper(self,visited,path,row,col,destR,destC):
path.append([row,col])
# next IF should come before the other IF:
if row == destR and col == destC: # no parentheses needed
return path
# reorder conditions in next IF statement
if (row,col) in visited or row < 0 or row > len(map)-1 or col < 0 or col > len(map[0])-1 or map[row][col] != 'road':
return None
visited.append((row,col))
others=[]
others.append(self.path_helper(visited,path[:],row-1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row+1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row,col-1,destR,destC))
others.append(self.path_helper(visited,path[:],row,col+1,destR,destC))
others = list(filter(None, others)) # delete ALL occurrences of None
return self.getMin(others)
还有其他一些可以改进的地方(比如对 visited
使用 set
,而不是用你自己的变量隐藏原生 map
函数),但是上面提到的更改将使它起作用。
为了在 2D 地图中找到路径,我在 Person
实例上调用 get_building_path()
,但它一直返回 None
。我不知道出了什么问题,因为我是 Python.
下面我提供了重现该问题所需的代码。我已经尝试了很多东西,但我仍然不明白为什么它一直返回 None
:
from random import randint
width = 1400
height = 700
gridSize = 20
people = []
buildings = []
map = [['' for c in range(int(width/gridSize))] for r in range(int(height/gridSize))]
class Person():
def __init__(self,row,col):
self.row = row
self.col = col
def getMin(self,paths): # find shortest path
if (len(paths) == 0): return [] # if nothing was found, return an empty list
min = paths[0]
for n in range(1,len(paths),1):
if ((paths[n] != None and len(paths[n]) < len(min)) or min==[None]): # make sure [None] is not returned since that would be the shortest
min = paths[n]
return min
def path_helper(self,visited,path,row,col,destR,destC): # destR and destC are the row and col of the target position
if ((row,col) in visited or map[row][col] != 'road' or row < 0 or row > len(map)-1 or col < 0 or col > len(map[0])-1):
return None # make sure the current position has not been visited, and is in bounds of the map
path.append([row,col]) # add current position to the path
visited.append((row,col)) # mark current position as visited
if (row == destR and col == destC): # return the path if we found the destination
return path
others=[] # look in all four directions from the current position
others.append(self.path_helper(visited,path[:],row-1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row+1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row,col-1,destR,destC))
others.append(self.path_helper(visited,path[:],row,col+1,destR,destC))
others.remove(None) # remove any path that did not find anything
return self.getMin(others)
def get_path(self,row,col):
return self.path_helper([],[],self.row,self.col,row,col) #call to recursive helper function
def get_building_path(self,type):
all = []
for b in buildings:
if (b.type == type):
all.append(b)
target = all[randint(0,len(all)-1)] #get a random buildings of type 'type'
return self.get_path(target.row,target.col)
class Building():
def __init__(self,type,row,col):
self.type = type
self.row = row
self.col = col
midrow = int(height/gridSize/2) #get midpoint of the map
midcol = int(width/gridSize/2)
people.append(Person(midrow+1,midcol+2))
for n in range(0,3,2): #add new buildings to buildings list, along with the map
buildings.append(Building('house',midrow+n,midcol-2))
map[midrow+n][midcol-2] = buildings[len(buildings)-1]
buildings.append(Building('school',midrow+n,midcol-1))
map[midrow+n][midcol-1] = buildings[len(buildings)-1]
buildings.append(Building('workplace',midrow+n,midcol))
map[midrow+n][midcol] = buildings[len(buildings)-1]
buildings.append(Building('store',midrow+n,midcol+1))
map[midrow+n][midcol+1] = buildings[len(buildings)-1]
buildings.append(Building('restaurant',midrow+n,midcol+2))
map[midrow+n][midcol+2] = buildings[len(buildings)-1]
for n in range(-2,3,1): #add roads to connect the buildings together
map[midrow+1][midcol+n] = 'road'
testPath = people[0].get_building_path('house')
print(testPath)
如果您想直观地看到建筑物和道路的位置,这里有一张图片:
从左到右,建筑物是'house'、'school'、'workplace'、'store'、'restaurant'。
蓝色圆圈代表人物。
(左上角建筑物的位置为(17,33) (row,col)
几个问题:
others.remove(None)
仅删除第一次出现的None
map[row][col] != 'road'
到达目标时将为 True,因此此测试应仅在 确认您尚未到达目标后进行。
当 map[row][col] != 'road'
可能会出错,因此您应该 首先 进行范围检查
row
或 col
超出范围时,所以path_helper
应该更正为:
def path_helper(self,visited,path,row,col,destR,destC):
path.append([row,col])
# next IF should come before the other IF:
if row == destR and col == destC: # no parentheses needed
return path
# reorder conditions in next IF statement
if (row,col) in visited or row < 0 or row > len(map)-1 or col < 0 or col > len(map[0])-1 or map[row][col] != 'road':
return None
visited.append((row,col))
others=[]
others.append(self.path_helper(visited,path[:],row-1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row+1,col,destR,destC))
others.append(self.path_helper(visited,path[:],row,col-1,destR,destC))
others.append(self.path_helper(visited,path[:],row,col+1,destR,destC))
others = list(filter(None, others)) # delete ALL occurrences of None
return self.getMin(others)
还有其他一些可以改进的地方(比如对 visited
使用 set
,而不是用你自己的变量隐藏原生 map
函数),但是上面提到的更改将使它起作用。