问题
First of all, excuse the bad title, but I don't know how to describe this in just one sentence...
Given a grid with 3 kinds of fields, empty fields, walls and exits, I wrote a program that checks for every empty field, whether that field is "safe". A person walks through that grid, but can only walk non-diagonally and can't go through walls. The person, starting at one field, chooses one direction at random and starts walking that way. Once it hits a wall, it chooses a direction at random again, starting to move into that direction and so on. A field is considered safe if a person traversing the grid as described above, starting at that field, is guaranteed to find an exit at some point.
I wrote a Python program to solve this problem. It builds a "tree" for every field it checks, containing every possible route from that field. I have a function that just returns the "parent" of a given node, by recursively adding the parent of the current node to a list of nodes until it reaches the topmost node.
The program works as expected when checking only one field, for example (1, 4). However it doesn't work when checking all fields of the example grid.
I already looked into it and realized that the alle_parents() function which returns all parents of a given node yields unexpected results when checking all nodes. E.g. when checking the field (1, 4), one child of that node is (1, 8). The parents of (1, 8) should just be (1, 4). That's not the case, though. alle_parents((1, 8)) returns many different fields that shouldn't be there. However I can't figure out why it behaves as it does. My only guess is that it has to do with "left-over" data/GC not working as intended.
Relevant code:
class Knoten():
def __init__(self, x, y, parent = None):
self.x = x
self.y = y
self.parent = parent
self.children = []
n = len(spielfeld)
m = len(spielfeld[0])
for k in range(n):
for j in range(m):
if spielfeld[k][j] not in [None, '#', 'E']:
baum = []
i = 0
ebene = []
ebene.append(Knoten(k, j))
baum.append(ebene)
i += 1
while i <= 100:
ebene = []
for knoten in baum[i - 1]:
children = []
if spielfeld[knoten.x][knoten.y] == 'E':
continue
for feld in next_feld(knoten.x, knoten.y):
knoten_neu = Knoten(feld[0], feld[1], knoten)
hinzufuegen = True
for parent in alle_parents(knoten_neu):
if knoten_neu.x == parent.x and knoten_neu.y == parent.y:
hinzufuegen = False
if hinzufuegen:
ebene.append(knoten_neu)
children.append(knoten_neu)
knoten.children = children
if children == []:
if spielfeld[knoten.x][knoten.y] != 'E':
spielfeld[k][j] = '%' # Field not safe
baum.append(ebene)
i += 1
def alle_parents(knoten, parents = []):
if knoten.parent == None:
return parents
else:
parents.append(knoten.parent)
return alle_parents(knoten.parent, parents)
The example map I'm using:
############
# # # #
# ## #
# # E# #
# ## #
# #
# #E E###
############
Full code (parts of it are German, sorry for that): http://pastebin.com/3XUBbpkK
回答1:
I suspect your issue is a common Python gotcha. This line:
def alle_parents(knoten, parents = []):
Creates an empty array when the module is loaded, NOT every time the function is called. Future calls to alle_parents() will reuse the same array (which may have grown in size) instead of a new empty array! A good way to fix is to do this:
def alle_parents(knoten, parents = None):
parents = parents or []
来源:https://stackoverflow.com/questions/34815882/pathfinding-code-produces-unexpected-results