AEtoile.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. import time
  6. from PyQt4.QtCore import *
  7. from PyQt4.QtGui import *
  8. #pour des performances correctes, ne pas utiliser pour de deplacements de plus de 100 cases
  9. def distance(coord1, coord2):
  10. return sqrt((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)
  11. def distanceCarree(coord1, coord2):
  12. """bcp plus rapide a calculer que la distance reelle"""
  13. return (coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2
  14. class N():
  15. """noeud du chemin"""
  16. def __init__(self, coord):
  17. self.parent = None #coord du noeud qui a amene a ce noeud-ci
  18. self.coord = coord
  19. self.kDep = 1
  20. self.coutG = 0
  21. self.coutH = 0
  22. self.cout = 0
  23. def creer(self, parent, cible, kDep):
  24. self.parent = parent
  25. self.kDep = kDep
  26. self.coutH = distanceCarree(self.coord, cible)
  27. self.coutG = self.parent.coutG + self.kDep
  28. self.cout = self.coutG + self.coutH
  29. class Chemin():
  30. def __init__(self, plateau, origine, cible):
  31. self.plateau = plateau
  32. self.origine = origine
  33. self.cible = cible
  34. self.echec = False
  35. self.stop = False
  36. ###active l'evolution sur le plateau
  37. self.debug = False
  38. def arreter(self):
  39. self.stop = True
  40. def liste(self):
  41. """retourne la liste des coord a traverser pour atteindre l'objectif
  42. se base sur la fonction estFranchissable() des cases"""
  43. if self.debug:
  44. for coord in self.plateau.cases:
  45. self.plateau.cases[coord].majEstCibleCurseur(False)
  46. self.plateau.cases[coord].majEstCibleAttaque(False)
  47. QApplication.processEvents()
  48. t0 = time.time()
  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. 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. if self.plateau.cases[coord].estFranchissable():
  75. noeud = N(coord)
  76. #on calcule le cout de la case
  77. if self.stop: return []
  78. noeud.creer(position, self.cible, self.plateau.cases[coord].coutDep())
  79. #si le noeud est trouve dans la liste ouverte, on le compare a celui-ci
  80. # si ce nouveau noeud a un cout moindre, on remplace
  81. # sinon on ajoute ce noeud a la liste ouverte
  82. trouve = False
  83. for nTest in filOuvert:
  84. if self.stop: return []
  85. if nTest.coord == noeud.coord:
  86. if noeud.cout < nTest.cout:
  87. nTest.parent = noeud.parent
  88. nTest.cout = noeud.cout
  89. trouve = True
  90. if not trouve:
  91. filOuvert.append(noeud)
  92. if self.debug:
  93. self.plateau.cases[noeud.coord].majEstCibleCurseur(True, True)
  94. time.sleep(0.05)
  95. QApplication.processEvents()
  96. #on parcourt les noeuds de la liste ouverte
  97. #et on cherche le meilleur noeud (le cout le plus faible)
  98. #si trouve: on l'ajoute a la liste fermee, on le retire de la liste ouverte et on continue
  99. #sinon, le chemin n'existe pas
  100. meilleur = None
  101. for noeud in filOuvert:
  102. if self.stop: return []
  103. if meilleur == None:
  104. meilleur = noeud
  105. else:
  106. if noeud.cout < meilleur.cout:
  107. meilleur = noeud
  108. if meilleur:
  109. filFerme.append(meilleur)
  110. if self.debug:
  111. self.plateau.cases[meilleur.coord].majEstCibleCurseur(True, False)
  112. QApplication.processEvents()
  113. time.sleep(0.05)
  114. filOuvert.remove(meilleur)
  115. position = meilleur
  116. else:
  117. echec = True
  118. #on revient de parent en parent jusqu'a l'arrivee
  119. if not self.echec:
  120. while position.coord != self.origine:
  121. if self.stop: return []
  122. chemin.insert(0, position.coord)
  123. if self.debug:
  124. self.plateau.cases[position.coord].majEstCibleCurseur(False)
  125. self.plateau.cases[position.coord].majEstCibleAttaque(True)
  126. QApplication.processEvents()
  127. position = position.parent
  128. else:
  129. chemin = []
  130. return chemin
  131. ### pour les tests
  132. ##class Plateau():
  133. ## def __init__(self):
  134. ## self.cases = {}
  135. ##
  136. ##class Case():
  137. ## def __init__(self, coord):
  138. ## self.coord = coord
  139. ## self.voisins = []
  140. ## self.majVoisins()
  141. ##
  142. ## def majVoisins(self):
  143. ## voisins = []
  144. ## lst = [(x, y-1), (x+1, y-1), (x+1, y), (x+1, y+1), (x, y+1), (x-1, y+1), (x-1, y), (x-1, y-1)]
  145. ## for coord in lst:
  146. ## if (coord[0] > 0 and coord[1] > 0 and coord[0] <= 5 and coord[1] <= 5):
  147. ## self.voisins.append(coord)
  148. ##
  149. ## def estFranchissable(self):
  150. ## return not (self.coord[0]==2 and self.coord[1] in [3, 4])
  151. ##
  152. ## def coutDep(self):
  153. ## cout = 1
  154. ## if self.coord in [(3,2), (3,3), (3, 4), (4,3), (4,4)]:
  155. ## cout = 2
  156. ## return cout
  157. ##
  158. ##
  159. ##plateau = Plateau()
  160. ##
  161. ##for x in range(1, 6):
  162. ## for y in range(1, 6):
  163. ## plateau.cases[(x, y)] = Case((x, y))
  164. ##depart = (1, 2)
  165. ##arrivee = (5, 5)
  166. ##
  167. ##for essai in range(1,2):
  168. ## t0 = time.time()
  169. ## c = chemin(plateau, depart, arrivee)
  170. ## print (time.time() - t0)
  171. ## print c