forked from UNN/2026-rff_mp
117 lines
3.5 KiB
Python
117 lines
3.5 KiB
Python
|
|
import sys
|
||
|
|
import os
|
||
|
|
|
||
|
|
class Tile:
|
||
|
|
"""Клетка лабиринта."""
|
||
|
|
def __init__(self, x, y):
|
||
|
|
self.x = x
|
||
|
|
self.y = y
|
||
|
|
self.wall = False
|
||
|
|
self.start = False
|
||
|
|
self.exit = False
|
||
|
|
|
||
|
|
def passable(self):
|
||
|
|
return not self.wall
|
||
|
|
|
||
|
|
|
||
|
|
class Labyrinth:
|
||
|
|
"""Модель лабиринта."""
|
||
|
|
def __init__(self, width, height):
|
||
|
|
self.width = width
|
||
|
|
self.height = height
|
||
|
|
self._tiles = [[Tile(x, y) for x in range(width)] for y in range(height)]
|
||
|
|
self.start_tile = None
|
||
|
|
self.exit_tile = None
|
||
|
|
|
||
|
|
def get_tile(self, x, y):
|
||
|
|
if 0 <= x < self.width and 0 <= y < self.height:
|
||
|
|
return self._tiles[y][x]
|
||
|
|
return None
|
||
|
|
|
||
|
|
def set_tile(self, x, y, kind):
|
||
|
|
tile = self.get_tile(x, y)
|
||
|
|
if tile is None:
|
||
|
|
return
|
||
|
|
if kind == 'wall':
|
||
|
|
tile.wall = True
|
||
|
|
elif kind == 'start':
|
||
|
|
if self.start_tile:
|
||
|
|
self.start_tile.start = False
|
||
|
|
tile.start = True
|
||
|
|
tile.wall = False
|
||
|
|
self.start_tile = tile
|
||
|
|
elif kind == 'exit':
|
||
|
|
if self.exit_tile:
|
||
|
|
self.exit_tile.exit = False
|
||
|
|
tile.exit = True
|
||
|
|
tile.wall = False
|
||
|
|
self.exit_tile = tile
|
||
|
|
elif kind == 'path':
|
||
|
|
tile.wall = False
|
||
|
|
|
||
|
|
def neighbours(self, tile):
|
||
|
|
dirs = [(0, -1), (0, 1), (-1, 0), (1, 0)]
|
||
|
|
result = []
|
||
|
|
for dx, dy in dirs:
|
||
|
|
nx, ny = tile.x + dx, tile.y + dy
|
||
|
|
nb = self.get_tile(nx, ny)
|
||
|
|
if nb and nb.passable():
|
||
|
|
result.append(nb)
|
||
|
|
return result
|
||
|
|
|
||
|
|
|
||
|
|
class LabyrinthLoader:
|
||
|
|
def load(self, filename):
|
||
|
|
raise NotImplementedError
|
||
|
|
|
||
|
|
|
||
|
|
class TextLabyrinthLoader(LabyrinthLoader):
|
||
|
|
def load(self, filename):
|
||
|
|
with open(filename, 'r', encoding='utf-8') as f:
|
||
|
|
lines = [line.rstrip('\n') for line in f]
|
||
|
|
h = len(lines)
|
||
|
|
w = max(len(line) for line in lines) if h > 0 else 0
|
||
|
|
start_cnt = 0
|
||
|
|
exit_cnt = 0
|
||
|
|
lab = Labyrinth(w, h)
|
||
|
|
|
||
|
|
for y, line in enumerate(lines):
|
||
|
|
for x, ch in enumerate(line):
|
||
|
|
if ch == '#':
|
||
|
|
lab.set_tile(x, y, 'wall')
|
||
|
|
elif ch == 'S':
|
||
|
|
lab.set_tile(x, y, 'start')
|
||
|
|
start_cnt += 1
|
||
|
|
elif ch == 'E':
|
||
|
|
lab.set_tile(x, y, 'exit')
|
||
|
|
exit_cnt += 1
|
||
|
|
else:
|
||
|
|
lab.set_tile(x, y, 'path')
|
||
|
|
if start_cnt != 1 or exit_cnt != 1:
|
||
|
|
raise ValueError(f"Нужны ровно S и E, найдено S={start_cnt}, E={exit_cnt}")
|
||
|
|
return lab
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
# Простая проверка загрузки и вывода лабиринта
|
||
|
|
loader = TextLabyrinthLoader()
|
||
|
|
lab = loader.load("maze/maze1.txt") # временно создадим позже
|
||
|
|
|
||
|
|
os.system('cls' if os.name == 'nt' else 'clear')
|
||
|
|
print("=" * (lab.width * 2 + 4))
|
||
|
|
print(" ЛАБИРИНТ (загружен)")
|
||
|
|
print("=" * (lab.width * 2 + 4))
|
||
|
|
for y in range(lab.height):
|
||
|
|
print(" ", end='')
|
||
|
|
for x in range(lab.width):
|
||
|
|
t = lab.get_tile(x, y)
|
||
|
|
if t == lab.start_tile:
|
||
|
|
print('S', end=' ')
|
||
|
|
elif t == lab.exit_tile:
|
||
|
|
print('E', end=' ')
|
||
|
|
elif t.wall:
|
||
|
|
print('#', end=' ')
|
||
|
|
else:
|
||
|
|
print('.', end=' ')
|
||
|
|
print()
|
||
|
|
print("=" * (lab.width * 2 + 4))
|