Skip to content

Commit

Permalink
Реализован код
Browse files Browse the repository at this point in the history
  • Loading branch information
Anr1st committed Jan 25, 2025
1 parent 3b77ade commit fc12904
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 38 deletions.
53 changes: 42 additions & 11 deletions homework04/life.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pygame
from pygame.locals import *
from pygame.locals import QUIT

Cell = tp.Tuple[int, int]
Cells = tp.List[int]
Expand All @@ -29,46 +30,76 @@ def __init__(
self.generations = 1

def create_grid(self, randomize: bool = False) -> Grid:
# Copy from previous assignment
pass
return [[random.randint(0, 1) if randomize else 0 for _ in range(self.cols)] for _ in range(self.rows)]

def get_neighbours(self, cell: Cell) -> Cells:
# Copy from previous assignment
pass
row, col = cell
neighbors = []
for i in range(max(0, row - 1), min(self.rows, row + 2)):
for j in range(max(0, col - 1), min(self.cols, col + 2)):
if (i, j) != (row, col):
neighbors.append(self.curr_generation[i][j])
return neighbors

def get_next_generation(self) -> Grid:
# Copy from previous assignment
pass
new_grid = [[0] * self.cols for _ in range(self.rows)]
for i in range(self.rows):
for j in range(self.cols):
neib_cells = self.get_neighbours((i, j))
alive_neibs = sum(neib_cells)
if self.curr_generation[i][j] == 0 and alive_neibs == 3:
new_grid[i][j] = 1
elif self.curr_generation[i][j] == 1:
if 2 <= alive_neibs <= 3:
new_grid[i][j] = 1
return new_grid

def step(self) -> None:
"""
Выполнить один шаг игры.
"""
pass
if not self.is_max_generations_exceeded:
self.prev_generation = self.curr_generation
self.curr_generation = self.get_next_generation()
if self.is_changing:
self.generations += 1
else:
pygame.quit()

@property
def is_max_generations_exceeded(self) -> bool:
"""
Не превысило ли текущее число поколений максимально допустимое.
"""
pass
return self.max_generations is not None and self.generations >= self.max_generations

@property
def is_changing(self) -> bool:
"""
Изменилось ли состояние клеток с предыдущего шага.
"""
pass
return self.prev_generation != self.curr_generation

@staticmethod
def from_file(filename: pathlib.Path) -> "GameOfLife":
"""
Прочитать состояние клеток из указанного файла.
"""
pass
grid = []
with filename.open() as f:
for line in f:
line = line.strip()
if line:
row = [int(char) for char in line]
grid.append(row)
game = GameOfLife((len(grid), len(grid[0])))
game.curr_generation = grid
return game

def save(self, filename: pathlib.Path) -> None:
"""
Сохранить текущее состояние клеток в указанный файл.
"""
pass
with filename.open("w") as f:
for row in self.curr_generation:
f.write("".join(map(str, row)) + "\n")
53 changes: 47 additions & 6 deletions homework04/life_console.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import curses

import pygame

from life import GameOfLife
from ui import UI

Expand All @@ -9,14 +11,53 @@ def __init__(self, life: GameOfLife) -> None:
super().__init__(life)

def draw_borders(self, screen) -> None:
""" Отобразить рамку. """
pass
"""Отобразить рамку."""
screen.border(0)

def draw_grid(self, screen) -> None:
""" Отобразить состояние клеток. """
pass
"""Отобразить состояние клеток."""
height, width = screen.getmaxyx()
for i, row in enumerate(self.life.curr_generation):
for j, cell in enumerate(row):
if 0 < i < height - 1 and 0 < j < width - 1:
char = "0" if cell else " "
screen.addch(i, j, char)

def run(self) -> None:
screen = curses.initscr()
# PUT YOUR CODE HERE
curses.endwin()
curses.curs_set(0)
screen.nodelay(True)
screen.timeout(100)

curses.start_color()
curses.init_pair(1, curses.COLOR_MAGENTA, curses.COLOR_BLACK)

running = True
try:
while running:
screen.clear()
self.draw_borders(screen)
self.draw_grid(screen)
height, _ = screen.getmaxyx()
screen.addstr(
height - 1,
0,
f"Press [q] to quit | Generation: {self.life.generations}",
curses.color_pair(1) | curses.A_BOLD,
)
screen.refresh()

self.life.step()

key = screen.getch()
if key == ord("q"): # Press 'q' to exit
running = False
break
finally:
curses.endwin()
running = False

if __name__ == "__main__":
life = GameOfLife((24, 80), max_generations=50)
ui = Console(life)
ui.run()
70 changes: 63 additions & 7 deletions homework04/life_gui.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,77 @@
import pygame
from life import GameOfLife
from pygame.constants import K_SPACE, KEYDOWN, MOUSEBUTTONDOWN, QUIT, K_q
from pygame.locals import *

from life import GameOfLife
from ui import UI


class GUI(UI):
def __init__(self, life: GameOfLife, cell_size: int = 10, speed: int = 10) -> None:
super().__init__(life)
self.cell_size = cell_size
self.speed = speed
self.running = True
self.paused = False
self.width = life.cols * cell_size
self.height = life.rows * cell_size
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption("Game of Life")

def draw_lines(self) -> None:
# Copy from previous assignment
pass
for x in range(0, self.width, self.cell_size):
pygame.draw.line(self.screen, pygame.Color("gray"), (x, 0), (x, self.height))
for y in range(0, self.height, self.cell_size):
pygame.draw.line(self.screen, pygame.Color("gray"), (0, y), (self.width, y))

def draw_grid(self) -> None:
# Copy from previous assignment
pass
for i, row in enumerate(self.life.curr_generation):
for j, cell in enumerate(row):
color = pygame.Color("green") if cell else pygame.Color("white")
pygame.draw.rect(
self.screen, color, (j * self.cell_size, i * self.cell_size, self.cell_size, self.cell_size)
)

def run(self) -> None:
# Copy from previous assignment
pass
pygame.init()
clock = pygame.time.Clock()
self.screen.fill(pygame.Color("white"))
self.life.curr_generation = self.life.create_grid(randomize=True)
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key == K_SPACE: # Пауза по пробелу
self.paused = not self.paused
elif event.key == K_q: # Выход по клавише 'q'
running = False
if event.type == MOUSEBUTTONDOWN:
if event.button == 1 and self.paused:
x, y = event.pos
# ячейка, внутри которой был клик
x //= self.cell_size
y //= self.cell_size
self.life.curr_generation[y][x] = not self.life.curr_generation[y][x]
self.draw_grid()
self.draw_lines()
pygame.display.flip()

if not self.paused:
self.life.step() # Выполнение шага игры, если не на паузе

self.draw_lines()
self.draw_grid()
if self.life.is_max_generations_exceeded or not self.life.is_changing:
running = False

pygame.display.flip()
clock.tick(self.speed)

pygame.quit()

if __name__ == "__main__":
life = GameOfLife((30, 30))
game = GUI(life)
game.run()
79 changes: 65 additions & 14 deletions homework04/life_proto.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
import typing as tp

import pygame
from pygame.locals import *
from pygame.locals import QUIT

Cell = tp.Tuple[int, int]
Cells = tp.List[int]
Grid = tp.List[Cells]


class GameOfLife:
def __init__(
self, width: int = 640, height: int = 480, cell_size: int = 10, speed: int = 10
) -> None:
def __init__(self, width: int = 640, height: int = 480, cell_size: int = 10, speed: int = 10) -> None:
self.width = width
self.height = height
self.cell_size = cell_size
Expand All @@ -30,21 +28,21 @@ def __init__(
self.speed = speed

def draw_lines(self) -> None:
""" Отрисовать сетку """
"""Отрисовать сетку"""
for x in range(0, self.width, self.cell_size):
pygame.draw.line(self.screen, pygame.Color("black"), (x, 0), (x, self.height))
for y in range(0, self.height, self.cell_size):
pygame.draw.line(self.screen, pygame.Color("black"), (0, y), (self.width, y))

def run(self) -> None:
""" Запустить игру """
"""Запустить игру"""
pygame.init()
clock = pygame.time.Clock()
pygame.display.set_caption("Game of Life")
self.screen.fill(pygame.Color("white"))

# Создание списка клеток
# PUT YOUR CODE HERE
self.grid = self.create_grid(randomize=True)

running = True
while running:
Expand All @@ -53,9 +51,19 @@ def run(self) -> None:
running = False
self.draw_lines()

# Отрисовка списка клеток
# Выполнение одного шага игры (обновление состояния ячеек)
# PUT YOUR CODE HERE
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
self.draw_lines()

# Отрисовка списка клеток
self.draw_grid()
self.draw_lines()

# Выполнение одного шага игры (обновление состояния ячеек)
self.grid = self.get_next_generation()

pygame.display.flip()
clock.tick(self.speed)
Expand All @@ -79,13 +87,33 @@ def create_grid(self, randomize: bool = False) -> Grid:
out : Grid
Матрица клеток размером `cell_height` х `cell_width`.
"""
pass
grid = []
for _ in range(self.cell_height):
row = []
for _ in range(self.cell_width):
if randomize:
row.append(random.randint(0, 1))
else:
row.append(0)
grid.append(row)
return grid

def draw_grid(self) -> None:
"""
Отрисовка списка клеток с закрашиванием их в соответствующе цвета.
"""
pass
for i, row in enumerate(self.grid):
for j, val in enumerate(row):
if val == 1:
for x in range(i * self.cell_size, (i + 1) * self.cell_size):
pygame.draw.line(
self.screen, pygame.Color("green"), (j * self.cell_size, x), ((j + 1) * self.cell_size, x)
)
else:
for x in range(i * self.cell_size, (i + 1) * self.cell_size + 1):
pygame.draw.line(
self.screen, pygame.Color("white"), (j * self.cell_size, x), ((j + 1) * self.cell_size, x)
)

def get_neighbours(self, cell: Cell) -> Cells:
"""
Expand All @@ -105,7 +133,13 @@ def get_neighbours(self, cell: Cell) -> Cells:
out : Cells
Список соседних клеток.
"""
pass
row, col = cell
neighbors = []
for i in range(max(0, row - 1), min(self.cell_height, row + 2)):
for j in range(max(0, col - 1), min(self.cell_width, col + 2)):
if (i, j) != (row, col):
neighbors.append(self.grid[i][j])
return neighbors

def get_next_generation(self) -> Grid:
"""
Expand All @@ -116,4 +150,21 @@ def get_next_generation(self) -> Grid:
out : Grid
Новое поколение клеток.
"""
pass
next_generation = self.create_grid()
for i, row in enumerate(next_generation):
for j, _ in enumerate(row):
neighbours = self.get_neighbours((i, j))
sum_neigh = sum(neighbours)
if self.grid[i][j] == 1:
if sum_neigh == 2 or sum_neigh == 3:
next_generation[i][j] = 1
else:
next_generation[i][j] = 0
else:
if sum_neigh == 3:
next_generation[i][j] = 1
return next_generation

if __name__ == "__main__":
game = GameOfLife(480, 640, 10)
game.run()

0 comments on commit fc12904

Please sign in to comment.