| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #from __future__ import unicode_literals
- # -*- coding: utf-8 -*-
- """algorithme de recherche du plus court chemin entre deux cases"""
- from math import *
- import time
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- #pour des performances correctes, ne pas utiliser pour de deplacements de plus de 100 cases
-
- def distance(coord1, coord2):
- return sqrt((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)
- def distanceCarree(coord1, coord2):
- """bcp plus rapide a calculer que la distance reelle"""
- return (coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2
-
- class N():
- """noeud du chemin"""
- def __init__(self, coord):
- self.parent = None #coord du noeud qui a amene a ce noeud-ci
- self.coord = coord
- self.kDep = 1
- self.coutG = 0
- self.coutH = 0
- self.cout = 0
- def creer(self, parent, cible, kDep):
- self.parent = parent
- self.kDep = kDep
- self.coutH = distanceCarree(self.coord, cible)
- self.coutG = self.parent.coutG + self.kDep
- self.cout = self.coutG + self.coutH
- class Chemin():
- def __init__(self, plateau, origine, cible, z1 = 0, z2 = 0):
- self.plateau = plateau
- self.origine = origine
- self.cible = cible
- self.echec = False
- self.stop = False
- self._z1 = z1
- self._z2 = z2
- ###active l'evolution sur le plateau
- self.debug = False
- def arreter(self):
- self.stop = True
- def liste(self):
- """retourne la liste des coord a traverser pour atteindre l'objectif
- se base sur la fonction estFranchissable() des cases"""
- if self.debug:
- for coord in self.plateau.cases:
- self.plateau.cases[coord].majEstCibleCurseur(False)
- self.plateau.cases[coord].majEstCibleAttaque(False)
- QApplication.processEvents()
- t0 = time.time()
- nO = N(self.origine)
- nO.parent = None
- nO.coutG = 0
- nO.cout = 0
- filOuvert = [] #"liste ouverte": noeuds etudies et a etudier
- filFerme = [nO] #"liste fermee": noeuds retenus
- chemin = []
- position = nO
- echec = False
-
- #on continue jusqu'a tomber sur la case cible, ou jusqu'a un echec
- it = 0
- while position.coord != self.cible and not self.echec:
- it += 1
- ## print "iteration: ", i
-
- #on etudie tous les voisins de la case en cours
- for coord in self.plateau.cases[position.coord].voisins:
- if self.stop: return []
- #on elimine les cases deja retenues (celles qui sont dans le fil ferme)
- trouve = False
- for nTest in filFerme:
- if self.stop: return []
- if nTest.coord == coord:
- trouve = True
- if not trouve:
-
- #on elimine les cases infranchissables
- if self.plateau.cases[coord].estFranchissable():
- noeud = N(coord)
-
- #on calcule le cout de la case
- if self.stop: return []
- noeud.creer(position, self.cible, self.plateau.cases[coord].coutDep())
- #si le noeud est trouve dans la liste ouverte, on le compare a celui-ci
- # si ce nouveau noeud a un cout moindre, on remplace
- # sinon on ajoute ce noeud a la liste ouverte
- trouve = False
- for nTest in filOuvert:
- if self.stop: return []
- if nTest.coord == noeud.coord:
- if noeud.cout < nTest.cout:
- nTest.parent = noeud.parent
- nTest.cout = noeud.cout
- trouve = True
-
- if not trouve:
- filOuvert.append(noeud)
- if self.debug:
- self.plateau.cases[noeud.coord].majEstCibleCurseur(True, True)
- time.sleep(0.05)
- QApplication.processEvents()
- #on parcourt les noeuds de la liste ouverte
- #et on cherche le meilleur noeud (le cout le plus faible)
- #si trouve: on l'ajoute a la liste fermee, on le retire de la liste ouverte et on continue
- #sinon, le chemin n'existe pas
- meilleur = None
-
- for noeud in filOuvert:
- if self.stop: return []
- if meilleur == None:
- meilleur = noeud
- else:
- if noeud.cout < meilleur.cout:
- meilleur = noeud
-
- if meilleur:
- filFerme.append(meilleur)
- if self.debug:
- self.plateau.cases[meilleur.coord].majEstCibleCurseur(True, False)
- QApplication.processEvents()
- time.sleep(0.05)
- filOuvert.remove(meilleur)
- position = meilleur
- else:
- echec = True
- #on revient de parent en parent jusqu'a l'arrivee
- if not self.echec:
- while position.coord != self.origine:
- if self.stop: return []
- chemin.insert(0, (position.coord, position.coutG))
- if self.debug:
- self.plateau.cases[position.coord].majEstCibleCurseur(False)
- self.plateau.cases[position.coord].majEstCibleAttaque(True)
- QApplication.processEvents()
-
- position = position.parent
- else:
- chemin = []
-
- return chemin
-
- ### pour les tests
- ##class Plateau():
- ## def __init__(self):
- ## self.cases = {}
- ##
- ##class Case():
- ## def __init__(self, coord):
- ## self.coord = coord
- ## self.voisins = []
- ## self.majVoisins()
- ##
- ## def majVoisins(self):
- ## voisins = []
- ## 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)]
- ## for coord in lst:
- ## if (coord[0] > 0 and coord[1] > 0 and coord[0] <= 5 and coord[1] <= 5):
- ## self.voisins.append(coord)
- ##
- ## def estFranchissable(self):
- ## return not (self.coord[0]==2 and self.coord[1] in [3, 4])
- ##
- ## def coutDep(self):
- ## cout = 1
- ## if self.coord in [(3,2), (3,3), (3, 4), (4,3), (4,4)]:
- ## cout = 2
- ## return cout
- ##
- ##
- ##plateau = Plateau()
- ##
- ##for x in range(1, 6):
- ## for y in range(1, 6):
- ## plateau.cases[(x, y)] = Case((x, y))
- ##depart = (1, 2)
- ##arrivee = (5, 5)
- ##
- ##for essai in range(1,2):
- ## t0 = time.time()
- ## c = chemin(plateau, depart, arrivee)
- ## print (time.time() - t0)
- ## print c
-
|