8 Commits

Author SHA1 Message Date
Maoake Teriierooiterai c478400640 fix the cell pydantic cause the program was too long 2026-03-24 15:34:43 +01:00
Maoake Teriierooiterai 993bcce857 add generator to my maze generator DFS 2026-03-24 15:22:20 +01:00
Maoake Teriierooiterai a85e342a0a fix conflict 2026-03-24 14:31:49 +01:00
Maoake Teriierooiterai 4d151664ab finish the generator DFS 2026-03-24 14:28:10 +01:00
Maoake Teriierooiterai 8b4ef7afce finish the maze generator 2026-03-24 11:10:16 +01:00
Maoake Teriierooiterai 030c6142ba need to fix my infinite while so i make a checkpoint if i need to restore it 2026-03-24 09:34:53 +01:00
Maoake Teriierooiterai f8f0e31598 fix some bug with my unit testing on the DFS 2026-03-23 19:24:32 +01:00
Maoake Teriierooiterai e75e14110d adding my maze need to be tested 2026-03-23 18:49:13 +01:00
8 changed files with 173 additions and 33 deletions
+8
View File
@@ -18,5 +18,13 @@ lint-strict:
uv run flake8 . uv run flake8 .
uv run mypy . --strict uv run mypy . --strict
run_test_parsing:
PYTHONPATH=src uv run pytest tests/test_parsing.py
run_test_dfs:
PYTHONPATH=src uv run pytest tests/test_Depth.py
run_test_maze_gen:
PYTHONPATH=src uv run pytest tests/test_MazeGenerator.py
run_test: run_test:
uv run pytest uv run pytest
+6 -9
View File
@@ -1,24 +1,21 @@
import os import os
from numpy import ma
from src.amaz_lib import MazeGenerator, Kruskal, AStar
from src.amaz_lib import Maze from src.amaz_lib import Maze
from src.amaz_lib import MazeGenerator
import src.amaz_lib as g
def main() -> None: def main(maze_gen: MazeGenerator) -> None:
# try: # try:
maze = Maze(maze=None) maze = Maze(maze=None)
generator = Kruskal() gen = maze_gen.generator(100, 100)
for alg in generator.generator(20, 20): for alg in gen:
maze.set_maze(alg) maze.set_maze(alg)
os.system("clear") os.system("clear")
maze.ascii_print() maze.ascii_print()
solver = AStar((1, 1), (14, 18))
print(solver.solve(maze))
# except Exception as err: # except Exception as err:
# print(err) # print(err)
if __name__ == "__main__": if __name__ == "__main__":
main() main(g.DepthFirstSearch())
+5 -3
View File
@@ -1,8 +1,10 @@
from pydantic import BaseModel, Field from dataclasses import dataclass
class Cell(BaseModel): @dataclass
value: int = Field(ge=0, le=15) class Cell:
def __init__(self, value: int) -> None:
self.value = value
def __str__(self) -> str: def __str__(self) -> str:
return hex(self.value).removeprefix("0x").upper() return hex(self.value).removeprefix("0x").upper()
+112 -11
View File
@@ -84,17 +84,118 @@ class Kruskal(MazeGenerator):
return self.walls_to_maze(walls, height, width) return self.walls_to_maze(walls, height, width)
def main(): class DepthFirstSearch(MazeGenerator):
try:
for alg in MazeGenerator.Kruskal.kruskal(10, 10):
maze = alg
# print(maze)
# print()
print(maze)
except GeneratorExit as maze: def generator(self, width: int, height: int
print(maze) ) -> Generator[np.ndarray, None, np.ndarray]:
maze = DepthFirstSearch.init_maze(width, height)
visited = np.zeros((height, width), dtype=bool)
path = list()
w_h = (width, height)
coord = (0, 0)
x, y = coord
first = True
while path or first:
first = False
visited[y, x] = True
path = DepthFirstSearch.add_cell_visited(coord, path)
random_c = DepthFirstSearch.random_cells(visited, coord, w_h)
if len(random_c) == 0:
path = DepthFirstSearch.back_on_step(path, w_h, visited)
if path:
coord = path[-1]
random_c = DepthFirstSearch.random_cells(visited, coord, w_h)
x, y = coord
if not path:
break
if __name__ == "__main__": wall = DepthFirstSearch.next_step(random_c)
main() maze[y][x] = DepthFirstSearch.broken_wall(maze[y][x], wall)
coord = DepthFirstSearch.next_cell(x, y, wall)
wall_r = DepthFirstSearch.reverse_path(wall)
x, y = coord
maze[y][x] = DepthFirstSearch.broken_wall(maze[y][x], wall_r)
yield maze
return maze
@staticmethod
def init_maze(width: int, height: int) -> np.ndarray:
maze = np.array([[Cell(value=15) for _ in range(width)]
for _ in range(height)])
return maze
@staticmethod
def add_cell_visited(coord: tuple, path: set) -> list:
path.append(coord)
return path
@staticmethod
def random_cells(visited: np.array, coord: tuple, w_h: tuple) -> list:
rand_cell = []
x, y = coord
width, height = w_h
if y - 1 >= 0 and not visited[y - 1][x]:
rand_cell.append("N")
if y + 1 < height and not visited[y + 1][x]:
rand_cell.append("S")
if x - 1 >= 0 and not visited[y][x - 1]:
rand_cell.append("W")
if x + 1 < width and not visited[y][x + 1]:
rand_cell.append("E")
return rand_cell
@staticmethod
def next_step(rand_cell: list) -> str:
return np.random.choice(rand_cell)
@staticmethod
def broken_wall(cell: Cell, wall: str) -> Cell:
if wall == "N":
cell.set_north(False)
elif wall == "S":
cell.set_south(False)
elif wall == "W":
cell.set_west(False)
elif wall == "E":
cell.set_est(False)
return cell
@staticmethod
def next_cell(x: int, y: int, next: str) -> tuple:
next_step = {
"N": (0, -1),
"S": (0, 1),
"W": (-1, 0),
"E": (1, 0)
}
add_x, add_y = next_step[next]
return (x + add_x, y + add_y)
@staticmethod
def reverse_path(next: str) -> str:
reverse = {
"N": "S",
"S": "N",
"W": "E",
"E": "W"
}
return reverse[next]
@staticmethod
def back_on_step(path: list, w_h: tuple, visited: np.array) -> list:
last = path[-1]
r_cells = DepthFirstSearch.random_cells(visited, last, w_h)
while len(path) > 0:
path.pop()
if path:
last = path[-1]
r_cells = DepthFirstSearch.random_cells(visited, last, w_h)
if r_cells:
break
return path
+4 -2
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, Kruskal from .MazeGenerator import MazeGenerator, DepthFirstSearch
from .MazeGenerator import Kruskal
from .MazeSolver import MazeSolver, AStar from .MazeSolver import MazeSolver, AStar
__version__ = "1.0.0" __version__ = "1.0.0"
__author__ = "us" __author__ = "us"
__all__ = ["Cell", "Maze", "MazeGenerator", "MazeSolver", "AStar", "Kruskal"] __all__ = ["Cell", "Maze", "MazeGenerator",
"MazeSolver", "AStar", "Kruskal", "DepthFirstSearch"]
+27
View File
@@ -0,0 +1,27 @@
from amaz_lib.MazeGenerator import DepthFirstSearch
from amaz_lib.Cell import Cell
import numpy as np
class TestDepth:
def test_init_maze(self) -> None:
maze = DepthFirstSearch.init_maze(10, 10)
cell = Cell(value=15)
maze[1][1].set_est(False)
assert maze[0][0].value == cell.value
def test_rand_cells(self) -> None:
w_h = (10, 10)
lst = np.zeros((10, 10), dtype=bool)
lst[0, 0] = True
rand_cells = DepthFirstSearch.random_cells(lst, (0, 1), w_h)
assert len(rand_cells) == 2
def test_next_cell(self) -> None:
coord = (5, 4)
x, y = coord
assert DepthFirstSearch.next_cell(x, y, "N") == (2, 3)
def test_reverse_path(self) -> None:
assert DepthFirstSearch.reverse_path("N") == "S"
+1 -1
View File
@@ -15,7 +15,7 @@ def test_maze_setter_getter() -> None:
) )
maze.set_maze(test) maze.set_maze(test)
assert numpy.array_equal(maze.get_maze(), test) == True assert numpy.array_equal(maze.get_maze(), test) is True
def test_maze_str() -> None: def test_maze_str() -> None:
+10 -7
View File
@@ -1,11 +1,14 @@
import numpy import numpy
from amaz_lib.MazeGenerator import Kruskal from amaz_lib.MazeGenerator import DepthFirstSearch
def test_kruskal_output_shape() -> None: class TestMazeGenerator:
generator = Kruskal()
maze = numpy.array([])
for output in generator.generator(10, 10):
maze = output
assert maze.shape == (10, 10) def test_generator(self) -> None:
w_h = (300, 300)
maze = numpy.array([])
generator = DepthFirstSearch().generator(*w_h)
for output in generator:
maze = output
assert maze.shape == w_h