1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| # IMPORTATION ================================================================================
import copy
# CONSTANTE ==================================================================================
AFFICHAGE = {0:' ▅ ', 1:' . ', 2:' x ', 9:' ⎆ ', 'actuel':' ☺ '}
# DECLARATION DE FONCTION ====================================================================
def affiche(m, d, itineraire):
"""Affichage de la position actuelle dans le labyrinthe"""
print(itineraire)
print(f"-- deplacement en ligne {d[0]},colonne {d[1]}--")
for ligne in range(len(m)): # Attention, ligne est un indice
for colonne in range(len(m[0])): # Attention, colonne est un indice
case = m[ligne][colonne]
if (ligne, colonne) == d:
print(AFFICHAGE['actuel'], end='')
else:
print(AFFICHAGE[case], end='')
print('')
input("ENTREE pour la suite...")
print("\n\n")
def trajet_sortie(mat:'list[list]', depart:tuple) -> 'list[tuple]':
"""Renvoie la liste des (ligne, colonne) à suivre pour sortir du labyrinthe"""
m = copy.deepcopy(mat) # m est une copie profonde de la matrice reçue
itineraire = [] # on crée une Pile itineraire
itineraire.append(depart) # on emplie les coordonnées d
if cherche(m, itineraire): # si cherche() à trouver
return itineraire # renvoie l'itinéraire
else: # sinon
return [()] # renvoie un itinéaire vide compatible avec le prototype
def inconnue_a_gauche(ligne:int, colonne:int, m:'list[list]') -> bool:
"""Prédicat qui renvoie True si la case de gauche n'a pas encore été explorée"""
return (colonne-1) >= 0 and m[ligne][colonne-1] in [1, 9]
def inconnue_a_droite(ligne:int, colonne:int, m:'list[list]') -> bool:
"""Prédicat qui renvoie True si la case de droite n'a pas encore été explorée"""
return (colonne+1) < len(m[0]) and m[ligne][colonne+1] in [1, 9]
def inconnue_au_dessus(ligne:int, colonne:int, m:'list[list]') -> bool:
"""Prédicat qui renvoie True si la case au dessus n'a pas encore été explorée"""
return (ligne-1) >= 0 and m[ligne-1][colonne] in [1, 9]
def inconnue_en_dessous(ligne:int, colonne:int, m:'list[list]') -> bool:
"""Prédicat qui renvoie True si la case en dessous n'a pas encore été explorée"""
return (ligne+1) < len(m) and m[ligne+1][colonne] in [1, 9]
def cherche(m:'list[list]', itineraire:'Pile[tuple]|PileVIDE') -> bool:
"""Fonction récursive qui modifie itineraire et prédit s'il existe une sortie, ou pas"""
# Premier cas de base : la Pile itinéraire est vide : c'est fini...
if len(itineraire) == 0: # Si la Pile est vide
return False # On signale qu'il n'y a pas de sortie
ligne, colonne = itineraire[-1] # on lit les indices ligne et colonne du sommet
affiche(m, (ligne,colonne), itineraire ) # on affiche le labyrinthe et on lance l'attente
# Deuxième case de base : nous sommes sur la sortie : c'est fini.
if m[ligne][colonne] == 9: # Si c'est la case de sortie
return True # on signale que la sortie existe
# Cas récursif
else:
m[ligne][colonne] = 2 # on marque à 2 la case actuelle
if inconnue_a_gauche(ligne, colonne, m): # Si case gauche explorable et inconnue
itineraire.append( (ligne, colonne-1) ) # on empile cette destination
return cherche(m, itineraire) # on y cherche la sortie
elif inconnue_a_droite(ligne, colonne, m): # Si case droite explorable et inconnue
itineraire.append( (ligne, colonne+1) ) # on empile cette destination
return cherche(m, itineraire) # on y cherche la sortie
elif inconnue_au_dessus(ligne, colonne, m): # Si case au dessus explorable et inconnue
itineraire.append( (ligne-1, colonne) ) # on empile cette destination
return cherche(m, itineraire) # on y cherche la sortie
elif inconnue_en_dessous(ligne, colonne, m): # Si case en dessous explorable et inconnue
itineraire.append( (ligne+1, colonne) ) # on empile cette destination
return cherche(m, itineraire) # on y cherche la sortie
else: # plus de cases explorables depuis ici
itineraire.pop() # on dépile cette case pour repartir en arrière
return cherche(m, itineraire) # on cherche depuis la nouvelle case
# PROGRAMME PRINCIPAL ===============================================================================
if __name__ == "__main__":
# 0 pour mur, 1 pour couloir, 2 pour déjà visitée, 9 pour sortie
matrice = [
[0, 1, 0, 1, 1],
[0, 1, 1, 1, 1],
[0, 1, 0, 1, 0],
[0, 9, 0, 1, 0]
]
ligne_depart = 0
colonne_depart = 1
depart = (ligne_depart, colonne_depart) # création du couple (ligne, colonne) du départ
trajet = trajet_sortie(matrice, depart) # recherche du trajet possible, ou pas...
print(trajet)
|