Le plus gros problème avec votre code est que vous ne faites rien pour éviter que les mêmes coordonnées soient visitées plusieurs fois. Cela signifie que le nombre de noeuds visités est de garanti de croître de manière exponentielle, puisqu'il peut faire de nombreux allers-retours sur les premiers nœuds.
La meilleure façon d'éviter la duplication est de maintenir une set
des coordonnées que nous avons ajoutées à la file d'attente (bien que si votre node
les valeurs sont hachables, vous pourriez être en mesure de les ajouter directement à l'ensemble au lieu de coordonner les tuples). Puisque nous effectuons une recherche en largeur, nous atteindrons toujours une coordonnée donnée par (l'un des) chemin(s) le(s) plus court(s), nous n'aurons donc jamais à nous soucier de trouver un meilleur chemin par la suite.
Essayez quelque chose comme ça :
def get_distance(x1,y1,x2,y2):
neighbors = [(-1,0),(1,0),(0,-1),(0,1)]
nodes = [(square_pos[x1,y1],0)]
seen = set([(x1, y1)])
for node, path_length in nodes:
if path_length == 50:
break
if node.x == x2 and node.y == y2:
return path_length
for nx, ny in neighbors:
try:
square = square_pos[node.x + nx, node.y + ny]
if square.lightcycle == None and (square.x, square.y) not in seen:
nodes.append((square, path_length + 1))
seen.add((square.x, square.y))
except KeyError:
pass
return 50
J'ai également simplifié un peu la boucle. Plutôt que de changer la liste après chaque profondeur, vous pouvez simplement utiliser une boucle et ajouter à sa fin pendant que vous itérez sur les valeurs précédentes. Je m'arrête toujours si un chemin n'a pas été trouvé en moins de 50 étapes (en utilisant la distance stockée dans le 2-tuple, plutôt que le nombre de passages de la boucle externe). Une autre amélioration pourrait être d'utiliser un collections.dequeue
pour la file d'attente, puisque vous pourriez efficacement pop
d'une extrémité tandis que append
à l'autre bout. Cela ne fera probablement pas une grande différence, mais pourrait éviter un peu d'utilisation de la mémoire.
J'ai également évité la plupart des indexations par un et par zéro en faveur d'un déballage dans des noms de variables séparés dans le fichier for
boucles. Je pense que c'est beaucoup plus facile à lire, et cela évite toute confusion puisque les deux différents types de 2-tuples avaient des significations différentes (l'un est un node, distance
l'autre est x, y
).