AEtoile.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. """algorithme de recherche du plus court chemin entre deux cases"""
  4. from math import *
  5. def distance(coord1, coord2):
  6. return sqrt((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)
  7. def distanceCarree(coord1, coord2):
  8. """bcp plus rapide a calculer que la distance reelle"""
  9. return (coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2
  10. def chemin(plateau, origine, cible):
  11. """retourne la liste des coord a traverser pour atteindre l'objectif
  12. se base sur la fonction estFranchissable() des cases"""
  13. nO = N(origine)
  14. nO.parent = None
  15. nO.coutG = 0
  16. nO.cout = 0
  17. filOuvert = [] #"liste ouverte": noeuds etudies et a etudier
  18. filFerme = [nO] #"liste fermee": noeuds retenus
  19. chemin = []
  20. position = nO
  21. echec = False
  22. it = 0
  23. #on continue jusqu'a tomber sur la case cible, ou jusqu'a un echec
  24. while position.coord != cible and not echec:
  25. it += 1
  26. print "##", it, position.coord
  27. #on etudie tous les voisins de la case en cours
  28. for coord in plateau.cases[position.coord].voisins:
  29. #on elimine les cases deja retenues (celles qui sont dans le fil ferme)
  30. trouve = False
  31. for nTest in filFerme:
  32. if nTest.coord == coord:
  33. trouve = True
  34. if not trouve:
  35. #on elimine les cases infranchissables
  36. if plateau.cases[coord].estFranchissable():
  37. noeud = N(coord)
  38. #on calcule le cout de la case
  39. noeud.creer(position, cible)
  40. #si le noeud est trouve dans la liste ouverte, on le compare a celui-ci
  41. # si ce nouveau noeud a un meilleur cout, on remplace
  42. # sinon on ajoute ce noeud a la liste ouverte
  43. trouve = False
  44. for nTest in filOuvert:
  45. if nTest.coord == noeud.coord:
  46. nTest.parent = noeud.parent
  47. nTest.cout = noeud.cout
  48. trouve = True
  49. print " | teste", coord, "maj", noeud.coutG, noeud.coutH
  50. if not trouve:
  51. filOuvert.append(noeud)
  52. print " | teste", coord, "ajout", noeud.coutG, noeud.coutH
  53. #on parcourt les noeuds de la liste ouverte
  54. #et on cherche le meilleur noeud (le cout le plus faible)
  55. #si trouve: on l'ajoute a la liste fermee, on le retire de la liste ouverte et on continue
  56. #sinon, le chemin n'existe pas
  57. meilleur = None
  58. for noeud in filOuvert:
  59. if meilleur == None:
  60. meilleur = noeud
  61. else:
  62. if noeud.cout < meilleur.cout:
  63. meilleur = noeud
  64. print " >> retenu", meilleur.coord, meilleur.cout
  65. if meilleur:
  66. filFerme.append(meilleur)
  67. filOuvert.remove(meilleur)
  68. position = meilleur
  69. else:
  70. echec = True
  71. for n in reversed(filFerme):
  72. chemin.append(n.coord)
  73. return chemin
  74. class N():
  75. """noeud du chemin"""
  76. def __init__(self, coord):
  77. self.parent = None #coord du noeud qui a amene a ce noeud-ci
  78. self.coord = coord
  79. self.coutG = 0
  80. self.coutH = 0
  81. self.cout = 0
  82. ## def __repr__(self):
  83. ## return "{} ({}+{}= {}) |".format(self.coord, self.coutG, self.coutH, self.cout)
  84. def creer(self, parent, cible):
  85. self.parent = parent
  86. self.coutH = distanceCarree(self.coord, cible)
  87. self.coutG = self.parent.coutG + 1
  88. self.cout = self.coutG + self.coutH
  89. ### pour les tests
  90. ##
  91. ##class Plateau():
  92. ## def __init__(self):
  93. ## self.cases = {}
  94. ##
  95. ##class Case():
  96. ## def __init__(self, coord):
  97. ## self.coord = coord
  98. ## self.voisins = []
  99. ## self.majVoisins()
  100. ##
  101. ## def majVoisins(self):
  102. ## for x in range(1, 6):
  103. ## for y in range(1, 6):
  104. ## if x in [self.coord[0] - 1, self.coord[0], self.coord[0] + 1] and \
  105. ## y in [self.coord[1] - 1, self.coord[1], self.coord[1] + 1] and \
  106. ## (x, y) != self.coord:
  107. ## self.voisins.append((x, y))
  108. ##
  109. ## def estFranchissable(self):
  110. ## return not (self.coord[0]==2 and self.coord[1] in [2, 3, 4, 5])
  111. ##
  112. ##
  113. ##plateau = Plateau()
  114. ##
  115. ##for x in range(1, 6):
  116. ## for y in range(1, 6):
  117. ## plateau.cases[(x, y)] = Case((x, y))
  118. ##
  119. ##
  120. ##depart = (1, 2)
  121. ##arrivee = (5, 5)
  122. ##
  123. ##print chemin(plateau, depart, arrivee)
  124. ##