fixing the conflict

This commit is contained in:
Maoake Teriierooiterai
2026-03-30 14:47:16 +02:00
3 changed files with 181 additions and 175 deletions
+41 -38
View File
@@ -43,6 +43,8 @@ class MazeMLX:
)
def put_pixel(self, x, y) -> None:
if x < 0 or y < 0 or x >= self.width or y >= self.height:
return
offset = y * self.size_line + x * (self.bpp // 8)
self.buf[offset + 0] = self.color[0]
@@ -80,23 +82,23 @@ class MazeMLX:
def update_maze(self, maze: np.ndarray) -> None:
self.clear_image()
margin = math.trunc(
math.sqrt(self.width if self.width > self.height else self.height)
// 2
)
line_len = math.trunc(
(
(self.height - margin) // len(maze)
if self.height > self.width
else (self.width - margin) // len(maze[0])
)
)
rows = len(maze)
cols = len(maze[0])
line_len = min(self.width // cols, self.height // rows)
maze_width = cols * line_len
maze_height = rows * line_len
margin_x = (self.width - maze_width) // 2
margin_y = (self.height - maze_height) // 2
for y in range(len(maze)):
for x in range(len(maze[0])):
x0 = x * line_len + margin
y0 = y * line_len + margin
x1 = x * line_len + line_len + margin
y1 = y * line_len + line_len + margin
x0 = x * line_len + margin_x
y0 = y * line_len + margin_y
x1 = x * line_len + line_len + margin_x
y1 = y * line_len + line_len + margin_y
if maze[y][x].get_north():
self.put_line((x0, y0), (x1, y0))
@@ -119,31 +121,32 @@ class MazeMLX:
maze = amazing.maze.get_maze()
if maze is None:
return
margin = math.trunc(
math.sqrt(self.width if self.width > self.height else self.height)
// 2
)
cell_size = math.trunc(
(
(self.height - margin) // len(maze)
if self.height > self.width
else (self.width - margin) // len(maze[0])
)
)
rows = len(maze)
cols = len(maze[0])
line_len = min(self.width // cols, self.height // rows)
maze_width = cols * line_len
maze_height = rows * line_len
margin_x = (self.width - maze_width) // 2
margin_y = (self.height - maze_height) // 2
for i in range(len(path)):
ul = (
(actual[0]) * cell_size + margin + 12,
(actual[1]) * cell_size + 12 + margin,
(actual[0]) * line_len + margin_x + 12,
(actual[1]) * line_len + 12 + margin_y,
)
dr = (
(actual[0]) * cell_size + cell_size + margin - 12,
(actual[1]) * cell_size + cell_size - 12 + margin,
(actual[0]) * line_len + line_len + margin_x - 12,
(actual[1]) * line_len + line_len - 12 + margin_y,
)
self.put_block(ul, dr)
x0 = actual[0] * cell_size + margin + 12
y0 = actual[1] * cell_size + margin + 12
x1 = actual[0] * cell_size + cell_size + margin - 12
y1 = actual[1] * cell_size + cell_size + margin - 12
x0 = actual[0] * line_len + margin_x + 12
y0 = actual[1] * line_len + margin_y + 12
x1 = actual[0] * line_len + line_len + margin_x - 12
y1 = actual[1] * line_len + line_len + margin_y - 12
yield
match path[i]:
case "N":
@@ -159,12 +162,12 @@ class MazeMLX:
self.put_block((x0, y0), (x0 - 24, y1))
actual = (actual[0] - 1, actual[1])
ul = (
(actual[0]) * cell_size + margin + 12,
(actual[1]) * cell_size + 12 + margin,
(actual[0]) * line_len + margin_x + 12,
(actual[1]) * line_len + 12 + margin_y,
)
dr = (
(actual[0]) * cell_size + cell_size + margin - 12,
(actual[1]) * cell_size + cell_size - 12 + margin,
(actual[0]) * line_len + line_len + margin_x - 12,
(actual[1]) * line_len + line_len - 12 + margin_y,
)
self.put_block(ul, dr)
return
+2 -2
View File
@@ -1,8 +1,8 @@
WIDTH=15
HEIGHT=15
ENTRY=1,1
EXIT=11,11
EXIT=13,13
OUTPUT_FILE=maze.txt
PERFECT=False
GENERATOR=DFS
SOLVER=DFS
SOLVER=AStar
+138 -135
View File
@@ -1,5 +1,6 @@
from abc import ABC, abstractmethod
from .Maze import Maze
from typing import Any
import numpy as np
@@ -9,170 +10,165 @@ class MazeSolver(ABC):
self.end = (end[1] - 1, end[0] - 1)
@abstractmethod
def solve(self, maze: Maze, height: int = None,
width: int = None) -> str: ...
def solve(
self, maze: Maze, height: int | None = None, width: int | None = None
) -> str: ...
class AStar(MazeSolver):
class Node:
def __init__(
self,
coordinate: tuple[int, int],
g: int,
h: int,
f: int,
parent: Any,
) -> None:
self.coordinate = coordinate
self.g = g
self.h = h
self.f = f
self.parent = parent
def __eq__(self, value: object, /) -> bool:
return value == self.coordinate
def __init__(self, start: tuple[int, int], end: tuple[int, int]) -> None:
super().__init__(start, end)
self.path = []
def f(self, n):
def g(n: tuple[int, int]) -> int:
res = 0
if n[0] < self.start[0]:
res += self.start[0] - n[0]
else:
res += n[0] - self.start[0]
if n[1] < self.start[1]:
res += self.start[1] - n[1]
else:
res += n[1] - self.start[1]
return res
def h(self, n: tuple[int, int]) -> int:
return (
max(n[0], self.end[0])
- min(n[0], self.end[0])
+ max(n[1], self.end[1])
- min(n[1], self.end[1])
)
def h(n: tuple[int, int]) -> int:
res = 0
if n[0] < self.end[0]:
res += self.end[0] - n[0]
else:
res += n[0] - self.end[0]
if n[1] < self.end[1]:
res += self.end[1] - n[1]
else:
res += n[1] - self.end[1]
return res
try:
return g(n) + h(n)
except Exception:
return 1000
def best_path(
def get_paths(
self,
maze: np.ndarray,
actual: tuple[int, int],
last: str | None,
) -> dict[str, int]:
path = {
"N": (
self.f((actual[0], actual[1] - 1))
if not maze[actual[1]][actual[0]].get_north() and actual[1] > 0
close: list,
) -> list[tuple[int, int]]:
path = [
(
(actual[0], actual[1] - 1)
if not maze[actual[1]][actual[0]].get_north()
and actual[1] > 0
and (actual[0], actual[1] - 1)
not in [n.coordinate for n in close]
else None
),
"E": (
self.f((actual[0] + 1, actual[1]))
(
(actual[0] + 1, actual[1])
if not maze[actual[1]][actual[0]].get_est()
and actual[0] < len(maze[0]) - 1
and (actual[0] + 1, actual[1])
not in [n.coordinate for n in close]
else None
),
"S": (
self.f((actual[0], actual[1] + 1))
(
(actual[0], actual[1] + 1)
if not maze[actual[1]][actual[0]].get_south()
and actual[1] < len(maze) - 1
and (actual[0], actual[1] + 1)
not in [n.coordinate for n in close]
else None
),
"W": (
self.f((actual[0] - 1, actual[1]))
if not maze[actual[1]][actual[0]].get_west() and actual[0] > 0
(
(actual[0] - 1, actual[1])
if not maze[actual[1]][actual[0]].get_west()
and actual[0] > 0
and (actual[0] - 1, actual[1])
not in [n.coordinate for n in close]
else None
),
}
return {
k: v
for k, v in sorted(path.items(), key=lambda item: item[0])
if v is not None and k != last
}
]
return [p for p in path if p is not None]
def get_opposit(self, dir: str) -> str:
match dir:
case "N":
return "S"
case "E":
return "W"
case "S":
return "N"
case "W":
return "E"
case _:
return ""
def get_path(self, maze: np.ndarray) -> list:
open: list[AStar.Node] = []
close: list[AStar.Node] = []
def get_next_pos(
self, dir: str, actual: tuple[int, int]
) -> tuple[int, int]:
match dir:
case "N":
return (actual[0], actual[1] - 1)
case "E":
return (actual[0] + 1, actual[1])
case "S":
return (actual[0], actual[1] + 1)
case "W":
return (actual[0] - 1, actual[1])
case _:
return actual
def get_path(self, maze: np.ndarray) -> str | None:
path = [(self.start, self.best_path(maze, self.start, None))]
visited = [self.start]
while len(path) > 0 and path[-1][0] != self.end:
if len(path[-1][1]) == 0:
path.pop(-1)
if len(path) == 0:
break
k = next(iter(path[-1][1]))
path[-1][1].pop(k)
continue
while len(path[-1][1]) > 0:
next_pos = self.get_next_pos(
list(path[-1][1].keys())[0], path[-1][0]
)
if next_pos in visited:
k = next(iter(path[-1][1]))
path[-1][1].pop(k)
else:
break
if len(path[-1][1]) == 0:
path.pop(-1)
continue
pre = self.get_opposit(list(path[-1][1].keys())[0])
path.append(
(
next_pos,
self.best_path(maze, next_pos, pre),
)
open.append(
AStar.Node(
self.start,
0,
self.h(self.start),
self.h(self.start),
None,
)
visited += [next_pos]
if len(path) == 0:
return None
path[-1] = (self.end, {})
return "".join(
str(list(c[1].keys())[0]) for c in path if len(c[1]) > 0
)
def solve(self, maze: Maze, height: int = None,
width: int = None) -> str:
res = self.get_path(maze.get_maze())
if res is None:
raise Exception("Path not found")
while len(open) > 0:
to_check = sorted(open, key=lambda x: x.f)[0]
open.remove(to_check)
close.append(to_check)
if to_check.coordinate == self.end:
return close
paths = self.get_paths(maze, to_check.coordinate, close)
for path in paths:
open.append(
self.Node(
path,
to_check.g + 1,
self.h(path),
self.h(path) + to_check.g + 1,
to_check,
)
)
raise Exception("Path not found")
def get_rev_dir(self, current: Node) -> str:
if current.parent.coordinate == (
current.coordinate[0],
current.coordinate[1] - 1,
):
return "S"
elif current.parent.coordinate == (
current.coordinate[0] + 1,
current.coordinate[1],
):
return "W"
elif current.parent.coordinate == (
current.coordinate[0],
current.coordinate[1] + 1,
):
return "N"
elif current.parent.coordinate == (
current.coordinate[0] - 1,
current.coordinate[1],
):
return "E"
else:
raise Exception("Translate error: AStar path not found")
def translate(self, close: list) -> str:
current = close[-1]
res = ""
while True:
res = self.get_rev_dir(current) + res
current = current.parent
if current.coordinate == self.start:
break
return res
def solve(
self, maze: Maze, height: int | None = None, width: int | None = None
) -> str:
path = self.get_path(maze.get_maze())
return self.translate(path)
class DepthFirstSearchSolver(MazeSolver):
def __init__(self, start, end):
super().__init__(start, end)
def solve(self, maze: Maze, height: int = None,
width: int = None) -> str:
res = list()
for _ in range(50):
res.append(self.get_path(maze, height, width))
return min(res, key=lambda x: len(x))
def get_path(self, maze: Maze, height: int = None,
width: int = None) -> str:
def solve(
self, maze: Maze, height: int | None = None, width: int | None = None
) -> str:
path_str = ""
visited = np.zeros((height, width), dtype=bool)
path = list()
@@ -186,8 +182,9 @@ class DepthFirstSearchSolver(MazeSolver):
rand_p = self.random_path(visited, coord, maze_s, h_w)
if not rand_p:
path, move = self.back_on_step(path, visited, maze_s, h_w,
move)
path, move = self.back_on_step(
path, visited, maze_s, h_w, move
)
if not path:
break
coord = path[-1]
@@ -202,8 +199,9 @@ class DepthFirstSearchSolver(MazeSolver):
return path_str
@staticmethod
def random_path(visited: np.ndarray, coord: tuple,
maze: np.ndarray, h_w: tuple) -> list:
def random_path(
visited: np.ndarray, coord: tuple, maze: np.ndarray, h_w: tuple
) -> list:
random_p = []
h, w = h_w
y, x = coord
@@ -226,8 +224,13 @@ class DepthFirstSearchSolver(MazeSolver):
return np.random.choice(rand_path)
@staticmethod
def back_on_step(path: list, visited: np.ndarray,
maze: np.ndarray, h_w: tuple, move: list) -> list:
def back_on_step(
path: list,
visited: np.ndarray,
maze: np.ndarray,
h_w: tuple,
move: list,
) -> list:
while path:
last = path[-1]
if DepthFirstSearchSolver.random_path(visited, last, maze, h_w):