Étape 2 : Création du labyrinthe
Le principe
Il faut imaginer cette grille comme un graphe, où chaque sommet est une case reliée à ses voisines par un mur.
Toutes les cases ont 4 voisines sauf celles du bord qui n'en n'ont que 2 ou 3.
On fait un parcours en profondeur de ce graphe en utilisant la boucle draw()
Dans le setup()
current
<-- la case 0p
(une pile) <---current
Dans le draw()
( qui est une boucle )
On note
current
comme visitéeOn la met en bleu
voisines
<--- la liste de ses voisines non déjà visitéesSi
voisines
n'est pas une liste vide :next
<--- l'une d'entre ellesp
<---next
On élimine le mur entre
current
etnext
current
<---next
Sinon :
Si la pile n'est pas vide :
On dépile
p
danscurrent
Sinon : on a terminé
Méthode : Mise en œuvre
Il nous faudra une classe Pile : ( à récupérer et à écrire dans un nouvel onglet de maze_generator
).
Il faudra rajouter un attribut de classe à la classe Cell
pour noter le fait qu'une case est visitée ou pas.
# coding=utf-8 (nécessaire dans Processing)
class Cell:
def __init__(self,j,i,w=30):
self.i=i
self.j=j
self.w=w
self.walls=[True,True,True,True]
self.visited=False
Il faudra modifier la méthode show
Si la case a été visitée, on change sa couleur.
def show(self):
'''
'''
x=self.i*self.w
y=self.j*self.w
w=self.w
stroke(255)
if self.walls[0]:
line(x,y,x+w,y)
if self.walls[1]:
line(x+w,y,x+w,y+w)
if self.walls[2]:
line(x+w,y+w,x,y+w)
if self.walls[3]:
line(x,y+w,x,y)
if self.visited:
noStroke()
fill(255,0,255,100)
rect(x,y,w,w)
Voilà le setup()
grid=[]
p=Pile()
w=40 # dimension(on peut modifier)
def setup():
'''
'''
size(610,410)
global cols,rows,current # déclarées comme globales
#global current
cols=width//w
rows=height//w
#creation du tableau
for j in range(rows):
for i in range(cols):
cell=Cell(j,i,w)
grid.append(cell)
current=grid[0]
p.empiler(current)
frameRate(30)#vitesse (max 60)
Voici la méthode de la classe Cell qui permet de calculer l'indice d'une case à partir de ses coordonnées.
def index(self,i,j):
w=self.w
cols=int(width/w)
rows=int(height/w)
if (i < 0 or j < 0 or i > cols-1 or j > rows-1):
return -1
else:
return j*cols + i
Voici la fonction qui efface le mur entre deux cases.
def removeWalls(a,b):
'''
efface le mur entre a et b
'''
x=a.i-b.i
if x==1:
a.walls[3]=False
b.walls[1]=False
elif x==-1:
a.walls[1]=False
b.walls[3]=False
y=a.j-b.j
if y==1:
a.walls[0]=False
b.walls[2]=False
elif y==-1:
a.walls[2]=False
b.walls[0]=False
À faire : Expliquer le principe de cette fonction.
Voici la méthode de la classe Cell
qui permet de récupérer la liste des indices des voisines d'une case
Cette méthode utilise la fonction index ( donc attention si par hasard vous avez placé les classes dans des fichiers séparés...)
def checkVoisin(self):
'''
renvoie la liste des numéros des cases voisines
'''
voisins=[]
top_case = self.index(self.i,self.j-1)
right_case = self.index(self.i+1, self.j)
bottom_case = self.index(self.i, self.j+1)
left_case =self.index(self.i-1, self.j)
if top_case!=-1:
voisins.append(top_case)
if right_case!=-1:
voisins.append(right_case)
if bottom_case!=-1:
voisins.append(bottom_case)
if left_case!=-1:
voisins.append(left_case)
return voisins
Voici la fonction qui transforme la liste des indices des voisines en liste de voisines non visitées
def voisinage(liste):
'''
renvoie la liste des voisines non visitées
'''
neighbors=[]
for vois in liste:
if grid[vois].visited==False:
neighbors.append(grid[vois])
return neighbors
Simulation : Le draw() pour terminer
Il vous reste à écrire ce qu'il faut dans le draw...
Pour terminer le programme (une fois le labyrinthe créé) il suffit d'écrire l'instruction noLoop()
def draw():
'''
fonction qui boucle (par defaut 60 fois/seconde)
'''
global current,next
background(51)
for i in range(len(grid)):
grid[i].show()
current.highlight()
# à compléter