【问题标题】:Recursive pathfinding algorithm keeps returning None递归寻路算法不断返回 None
【发布时间】:2021-02-24 21:14:05
【问题描述】:

为了在 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)

如果您想直观地查看建筑物和道路的位置,请看下面的图片:

从左到右,建筑物是“房子”、“学校”、“工作场所”、“商店”、“餐厅”。

蓝色圆圈代表人。

(左上角建筑物的位置为 (17,33) (row,col)

【问题讨论】:

  • 请提供预期的minimal, reproducible example (MRE)。我们应该能够复制和粘贴您的代码的连续块,执行该文件,并重现您的问题以及跟踪问题点的输出。这让我们可以根据您的测试数据和所需的输出来测试我们的建议。我们希望您执行基本诊断以包含在您的帖子中。至少,在错误点打印可疑值并追溯它们的来源。
  • 见:stackoverflow.com/help/minimal-reproducible-example。虽然我建议只关注你的调试器,看看它变成了None
  • 好的,我会努力制作 MRE,对此感到抱歉

标签: python recursion path-finding


【解决方案1】:

几个问题:

  • others.remove(None) 仅删除第一次出现的 None
  • map[row][col] != 'road' 将在到达目标时为 True,因此此测试应仅在您确认尚未到达目标后进行。
  • rowcol 超出范围时,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)

还有其他一些可以改进的地方(比如使用set 代替visited,而不是使用您自己的变量来隐藏本机map 函数),但上述更改将使其正常工作。

【讨论】:

  • 非常感谢,效果很好!
猜你喜欢
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
  • 2014-12-06
  • 2020-07-10
  • 2018-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多