2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

再帰的バックトラッキングによる迷路生成(Python版)

Last updated at Posted at 2025-05-30

@hextomino さんの「再帰的バックトラッキングによる迷路生成」のコードのクラス構成を見直し、Pythonで書いてみました。

import time
import random
import tkinter as tk


class Wall:

    def __init__(self):
        self.top = self.bottom = self.left = self.right = True


class Cell:
    SIZE = 40

    def __init__(self, x: int, y: int) -> None:
        self.x = x
        self.y = y
        self.wall = Wall()
        self.visited = False

    def knock_through(self, neighbor: "Cell") -> None:
        """neighbor(上下左右のいずれか)との間の壁をなくす"""
        match (self.x - neighbor.x, self.y - neighbor.y):
            case (0, 1):
                self.wall.top = neighbor.wall.bottom = False
            case (0, -1):
                self.wall.bottom = neighbor.wall.top = False
            case (1, 0):
                self.wall.left = neighbor.wall.right = False
            case (-1, 0):
                self.wall.right = neighbor.wall.left = False

    def draw(self, canvas: tk.Canvas, color: str="pink") -> None:
        """canvasに背景色colorで描画する"""
        x1, y1 = self.x * self.SIZE, self.y * self.SIZE
        x2, y2 = x1 + self.SIZE, y1 + self.SIZE
        if self.visited:
            canvas.create_rectangle(x1, y1, x2, y2, fill=color, outline=color)
        if self.wall.top:
            canvas.create_line(x1, y1, x2, y1)
        if self.wall.bottom:
            canvas.create_line(x1, y2, x2, y2)
        if self.wall.left:
            canvas.create_line(x1, y1, x1, y2)
        if self.wall.right:
            canvas.create_line(x2, y1, x2, y2)


class Maze:
    ROWS = 20
    COLS = 20
    YS = range(ROWS)
    XS = range(COLS)

    def __init__(self, canvas: tk.Canvas) -> None:
        self.canvas = canvas
        self.cells = [[Cell(x, y) for x in self.XS] for y in self.YS]
        self.tracking = [self.cells[self.ROWS//2][self.COLS//2]]

    def make(self, animation: bool=True, interval: int=50):
        """再帰的バックトラッキングによる迷路生成"""
        while self.tracking:
            cell = self.tracking[-1]
            cell.visited = True
            x, y = cell.x, cell.y
            neighbors = [self.cells[ny][nx]
                         for nx, ny in ((x-1, y), (x+1, y), (x, y-1), (x, y+1))
                         if nx in self.XS and ny in self.YS
                         if not self.cells[ny][nx].visited]
            if neighbors:
                neighbor = random.choice(neighbors)
                cell.knock_through(neighbor)
                self.tracking.append(neighbor)
                if animation:
                    self.canvas.after(interval, self.make)
                    break
            else:
                del self.tracking[-1]
        if animation:
            self.draw()

    def draw(self) -> None:
        """描画する"""
        self.canvas.delete("all")
        for rows in self.cells:
            for cell in rows:
                cell.draw(self.canvas, "cyan" if cell in self.tracking else "pink")


def main() -> None:
    root = tk.Tk()
    root.title("Maze")
    canvas = tk.Canvas(root,
                       width=Maze.COLS*Cell.SIZE,
                       height=Maze.ROWS*Cell.SIZE,
                       bg="white")
    canvas.pack()
    maze = Maze(canvas)
    maze.make()
    maze.draw()
    root.mainloop()


main()

image.png

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?