fix mypy strict on MazeSolver and Maze Generator

This commit is contained in:
Maoake Teriierooiterai
2026-04-01 14:12:39 +02:00
parent ed16566677
commit 03b5f9e6fd
5 changed files with 73 additions and 57 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ lint:
uv run mypy . --warn-return-any --warn-unused-ignores --ignore-missing-imports --disallow-untyped-defs --check-untyped-defs uv run mypy . --warn-return-any --warn-unused-ignores --ignore-missing-imports --disallow-untyped-defs --check-untyped-defs
lint-strict: lint-strict:
uv run flake8 . uv run flake8 . --exclude=.venv
uv run mypy . --strict uv run mypy . --strict
run_test_parsing: run_test_parsing:
+1 -1
View File
@@ -330,7 +330,7 @@ class MazeMLX:
self.mlx.mlx_loop_hook(self.mlx_ptr, self.draw_image, amazing) self.mlx.mlx_loop_hook(self.mlx_ptr, self.draw_image, amazing)
self.mlx.mlx_hook(self.win_ptr, 33, 0, self.close_loop, None) self.mlx.mlx_hook(self.win_ptr, 33, 0, self.close_loop, None)
self.mlx.mlx_hook( self.mlx.mlx_hook(
self.win_ptr, 2, 1 << 0, self.handle_key_press_mteriier, amazing self.win_ptr, 2, 1 << 0, self.handle_key_press, amazing
) )
self.mlx.mlx_loop(self.mlx_ptr) self.mlx.mlx_loop(self.mlx_ptr)
+2 -2
View File
@@ -1,5 +1,5 @@
WIDTH=13 WIDTH=15
HEIGHT=13 HEIGHT=15
ENTRY=1,1 ENTRY=1,1
EXIT=5,5 EXIT=5,5
OUTPUT_FILE=maze.txt OUTPUT_FILE=maze.txt
+37 -29
View File
@@ -1,12 +1,15 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Generator, Set from typing import Generator, Any
import numpy as np import numpy as np
from numpy.typing import NDArray
from .Cell import Cell from .Cell import Cell
import math import math
import random
class MazeGenerator(ABC): class MazeGenerator(ABC):
def __init__(self, start: tuple, end: tuple, perfect: bool) -> None: def __init__(self, start: tuple[int, int], end: tuple[int, int],
perfect: bool) -> None:
self.start = (start[0] - 1, start[1] - 1) self.start = (start[0] - 1, start[1] - 1)
self.end = (end[0] - 1, end[1] - 1) self.end = (end[0] - 1, end[1] - 1)
self.perfect = perfect self.perfect = perfect
@@ -14,10 +17,10 @@ class MazeGenerator(ABC):
@abstractmethod @abstractmethod
def generator( def generator(
self, height: int, width: int, seed: int | None = None self, height: int, width: int, seed: int | None = None
) -> Generator[np.ndarray, None, np.ndarray]: ... ) -> Generator[NDArray[Any], None, NDArray[Any]]: ...
@staticmethod @staticmethod
def get_cell_ft(width: int, height: int) -> set: def get_cell_ft(width: int, height: int) -> set[tuple[int, int]]:
forty_two = set() forty_two = set()
y, x = (int(height / 2), int(width / 2)) y, x = (int(height / 2), int(width / 2))
forty_two.add((y, x - 1)) forty_two.add((y, x - 1))
@@ -42,9 +45,10 @@ class MazeGenerator(ABC):
@staticmethod @staticmethod
def unperfect_maze(width: int, height: int, def unperfect_maze(width: int, height: int,
maze: np.ndarray, forty_two: set | None, maze: NDArray[Any],
forty_two: set[tuple[int, int]] | None,
prob: float = 0.1 prob: float = 0.1
) -> Generator[np.ndarray, None, np.ndarray]: ) -> Generator[NDArray[Any], None, NDArray[Any]]:
directions = { directions = {
"N": (0, -1), "N": (0, -1),
"S": (0, 1), "S": (0, 1),
@@ -94,19 +98,19 @@ class MazeGenerator(ABC):
class Kruskal(MazeGenerator): class Kruskal(MazeGenerator):
class Set: class KruskalSet:
def __init__(self, cells: list[int]) -> None: def __init__(self, cells: list[int]) -> None:
self.cells: list[int] = cells self.cells: list[int] = cells
class Sets: class Sets:
def __init__(self, sets: list[Set]) -> None: def __init__(self, sets: list['Kruskal.KruskalSet']) -> None:
self.sets = sets self.sets = sets
@staticmethod @staticmethod
def walls_to_maze( def walls_to_maze(
walls: np.ndarray, height: int, width: int walls: list[tuple[int, int]], height: int, width: int
) -> np.ndarray: ) -> NDArray[Any]:
maze: np.ndarray = np.array( maze: NDArray[Any] = np.array(
[[Cell(value=0) for _ in range(width)] for _ in range(height)] [[Cell(value=0) for _ in range(width)] for _ in range(height)]
) )
for wall in walls: for wall in walls:
@@ -171,7 +175,7 @@ class Kruskal(MazeGenerator):
def generator( def generator(
self, height: int, width: int, seed: int | None = None self, height: int, width: int, seed: int | None = None
) -> Generator[np.ndarray, None, np.ndarray]: ) -> Generator[NDArray[Any], None, NDArray[Any]]:
cells_ft = None cells_ft = None
if height > 10 and width > 10: if height > 10 and width > 10:
cells_ft = self.get_cell_ft(width, height) cells_ft = self.get_cell_ft(width, height)
@@ -180,7 +184,7 @@ class Kruskal(MazeGenerator):
if seed is not None: if seed is not None:
np.random.seed(seed) np.random.seed(seed)
sets = self.Sets([self.Set([i]) for i in range(height * width)]) sets = self.Sets([self.KruskalSet([i]) for i in range(height * width)])
walls = [] walls = []
for h in range(height): for h in range(height):
for w in range(width - 1): for w in range(width - 1):
@@ -217,28 +221,29 @@ class Kruskal(MazeGenerator):
class DepthFirstSearch(MazeGenerator): class DepthFirstSearch(MazeGenerator):
def __init__(self, start: bool, end: bool, perfect: bool) -> None: def __init__(self, start: tuple[int, int], end: tuple[int, int],
perfect: bool) -> None:
self.start = (start[0] - 1, start[1] - 1) self.start = (start[0] - 1, start[1] - 1)
self.end = (end[0] - 1, end[1] - 1) self.end = (end[0] - 1, end[1] - 1)
self.perfect = perfect self.perfect = perfect
self.forty_two: set | None = None self.forty_two: set[tuple[int, int]] | None = None
def generator( def generator(
self, height: int, width: int, seed: int = None self, height: int, width: int, seed: int | None = None
) -> Generator[np.ndarray, None, np.ndarray]: ) -> Generator[NDArray[Any], None, NDArray[Any]]:
if seed is not None: if seed is not None:
np.random.seed(seed) np.random.seed(seed)
maze = self.init_maze(width, height) maze = self.init_maze(width, height)
if width > 9 and height > 9: if width > 9 and height > 9:
self.forty_two = self.get_cell_ft(width, height) self.forty_two = self.get_cell_ft(width, height)
visited = np.zeros((height, width), dtype=bool) visited: NDArray[np.object_] = np.zeros((height, width), dtype=bool)
if ( if (
self.forty_two self.forty_two
and self.start not in self.forty_two and self.start not in self.forty_two
and self.end not in self.forty_two and self.end not in self.forty_two
): ):
visited = self.lock_cell_ft(visited, self.forty_two) visited = self.lock_cell_ft(visited, self.forty_two)
path = list() path: list[tuple[int, int]] = list()
w_h = (width, height) w_h = (width, height)
coord = (0, 0) coord = (0, 0)
x, y = coord x, y = coord
@@ -277,20 +282,22 @@ class DepthFirstSearch(MazeGenerator):
return maze return maze
@staticmethod @staticmethod
def init_maze(width: int, height: int) -> np.ndarray: def init_maze(width: int, height: int) -> NDArray[Any]:
maze = np.array( maze = np.array(
[[Cell(value=15) for _ in range(width)] for _ in range(height)] [[Cell(value=15) for _ in range(width)] for _ in range(height)]
) )
return maze return maze
@staticmethod @staticmethod
def add_cell_visited(coord: tuple, path: set) -> list: def add_cell_visited(coord: tuple[int, int], path: list[tuple[int, int]]
) -> list[tuple[int, int]]:
path.append(coord) path.append(coord)
return path return path
@staticmethod @staticmethod
def random_cells(visited: np.array, coord: tuple, w_h: tuple) -> list: def random_cells(visited: NDArray[Any], coord: tuple[int, int],
rand_cell = [] w_h: tuple[int, int]) -> list[str]:
rand_cell: list[str] = []
x, y = coord x, y = coord
width, height = w_h width, height = w_h
@@ -308,8 +315,8 @@ class DepthFirstSearch(MazeGenerator):
return rand_cell return rand_cell
@staticmethod @staticmethod
def next_step(rand_cell: list) -> str: def next_step(rand_cell: list[str]) -> str:
return np.random.choice(rand_cell) return random.choice(rand_cell)
@staticmethod @staticmethod
def broken_wall(cell: Cell, wall: str) -> Cell: def broken_wall(cell: Cell, wall: str) -> Cell:
@@ -324,7 +331,7 @@ class DepthFirstSearch(MazeGenerator):
return cell return cell
@staticmethod @staticmethod
def next_cell(x: int, y: int, next: str) -> tuple: def next_cell(x: int, y: int, next: str) -> tuple[int, int]:
next_step = {"N": (0, -1), "S": (0, 1), "W": (-1, 0), "E": (1, 0)} next_step = {"N": (0, -1), "S": (0, 1), "W": (-1, 0), "E": (1, 0)}
add_x, add_y = next_step[next] add_x, add_y = next_step[next]
return (x + add_x, y + add_y) return (x + add_x, y + add_y)
@@ -334,7 +341,8 @@ class DepthFirstSearch(MazeGenerator):
return {"N": "S", "S": "N", "W": "E", "E": "W"}[direction] return {"N": "S", "S": "N", "W": "E", "E": "W"}[direction]
@staticmethod @staticmethod
def back_on_step(path: list, w_h: tuple, visited: np.ndarray) -> list: def back_on_step(path: list[tuple[int, int]], w_h: tuple[int, int],
visited: NDArray[Any]) -> list[tuple[int, int]]:
while path: while path:
last = path[-1] last = path[-1]
if DepthFirstSearch.random_cells(visited, last, w_h): if DepthFirstSearch.random_cells(visited, last, w_h):
@@ -344,8 +352,8 @@ class DepthFirstSearch(MazeGenerator):
@staticmethod @staticmethod
def lock_cell_ft( def lock_cell_ft(
visited: np.ndarray, forty_two: set[tuple[int]] visited: NDArray[Any], forty_two: set[tuple[int, int]]
) -> np.ndarray: ) -> NDArray[Any]:
tab = [cell for cell in forty_two] tab = [cell for cell in forty_two]
for cell in tab: for cell in tab:
visited[cell] = True visited[cell] = True
+32 -24
View File
@@ -2,6 +2,8 @@ from abc import ABC, abstractmethod
from .Maze import Maze from .Maze import Maze
from typing import Any from typing import Any
import numpy as np import numpy as np
from numpy.typing import NDArray
import random
class MazeSolver(ABC): class MazeSolver(ABC):
@@ -36,7 +38,6 @@ class AStar(MazeSolver):
def __init__(self, start: tuple[int, int], end: tuple[int, int]) -> None: def __init__(self, start: tuple[int, int], end: tuple[int, int]) -> None:
super().__init__(start, end) super().__init__(start, end)
self.path = []
def h(self, n: tuple[int, int]) -> int: def h(self, n: tuple[int, int]) -> int:
return ( return (
@@ -48,9 +49,9 @@ class AStar(MazeSolver):
def get_paths( def get_paths(
self, self,
maze: np.ndarray, maze: NDArray[Any],
actual: tuple[int, int], actual: tuple[int, int],
close: list, close: list['Node'],
) -> list[tuple[int, int]]: ) -> list[tuple[int, int]]:
path = [ path = [
( (
@@ -88,7 +89,7 @@ class AStar(MazeSolver):
] ]
return [p for p in path if p is not None] return [p for p in path if p is not None]
def get_path(self, maze: np.ndarray) -> list: def get_path(self, maze: NDArray[Any]) -> list['Node']:
open: list[AStar.Node] = [] open: list[AStar.Node] = []
close: list[AStar.Node] = [] close: list[AStar.Node] = []
@@ -145,7 +146,7 @@ class AStar(MazeSolver):
else: else:
raise Exception("Translate error: AStar path not found") raise Exception("Translate error: AStar path not found")
def translate(self, close: list) -> str: def translate(self, close: list['Node']) -> str:
current = close[-1] current = close[-1]
res = "" res = ""
while True: while True:
@@ -158,28 +159,35 @@ class AStar(MazeSolver):
def solve( def solve(
self, maze: Maze, height: int | None = None, width: int | None = None self, maze: Maze, height: int | None = None, width: int | None = None
) -> str: ) -> str:
path = self.get_path(maze.get_maze()) maze_arr = maze.get_maze()
if maze_arr is None:
raise Exception("Maze is not initialized")
path: list[AStar.Node] = self.get_path(maze_arr)
return self.translate(path) return self.translate(path)
class DepthFirstSearchSolver(MazeSolver): class DepthFirstSearchSolver(MazeSolver):
def __init__(self, start, end): def __init__(self, start: tuple[int, int], end: tuple[int, int]):
super().__init__(start, end) super().__init__(start, end)
def solve( def solve(
self, maze: Maze, height: int | None = None, width: int | None = None self, maze: Maze, height: int | None = None, width: int | None = None
) -> str: ) -> str:
path_str = "" path_str = ""
visited = np.zeros((height, width), dtype=bool) if height is None or width is None:
path = list() raise Exception("We need Height and Width in the arg")
move = list() visited: NDArray[Any] = np.zeros((height, width), dtype=bool)
path: list[tuple[int, int]] = list()
move: list[str] = list()
maze_s = maze.get_maze() maze_s = maze.get_maze()
if maze_s is None:
raise Exception("Maze is not initializef")
coord = self.start coord = self.start
h_w = (height, width) h_w: tuple[int, int] = (height, width)
while coord != self.end: while coord != self.end:
visited[coord] = True visited[coord] = True
path.append(coord) path.append(coord)
rand_p = self.random_path(visited, coord, maze_s, h_w) rand_p: list[str] = self.random_path(visited, coord, maze_s, h_w)
if not rand_p: if not rand_p:
path, move = self.back_on_step( path, move = self.back_on_step(
@@ -199,9 +207,9 @@ class DepthFirstSearchSolver(MazeSolver):
return path_str return path_str
@staticmethod @staticmethod
def random_path( def random_path(visited: NDArray[Any], coord: tuple[int, int],
visited: np.ndarray, coord: tuple, maze: np.ndarray, h_w: tuple maze: NDArray[Any], h_w: tuple[int, int]
) -> list: ) -> list[str]:
random_p = [] random_p = []
h, w = h_w h, w = h_w
y, x = coord y, x = coord
@@ -220,17 +228,17 @@ class DepthFirstSearchSolver(MazeSolver):
return random_p return random_p
@staticmethod @staticmethod
def next_path(rand_path: list) -> str: def next_path(rand_path: list[str]) -> str:
return np.random.choice(rand_path) return random.choice(rand_path)
@staticmethod @staticmethod
def back_on_step( def back_on_step(
path: list, path: list[tuple[int, int]],
visited: np.ndarray, visited: NDArray[Any],
maze: np.ndarray, maze: NDArray[Any],
h_w: tuple, h_w: tuple[int, int],
move: list, move: list[str],
) -> list: ) -> tuple[list[Any], list[Any]]:
while path: while path:
last = path[-1] last = path[-1]
if DepthFirstSearchSolver.random_path(visited, last, maze, h_w): if DepthFirstSearchSolver.random_path(visited, last, maze, h_w):
@@ -240,7 +248,7 @@ class DepthFirstSearchSolver(MazeSolver):
return path, move return path, move
@staticmethod @staticmethod
def next_cell(coord: tuple, next: str) -> tuple: def next_cell(coord: tuple[int, int], next: str) -> tuple[int, int]:
y, x = coord y, x = coord
next_step = {"N": (-1, 0), "S": (1, 0), "W": (0, -1), "E": (0, 1)} next_step = {"N": (-1, 0), "S": (1, 0), "W": (0, -1), "E": (0, 1)}
add_y, add_x = next_step[next] add_y, add_x = next_step[next]