diff --git a/BoriskovaDV/docs/data/2-nd-exercise/main.py b/BoriskovaDV/docs/data/2-nd-exercise/main.py index d081b64..f3cabfd 100644 --- a/BoriskovaDV/docs/data/2-nd-exercise/main.py +++ b/BoriskovaDV/docs/data/2-nd-exercise/main.py @@ -192,6 +192,86 @@ class LabyrinthSolver: ms = (t1 - t0) * 1000 return ms, self.algorithm.get_visited(), len(path) +class Player: + def __init__(self, start, lab): + self.current = start + self.last = None + self.lab = lab + + def move(self, cell): + if cell and cell.can_step(): + self.last = self.current + self.current = cell + return True + return False + + def undo(self): + if self.last: + self.current, self.last = self.last, None + return True + return False + +class Command: + def do(self): + raise NotImplementedError + def revert(self): + raise NotImplementedError + +class MoveCommand(Command): + def __init__(self, player, dx, dy, lab): + self.player = player + self.dx = dx + self.dy = dy + self.lab = lab + self.done = False + + def do(self): + nx = self.player.current.x + self.dx + ny = self.player.current.y + self.dy + target = self.lab.get_point(nx, ny) + if target and target.can_step(): + self.player.move(target) + self.done = True + return True + return False + + def revert(self): + if self.done: + self.player.undo() + self.done = False + return True + return False + +class InteractiveView: + def __init__(self, lab, player): + self.lab = lab + self.player = player + + def render(self): + os.system('cls' if os.name == 'nt' else 'clear') + print("=" * (self.lab.w * 2 + 4)) + print(" LABYRINTH (P = player)") + print("=" * (self.lab.w * 2 + 4)) + for y in range(self.lab.h): + print(" ", end='') + for x in range(self.lab.w): + p = self.lab.get_point(x, y) + if self.player.current == p: + print('P', end=' ') + elif p == self.lab.start_point: + print('S', end=' ') + elif p == self.lab.exit_point: + print('E', end=' ') + elif p.blocked: + print('#', end=' ') + else: + print('.', end=' ') + print() + print("=" * (self.lab.w * 2 + 4)) + print(f" Position: ({self.player.current.x},{self.player.current.y})") + print(" Controls: h(left) j(down) k(up) l(right) u=undo q=quit") + print(" Auto-search: b=BFS d=DFS a=A*") + def run_experiment(maze_file, algo, runs=5): loader = TextMazeLoader() lab = loader.load(maze_file) @@ -209,35 +289,53 @@ def run_experiment(maze_file, algo, runs=5): total_len += plen return total_ms / runs, total_visited / runs, total_len / runs -class TextView: - def display(self, lab): - os.system('cls' if os.name == 'nt' else 'clear') - print("=" * (lab.w * 2 + 4)) - print(" LABYRINTH") - print("=" * (lab.w * 2 + 4)) - for y in range(lab.h): - print(" ", end='') - for x in range(lab.w): - p = lab.get_point(x, y) - if p == lab.start_point: - print('S', end=' ') - elif p == lab.exit_point: - print('E', end=' ') - elif p.blocked: - print('#', end=' ') - else: - print('.', end=' ') - print() - print("=" * (lab.w * 2 + 4)) - print(" S - start E - exit # - wall . - path") - if __name__ == "__main__": - # quick demo loader = TextMazeLoader() lab = loader.load("maze/maze1.txt") - view = TextView() - view.display(lab) - print("\nRunning experiment on maze1.txt with BFS...") - bfs = BreadthFirst() - avg_t, avg_v, avg_l = run_experiment("maze/maze1.txt", bfs, runs=3) - print(f"BFS: time={avg_t:.3f}ms visited={avg_v:.0f} length={avg_l:.0f}") \ No newline at end of file + player = Player(lab.start_point, lab) + view = InteractiveView(lab, player) + view.render() + + solver = LabyrinthSolver(lab) + history = [] + + while True: + key = input("\n > ").lower() + if key == 'q': + print("Goodbye!") + break + elif key == 'b': + solver.set_algorithm(BreadthFirst()) + ms, vis, plen = solver.solve() + print(f"BFS: {ms:.3f}ms, visited={vis}, length={plen}") + elif key == 'd': + solver.set_algorithm(DepthFirst()) + ms, vis, plen = solver.solve() + print(f"DFS: {ms:.3f}ms, visited={vis}, length={plen}") + elif key == 'a': + solver.set_algorithm(AStar()) + ms, vis, plen = solver.solve() + print(f"A*: {ms:.3f}ms, visited={vis}, length={plen}") + elif key in ('h','j','k','l'): + moves = {'h': (-1,0), 'l': (1,0), 'k': (0,-1), 'j': (0,1)} + dx, dy = moves[key] + cmd = MoveCommand(player, dx, dy, lab) + if cmd.do(): + history.append(cmd) + view.render() + if player.current == lab.exit_point: + print("\n*** YOU REACHED THE EXIT! ***") + print(f"Total moves: {len(history)}") + break + else: + print("Can't go there - wall!") + elif key == 'u': + if history: + cmd = history.pop() + cmd.revert() + view.render() + print("Undo last move") + else: + print("Nothing to undo") + else: + print("Unknown command") \ No newline at end of file