Files
maturaarbeit/src/net.py

94 lines
2.8 KiB
Python

"""
Kernlogik des Spiels
"""
from random import choice
from src.interface import parse_description
from src.netTypes import Piece, Direction, Coordinate
DEMO_FIELD = parse_description("5x5:c7634887c213e5b8db3e69282")
class Grid:
pieces: list[list[Piece]]
width: int
height: int
def __init__(self, width: int, height: int) -> None:
self.height = height
self.width = width
if width != height or width not in [5, 7, 9, 11, 13]:
raise ValueError("Feldgrösse nicht erlaubt")
with open(f"descriptions/{width}x{height}.txt") as f:
lines = f.readlines()
selected = choice(lines).strip()
self.pieces = parse_description(selected)
def neighbors(self, x: int, y: int) -> list[Coordinate]:
neighbors: list[Coordinate] = []
for dx, dy in ((-1, 0), (1, 0), (0, -1), (0, 1)):
if (
x + dx < 0
or x + dx >= self.width
or y + dy < 0
or y + dy >= self.height
):
continue
neighbors.append((x + dx, y + dy))
return neighbors
def solved(self) -> bool:
connected = [([False] * self.height) for _ in range(self.width)]
connected = self._solve_floodfill(0, 0, connected)
return all(map(lambda x: all(x), connected))
def _solve_floodfill(
self, x: int, y: int, connected: list[list[bool]]
) -> list[list[bool]]:
connected[x][y] = True
connected_neighbors: list[Coordinate] = []
for nx, ny in self.neighbors(x, y):
dx = x - nx
dy = y - ny
if (
Direction.from_offset(dx, dy)
in self.pieces[nx][ny].connected_directions()
and Direction.from_offset(-dx, -dy)
in self.pieces[x][y].connected_directions()
):
connected_neighbors.append((nx, ny))
for nx, ny in connected_neighbors:
if connected[nx][ny]:
continue
connected = self._solve_floodfill(nx, ny, connected)
return connected
class NetGame:
_grid: Grid
def __init__(self, width: int, height: int) -> None:
self._grid = Grid(width, height)
def get_field(self) -> list[list[Piece]]:
return self._grid.pieces
def get_piece(self, x: int, y: int) -> Piece:
return self._grid.pieces[x][y]
def turn_cw(self, x: int, y: int) -> None:
self._grid.pieces[x][y].turn_cw()
def turn_ccw(self, x: int, y: int) -> None:
self._grid.pieces[x][y].turn_ccw()
def lock(self, x: int, y: int) -> None:
self._grid.pieces[x][y].locked = not self._grid.pieces[x][y].locked
def solved(self):
return self._grid.solved()