finish the generator DFS

This commit is contained in:
Maoake Teriierooiterai
2026-03-24 14:28:10 +01:00
parent 8b4ef7afce
commit 4d151664ab
5 changed files with 44 additions and 46 deletions
+9 -5
View File
@@ -1,21 +1,25 @@
import os import os
from src.amaz_lib import MazeGenerator from src.amaz_lib import Kruskal
from src.amaz_lib import DepthFirstSearch from src.amaz_lib import DepthFirstSearch
from src.amaz_lib import Maze from src.amaz_lib import Maze
def main() -> None: def main() -> None:
# try: # try:
maze = Maze(maze=None, start=(1, 1), end=(16, 15)) maze = Maze(maze=None)
for alg in MazeGenerator.Kruskal.kruskal(20, 20): gen = Kruskal().generator(10, 10)
for alg in gen:
maze.set_maze(alg) maze.set_maze(alg)
os.system("clear") os.system("clear")
maze.ascii_print() maze.ascii_print()
maze.export_maze("test.txt")
def main2() -> None: def main2() -> None:
DepthFirstSearch.generator(5, 5) maze = Maze(maze=None)
gen = DepthFirstSearch.generator(50, 50)
maze.set_maze(gen)
os.system("clear")
maze.ascii_print()
# except Exception as err: # except Exception as err:
+21 -22
View File
@@ -3,7 +3,6 @@ from typing import Generator
import numpy as np import numpy as np
from .Cell import Cell from .Cell import Cell
import math import math
import random
class MazeGenerator(ABC): class MazeGenerator(ABC):
@@ -90,24 +89,30 @@ class DepthFirstSearch:
@staticmethod @staticmethod
def generator(width: int, height: int) -> np.ndarray: def generator(width: int, height: int) -> np.ndarray:
maze = DepthFirstSearch.init_maze(width, height) maze = DepthFirstSearch.init_maze(width, height)
visited = set() visited = np.zeros((height, width), dtype=bool)
path = list() path = list()
w_h = (width, height) w_h = (width, height)
coord = (0, 0) coord = (0, 0)
x, y = coord x, y = coord
first = True
while len(visited) < width * height: while path or first:
visited = DepthFirstSearch.add_cell_visited(coord, visited) first = False
visited[y, x] = True
path = DepthFirstSearch.add_cell_visited(coord, path) path = DepthFirstSearch.add_cell_visited(coord, path)
random_c = DepthFirstSearch.random_cells(visited, coord, w_h) random_c = DepthFirstSearch.random_cells(visited, coord, w_h)
if len(random_c) == 0: if len(random_c) == 0:
path = DepthFirstSearch.back_on_step(path, w_h, visited) path = DepthFirstSearch.back_on_step(path, w_h, visited)
if path: if path:
coord = path[-1] coord = path[-1]
random_c = DepthFirstSearch.random_cells(path, coord, w_h) random_c = DepthFirstSearch.random_cells(visited, coord, w_h)
x, y = coord x, y = coord
if not path:
break
wall = DepthFirstSearch.next_step(random_c) wall = DepthFirstSearch.next_step(random_c)
maze[y][x] = DepthFirstSearch.broken_wall(maze[y][x], wall) maze[y][x] = DepthFirstSearch.broken_wall(maze[y][x], wall)
coord = DepthFirstSearch.next_cell(x, y, wall) coord = DepthFirstSearch.next_cell(x, y, wall)
wall_r = DepthFirstSearch.reverse_path(wall) wall_r = DepthFirstSearch.reverse_path(wall)
x, y = coord x, y = coord
@@ -121,38 +126,32 @@ class DepthFirstSearch:
return maze return maze
@staticmethod @staticmethod
def add_cell_visited(coord: tuple, visited: list | set) -> list | set: def add_cell_visited(coord: tuple, path: set) -> list:
if isinstance(visited, list): path.append(coord)
visited.append(coord) return path
if isinstance(visited, set):
visited.add(coord)
return visited
@staticmethod @staticmethod
def random_cells(visited: set, coord: tuple, w_h: tuple) -> list: def random_cells(visited: np.array, coord: tuple, w_h: tuple) -> list:
rand_cell = [] rand_cell = []
x, y = coord x, y = coord
width, height = w_h width, height = w_h
# NORTH
if y - 1 >= 0 and (x, y - 1) not in visited: if y - 1 >= 0 and not visited[y - 1][x]:
rand_cell.append("N") rand_cell.append("N")
# SOUTH if y + 1 < height and not visited[y + 1][x]:
if y + 1 < height and (x, y + 1) not in visited:
rand_cell.append("S") rand_cell.append("S")
# WEST if x - 1 >= 0 and not visited[y][x - 1]:
if x - 1 >= 0 and (x - 1, y) not in visited:
rand_cell.append("W") rand_cell.append("W")
# EAST if x + 1 < width and not visited[y][x + 1]:
if x + 1 < width and (x + 1, y) not in visited:
rand_cell.append("E") rand_cell.append("E")
return rand_cell return rand_cell
@staticmethod @staticmethod
def next_step(rand_cell: list) -> str: def next_step(rand_cell: list) -> str:
return random.choice(rand_cell) return np.random.choice(rand_cell)
@staticmethod @staticmethod
def broken_wall(cell: Cell, wall: str) -> Cell: def broken_wall(cell: Cell, wall: str) -> Cell:
@@ -188,7 +187,7 @@ class DepthFirstSearch:
return reverse[next] return reverse[next]
@staticmethod @staticmethod
def back_on_step(path: list, w_h: tuple, visited: set) -> list: def back_on_step(path: list, w_h: tuple, visited: np.array) -> list:
last = path[-1] last = path[-1]
r_cells = DepthFirstSearch.random_cells(visited, last, w_h) r_cells = DepthFirstSearch.random_cells(visited, last, w_h)
while len(path) > 0: while len(path) > 0:
+3 -1
View File
@@ -1,8 +1,10 @@
from .Cell import Cell from .Cell import Cell
from .Maze import Maze from .Maze import Maze
from .MazeGenerator import MazeGenerator, DepthFirstSearch from .MazeGenerator import MazeGenerator, DepthFirstSearch
from .MazeGenerator import Kruskal
from .MazeSolver import MazeSolver from .MazeSolver import MazeSolver
__version__ = "1.0.0" __version__ = "1.0.0"
__author__ = "us" __author__ = "us"
__all__ = ["Cell", "Maze", "MazeGenerator", "MazeSolver", "DepthFirstSearch"] __all__ = ["Cell", "Maze", "MazeGenerator",
"MazeSolver", "DepthFirstSearch", "Kruskal"]
+3 -11
View File
@@ -13,23 +13,15 @@ class TestDepth:
def test_rand_cells(self) -> None: def test_rand_cells(self) -> None:
w_h = (10, 10) w_h = (10, 10)
lst = DepthFirstSearch.add_cell_visited((0, 0), set()) lst = np.zeros((10, 10), dtype=bool)
lst[0, 0] = True
rand_cells = DepthFirstSearch.random_cells(lst, (0, 1), w_h) rand_cells = DepthFirstSearch.random_cells(lst, (0, 1), w_h)
assert len(rand_cells) == 2 assert len(rand_cells) == 2
def test_next_cell(self) -> None: def test_next_cell(self) -> None:
coord = (5, 4) coord = (5, 4)
x, y = coord x, y = coord
assert DepthFirstSearch.next_cell(x, y, "N") == (5, 3) assert DepthFirstSearch.next_cell(x, y, "N") == (2, 3)
def test_reverse_path(self) -> None: def test_reverse_path(self) -> None:
assert DepthFirstSearch.reverse_path("N") == "S" assert DepthFirstSearch.reverse_path("N") == "S"
def test_BOS(self) -> None:
path = {(0, 0), (0, 2), (1, 1)}
assert len(DepthFirstSearch.random_cells(path, (0, 1), (10, 10))) == 0
def test_generator(self):
maze = np.array([])
maze = DepthFirstSearch.generator(10, 10)
assert maze.shape == (10, 10)
+8 -7
View File
@@ -1,18 +1,19 @@
import numpy import numpy
from amaz_lib.MazeGenerator import DepthFirstSearch from amaz_lib.MazeGenerator import DepthFirstSearch
from amaz_lib.MazeGenerator import Kruskal
class TestMazeGenerator: class TestMazeGenerator:
# def test_kruskal_output_shape() -> None: def test_kruskal_output_shape() -> None:
# generator = Kruskal() generator = Kruskal().generator(10, 10)
# maze = numpy.array([]) maze = numpy.array([])
# for output in generator.generator(10, 10): for output in generator:
# maze = output maze = output
# assert maze.shape == (10, 10) assert maze.shape == (10, 10)
def test_generator(self): def test_generator(self) -> None:
maze = numpy.array([]) maze = numpy.array([])
maze = DepthFirstSearch.generator(10, 10) maze = DepthFirstSearch.generator(10, 10)
assert maze.shape == (10, 10) assert maze.shape == (10, 10)