AEtoile.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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 sqrt
  5. # import time
  6. # from PyQt4.QtGui import QApplication
  7. #pour des performances correctes, ne pas utiliser pour des deplacements de plus de 100 cases
  8. def distance(coord1, coord2):
  9. return sqrt((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)
  10. def distanceCarree(coord1, coord2):
  11. """bcp plus rapide a calculer que la distance reelle"""
  12. return (coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2
  13. class N():
  14. """noeud du chemin"""
  15. def __init__(self, coord):
  16. self.parent = None #coord du noeud qui a amene a ce noeud-ci
  17. self.coord = coord
  18. self.kDep = 1
  19. self.coutG = 0
  20. self.coutH = 0
  21. self.cout = 0
  22. def creer(self, parent, cible, kDep):
  23. self.parent = parent
  24. self.kDep = kDep
  25. self.coutH = distanceCarree(self.coord, cible)
  26. self.coutG = self.parent.coutG + self.kDep
  27. self.cout = self.coutG + self.coutH
  28. class Chemin():
  29. def __init__(self, plateau, origine, cible, z1 = 0, z2 = 0):
  30. self.plateau = plateau
  31. self.origine = origine
  32. self.cible = cible
  33. self.echec = False
  34. self.stop = False
  35. self._z1 = z1
  36. self._z2 = z2
  37. ###active l'evolution sur le plateau
  38. self.debug = False
  39. def arreter(self):
  40. self.stop = True
  41. def liste(self):
  42. """retourne la liste des coord a traverser pour atteindre l'objectif
  43. se base sur la fonction estFranchissable() des cases"""
  44. # if self.debug:
  45. # for coord in self.plateau.cases:
  46. # self.plateau.cases[coord].majEstCibleCurseur(False)
  47. # self.plateau.cases[coord].majEstCibleAttaque(False)
  48. # QApplication.processEvents()
  49. nO = N(self.origine)
  50. nO.parent = None
  51. nO.coutG = 0
  52. nO.cout = 0
  53. filOuvert = [] #"liste ouverte": noeuds etudies et a etudier
  54. filFerme = [nO] #"liste fermee": noeuds retenus
  55. chemin = []
  56. position = nO
  57. self.echec = False
  58. #on continue jusqu'a tomber sur la case cible, ou jusqu'a un echec
  59. it = 0
  60. while position.coord != self.cible and not self.echec:
  61. it += 1
  62. ## print "iteration: ", i
  63. #on etudie tous les voisins de la case en cours
  64. for coord in self.plateau.cases[position.coord].voisins:
  65. if self.stop: return []
  66. #on elimine les cases deja retenues (celles qui sont dans le fil ferme)
  67. trouve = False
  68. for nTest in filFerme:
  69. if self.stop: return []
  70. if nTest.coord == coord:
  71. trouve = True
  72. if not trouve:
  73. #on elimine les cases infranchissables
  74. cout = self.plateau.coutDep(position.coord, coord)
  75. if cout >= 0:
  76. noeud = N(coord)
  77. #on calcule le cout de la case
  78. if self.stop: return []
  79. noeud.creer(position, self.cible, cout)
  80. # noeud.creer(position, self.cible, self.plateau.cases[coord].coutDep())
  81. #si le noeud est trouve dans la liste ouverte, on le compare a celui-ci
  82. # si ce nouveau noeud a un cout moindre, on remplace
  83. # sinon on ajoute ce noeud a la liste ouverte
  84. trouve = False
  85. for nTest in filOuvert:
  86. if self.stop: return []
  87. if nTest.coord == noeud.coord:
  88. if noeud.cout < nTest.cout:
  89. nTest.parent = noeud.parent
  90. nTest.cout = noeud.cout
  91. trouve = True
  92. if not trouve:
  93. filOuvert.append(noeud)
  94. # if self.debug:
  95. # self.plateau.cases[noeud.coord].majEstCibleCurseur(True, True)
  96. # time.sleep(0.05)
  97. # QApplication.processEvents()
  98. #on parcourt les noeuds de la liste ouverte
  99. #et on cherche le meilleur noeud (le cout le plus faible)
  100. #si trouve: on l'ajoute a la liste fermee, on le retire de la liste ouverte et on continue
  101. #sinon, le chemin n'existe pas
  102. meilleur = None
  103. for noeud in filOuvert:
  104. if self.stop: return []
  105. if meilleur == None:
  106. meilleur = noeud
  107. else:
  108. if noeud.cout < meilleur.cout:
  109. meilleur = noeud
  110. if meilleur:
  111. filFerme.append(meilleur)
  112. # if self.debug:
  113. # self.plateau.cases[meilleur.coord].majEstCibleCurseur(True, False)
  114. # QApplication.processEvents()
  115. # time.sleep(0.05)
  116. filOuvert.remove(meilleur)
  117. position = meilleur
  118. else:
  119. self.echec = True
  120. #on revient de parent en parent jusqu'au depart
  121. if not self.echec:
  122. while position.coord != self.origine:
  123. if self.stop: return []
  124. chemin.insert(0, (position.coord, position.kDep))
  125. # if self.debug:
  126. # self.plateau.cases[position.coord].majEstCibleCurseur(False)
  127. # self.plateau.cases[position.coord].majEstCibleAttaque(True)
  128. # QApplication.processEvents()
  129. position = position.parent
  130. else:
  131. chemin = []
  132. return chemin