Algorithme main droite
This commit is contained in:
parent
41f515d675
commit
efc4cdedfa
209
Chapitre 4 - Graphes/C08_labyrinthe.py
Normal file
209
Chapitre 4 - Graphes/C08_labyrinthe.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
#
|
||||
# Chapitre 8 - Exercice Initié 14 - Sortie de labyrinthe
|
||||
#
|
||||
|
||||
from random import randint
|
||||
from math import sqrt, ceil, floor
|
||||
|
||||
# Changements de directions possibles depuis les
|
||||
# coordonnées d'une salle du labyrinthe :
|
||||
# Haut, droite, bas, gauche
|
||||
direction_diff = [(0, 1), (1, 0), (0, -1), (-1, 0)]
|
||||
|
||||
class Salle:
|
||||
def __init__(self, mur=True, entree=False, sortie=False):
|
||||
self.mur = mur
|
||||
self.entree = entree
|
||||
self.sortie = sortie
|
||||
self.visites = 0
|
||||
|
||||
def __repr__(self):
|
||||
""" Fonction appelée par défaut par `print()`
|
||||
pour représenter un objet sous forme
|
||||
textuelle. """
|
||||
|
||||
resultat = ""
|
||||
if self.mur:
|
||||
resultat += "Mur"
|
||||
elif self.entree:
|
||||
resultat += "Entrée"
|
||||
elif self.sortie:
|
||||
resultat += "Sortie"
|
||||
else:
|
||||
resultat += "Salle"
|
||||
|
||||
if self.visites > 0:
|
||||
resultat += f" [{self.visites}]"
|
||||
return resultat
|
||||
|
||||
class Labyrinthe:
|
||||
|
||||
def __init__(self, salles, entree, sortie):
|
||||
self.salles = salles
|
||||
self.coord_entree = entree # coordonnées
|
||||
self.coord_sortie = sortie # coordonnées
|
||||
self.direction = 0
|
||||
|
||||
def __repr__(self):
|
||||
""" Fonction appelée par défaut par `print()`
|
||||
pour représenter un objet sous forme
|
||||
textuelle. """
|
||||
|
||||
return f"Labyrinthe de {len(self.salles)} x {len(self.salles[0])} : {self.coord_entree} vers {self.coord_sortie}"
|
||||
|
||||
def salle(self, coords):
|
||||
""" Renvoie la Salle correspondant aux `coords`
|
||||
passées en argument, si elle existe. """
|
||||
|
||||
if 0 <= coords[0] < len(self.salles):
|
||||
if 0 <= coords[1] < len(self.salles[coords[0]]):
|
||||
return self.salles[coords[0]][coords[1]]
|
||||
|
||||
return None
|
||||
|
||||
def montrer(self):
|
||||
""" Renvoie une représentation textuelle du
|
||||
labyinthe représentant ses murs, son entrée,
|
||||
sa sortie, et les salles déjà visitées. """
|
||||
|
||||
resultat = " " + "-"*2*len(self.salles[0]) + "\n|"
|
||||
for l in range(len(self.salles)):
|
||||
for h in range(len(self.salles[l])):
|
||||
if self.salles[l][h].mur:
|
||||
resultat += "█▊"
|
||||
elif self.salles[l][h].entree:
|
||||
resultat += 'E '
|
||||
elif self.salles[l][h].sortie:
|
||||
resultat += 'S '
|
||||
elif self.salles[l][h].visites > 0:
|
||||
resultat += '. '
|
||||
else:
|
||||
resultat += ' '
|
||||
if h < len(self.salles[0])-1:
|
||||
resultat += "-"*2*(len(self.salles[0])-len(self.salles[-1]))
|
||||
resultat += "|\n|"
|
||||
resultat = resultat[:-1] + "-"*2*len(self.salles[-1])
|
||||
return resultat
|
||||
|
||||
def reinitialiser(self):
|
||||
""" Remet à zéro le nombre de visites
|
||||
des salles du labyrinthe. """
|
||||
|
||||
for i in range(len(self.salles)):
|
||||
for j in range(len(self.salles[i])):
|
||||
self.salles[i][j].visites = 0
|
||||
|
||||
def voisins(self, coords):
|
||||
""" Retourne la liste des coordonnées des salles
|
||||
voisines à la salle aux coordonnées `coords`. """
|
||||
|
||||
global direction_diff
|
||||
voisins = [ [ coords[i]+direction_diff[j][i]
|
||||
for i in range(len(coords)) ]
|
||||
for j in range(len(direction_diff)) ]
|
||||
|
||||
return [ tuple(v) for v in voisins if self.salle(v) is not None ]
|
||||
|
||||
def nb_aretes(self, coords):
|
||||
""" Nombre « d'arêtes » de la salle aux coordonnées
|
||||
fournies, c'est à dire le nombre de ses voisins
|
||||
qui ne sont pas des murs. """
|
||||
nb_aretes = 0
|
||||
for v in self.voisins(coords):
|
||||
s = self.salle(v)
|
||||
if (s is not None) and (not s.mur) and (not s.entree) and not s.sortie:
|
||||
nb_aretes += 1
|
||||
return nb_aretes
|
||||
|
||||
def coords_direction(self, coords, nombre):
|
||||
""" Met à jour self.direction de `nombre`
|
||||
quarts de tour dans le sense antihoraire,
|
||||
et renvoie les coordonnées contigues à
|
||||
`coords` dans cette direction. """
|
||||
|
||||
global direction_diff
|
||||
self.direction = (self.direction + nombre) % 4
|
||||
diff = direction_diff[self.direction]
|
||||
return (coords[0] + diff[0], coords[1] + diff[1])
|
||||
|
||||
|
||||
def creer_labyrinthe(nb_salles):
|
||||
""" Fonction utilisée pour générer des labyrinthes
|
||||
simples lors du chargement de `labyrinthe.py`. """
|
||||
|
||||
largeur = int( floor( sqrt( nb_salles ) ) )
|
||||
hauteur = int( ceil( nb_salles / largeur ) )
|
||||
salles = [ [ Salle() for i in range(hauteur) ] for j in range(largeur) ]
|
||||
|
||||
coord_entree = (randint(1, largeur//2-1), 0)
|
||||
coord_sortie = (randint(largeur//2, largeur-1), hauteur-1)
|
||||
salles[coord_entree[0]][coord_entree[1]].entree = True
|
||||
salles[coord_sortie[0]][coord_sortie[1]].sortie = True
|
||||
salles[coord_entree[0]][coord_entree[1]].mur = False
|
||||
salles[coord_sortie[0]][coord_sortie[1]].mur = False
|
||||
|
||||
x = coord_entree[0]
|
||||
cds = False
|
||||
for h in range(1, hauteur):
|
||||
salles[x][h].mur = False
|
||||
if ((h%2==0) or abs(coord_sortie[0]-x)==hauteur-h) and x != coord_sortie[0]:
|
||||
diff = coord_sortie[0] - x
|
||||
x += diff // abs(diff)
|
||||
salles[x][h].mur = False
|
||||
|
||||
if cds:
|
||||
cds = False
|
||||
elif randint(0, 10) > 2:
|
||||
cds = True
|
||||
direction = randint(0, 1) * 2 - 1
|
||||
for i in range(x+direction, max(1, min(largeur-1, x + 4 * direction)), direction):
|
||||
salles[i][h].mur = False
|
||||
|
||||
|
||||
return Labyrinthe(salles, coord_entree, coord_sortie)
|
||||
|
||||
labyrinthe_simple = creer_labyrinthe(200)
|
||||
|
||||
salles2 = [ [Salle() for i in range(10)] for j in range(10) ]
|
||||
salles2[0][5].entree = True
|
||||
salles2[5][5].sortie = True
|
||||
salles2[0][5].mur = False
|
||||
salles2[5][5].mur = False
|
||||
for i in range(1, 9):
|
||||
salles2[i][1].mur = False
|
||||
salles2[i][8].mur = False
|
||||
salles2[1][i].mur = False
|
||||
salles2[8][i].mur = False
|
||||
salles2[6][5].mur = False
|
||||
salles2[7][5].mur = False
|
||||
labyrinthe_complexe_1 = Labyrinthe(salles2, (0, 5), (5, 5))
|
||||
|
||||
salles3 = [ [Salle() for i in range(10)] for j in range(10) ]
|
||||
salles3[0][5].entree = True
|
||||
salles3[5][5].sortie = True
|
||||
salles3[0][5].mur = False
|
||||
salles3[5][5].mur = False
|
||||
for i in range(1, 9):
|
||||
salles3[i][1].mur = False
|
||||
salles3[i][8].mur = False
|
||||
salles3[1][i].mur = False
|
||||
salles3[8][i].mur = False
|
||||
labyrinthe_complexe_2 = Labyrinthe(salles3, (0, 5), (5, 5))
|
||||
|
||||
def sortie_main_droite(l: Labyrinthe):
|
||||
nodes = []
|
||||
current = l.coord_entree
|
||||
while current != l.coord_sortie:
|
||||
new_current = l.coords_direction(current, 1)
|
||||
if new_current in [coord for coord in l.voisins(current) if not l.salle(coord).mur]:
|
||||
nodes.append(current)
|
||||
current = new_current
|
||||
if current == l.coord_sortie:
|
||||
nodes.append(current)
|
||||
break
|
||||
else:
|
||||
l.coords_direction(current, -2)
|
||||
return nodes
|
||||
|
||||
print(labyrinthe_simple.montrer())
|
||||
print(sortie_main_droite(labyrinthe_simple))
|
Loading…
Reference in a new issue