diff --git a/graphes/maze/main.py b/graphes/maze/main.py index a207245..896fc9d 100644 --- a/graphes/maze/main.py +++ b/graphes/maze/main.py @@ -1,7 +1,7 @@ import maze_creator as mc -import random -random.seed(random.randint(-2147483647, 2147483647)) -lab = mc.Labyrinth(100,100) +lab = mc.Labyrinth(10,10) lab.set_start_end((0,0),(100,100)) +lab.generate_maze() +print(lab.__str__()) diff --git a/graphes/maze/maze_creator.py b/graphes/maze/maze_creator.py index 8ba2c03..7b73cca 100644 --- a/graphes/maze/maze_creator.py +++ b/graphes/maze/maze_creator.py @@ -1,4 +1,5 @@ import fifo +import random as rnd import lifo class Labyrinth: @@ -12,15 +13,56 @@ class Labyrinth: self.start = None self.end = None + def voisins(self, x, y): + directions = [(0, 2), (0, -2), (2, 0), (-2, 0)] # Les déplacements par-dessus un mur + voisins = [] + + for dx, dy in directions: + nx, ny = x + dx, y + dy + if 0 <= nx < self.rows and 0 <= ny < self.cols and self.grid[nx][ny] == 1: + voisins.append((nx, ny)) + + return voisins + + def casser_mur(self, x1, y1, x2, y2): + mx, my = (x1 + x2) // 2, (y1 + y2) // 2 # Position du mur entre deux cellules + self.grid[mx][my] = 0 # Le mur devient un chemin + self.grid[x2][y2] = 0 # La cellule voisine devient aussi un chemin + + + + def est_mur(self, x, y): + return self.grid[y][x] == 1 + + def cell_type(self, x, y): + return self.grid[y][x] + + def __str__(self) -> str: return "\n".join("".join(" " if cell == 0 else "#" for cell in row) for row in self.grid) def set_start_end(self, start, end): self.start = start self.end = end + def generate_maze(self): - + x, y = rnd.randrange(0, self.rows, 2), rnd.randrange(0, self.cols, 2) + self.grid[x][y] = 0 + + murs = self.voisins(x, y) + + while murs: + nx, ny = rnd.choice(murs) + murs.remove((nx, ny)) + + for dx, dy in [(-2, 0), (2, 0), (0, -2), (0, 2)]: + cx, cy = nx + dx, ny + dy + if 0 <= cx < self.rows and 0 <= cy < self.cols and self.grid[cx][cy] == 0: + self.casser_mur(cx, cy, nx, ny) + murs.extend(self.voisins(nx, ny)) + break + def solve(self): pass diff --git a/pygame/lab_py/main.py b/pygame/lab_py/main.py new file mode 100644 index 0000000..d1e52a4 --- /dev/null +++ b/pygame/lab_py/main.py @@ -0,0 +1,154 @@ +import pygame +import random +import sys + +# Paramètres de la grille +CELL_SIZE = 20 # Taille d'une cellule en pixels +COLS = 30 # Nombre de colonnes +ROWS = 30 # Nombre de lignes +WIDTH = COLS * CELL_SIZE +HEIGHT = ROWS * CELL_SIZE + +# Couleurs +BLACK = (0, 0, 0) +WHITE = (255, 255, 255) +GRAY = (100, 100, 100) +GREEN = (0, 255, 0) + +class Cell: + def __init__(self, i, j): + self.i = i # Numéro de la colonne + self.j = j # Numéro de la ligne + # Chaque cellule possède 4 murs, tous présents initialement + self.walls = {'top': True, 'right': True, 'bottom': True, 'left': True} + self.visited = False + + def draw(self, surface): + """Dessine la cellule et ses murs sur la surface donnée.""" + x = self.i * CELL_SIZE + y = self.j * CELL_SIZE + + # Remplir la cellule (si visitée) AVANT de dessiner les murs + if self.visited: + pygame.draw.rect(surface, GRAY, (x, y, CELL_SIZE, CELL_SIZE)) + + # Dessiner les murs par-dessus la couleur de fond + if self.walls['top']: + pygame.draw.line(surface, WHITE, (x, y), (x + CELL_SIZE, y)) + if self.walls['right']: + pygame.draw.line(surface, WHITE, (x + CELL_SIZE, y), (x + CELL_SIZE, y + CELL_SIZE)) + if self.walls['bottom']: + pygame.draw.line(surface, WHITE, (x + CELL_SIZE, y + CELL_SIZE), (x, y + CELL_SIZE)) + if self.walls['left']: + pygame.draw.line(surface, WHITE, (x, y + CELL_SIZE), (x, y)) + +def get_cell(i, j): + """Retourne la cellule aux coordonnées (i, j) si elle existe.""" + if 0 <= i < COLS and 0 <= j < ROWS: + return grid[i][j] + return None + +def get_unvisited_neighbors(cell): + """Retourne la liste des voisins non visités de la cellule donnée.""" + neighbors = [] + i, j = cell.i, cell.j + # Voisin du haut + top = get_cell(i, j - 1) + if top and not top.visited: + neighbors.append(top) + # Voisin de droite + right = get_cell(i + 1, j) + if right and not right.visited: + neighbors.append(right) + # Voisin du bas + bottom = get_cell(i, j + 1) + if bottom and not bottom.visited: + neighbors.append(bottom) + # Voisin de gauche + left = get_cell(i - 1, j) + if left and not left.visited: + neighbors.append(left) + + return neighbors + +def remove_walls(current, next_cell): + """ + Enlève les murs entre la cellule courante et le voisin sélectionné. + """ + dx = next_cell.i - current.i + dy = next_cell.j - current.j + if dx == 1: # Voisin à droite + current.walls['right'] = False + next_cell.walls['left'] = False + elif dx == -1: # Voisin à gauche + current.walls['left'] = False + next_cell.walls['right'] = False + elif dy == 1: # Voisin en bas + current.walls['bottom'] = False + next_cell.walls['top'] = False + elif dy == -1: # Voisin en haut + current.walls['top'] = False + next_cell.walls['bottom'] = False + +def main(): + global grid + pygame.init() + screen = pygame.display.set_mode((WIDTH, HEIGHT)) + pygame.display.set_caption("Labyrinthe généré par DFS") + clock = pygame.time.Clock() + + # Création de la grille : une matrice de cellules + grid = [[Cell(i, j) for j in range(ROWS)] for i in range(COLS)] + + # Initialisation de l'algorithme DFS + current = grid[0][0] # Départ en haut à gauche + current.visited = True + stack = [] + + running = True + finished = False # Indique si la génération est terminée + + while running: + clock.tick(60) # Limite à 60 images par seconde + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + # Exécution de l'algorithme DFS tant que la génération n'est pas terminée + if not finished: + neighbors = get_unvisited_neighbors(current) + if neighbors: + # Choix aléatoire d'un voisin non visité + next_cell = random.choice(neighbors) + stack.append(current) + remove_walls(current, next_cell) + current = next_cell + current.visited = True + elif stack: + # Revenir en arrière si aucun voisin n'est disponible + current = stack.pop() + else: + # Génération terminée + finished = True + + # Affichage + screen.fill(BLACK) + # Dessiner toutes les cellules de la grille + for i in range(COLS): + for j in range(ROWS): + grid[i][j].draw(screen) + + # Mettre en évidence la cellule courante (seulement si la génération est en cours) + if not finished: + x = current.i * CELL_SIZE + y = current.j * CELL_SIZE + pygame.draw.rect(screen, GREEN, (x, y, CELL_SIZE, CELL_SIZE)) + + pygame.display.flip() + + pygame.quit() + sys.exit() + +if __name__ == '__main__': + main() +