#!/usr/bin/env python3
"""Conway's Game of Life.
Implementacja Gry w Życie Conwaya w Pythonie z użyciem Pygame i NumPy.
"""
import numpy as np
import pygame
# Stałe
WIDTH = 800
HEIGHT = 600
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 200, 0)
CELL_SIZE = 10
GRID_WIDTH = WIDTH // CELL_SIZE
GRID_HEIGHT = HEIGHT // CELL_SIZE
DEFAULT_FPS = 10
def create_random_grid() -> np.ndarray:
"""Tworzy losową siatkę złożoną z 0 i 1."""
rng = np.random.default_rng()
return rng.integers(0, 2, size=(GRID_HEIGHT, GRID_WIDTH), dtype=np.int8)
def create_empty_grid() -> np.ndarray:
"""Tworzy pustą siatkę złożoną z 0."""
return np.zeros(
(GRID_HEIGHT, GRID_WIDTH),
dtype=np.int8,
)
def get_next_generation(grid: np.ndarray) -> np.ndarray:
"""Oblicza następne pokolenie Gry w Życie."""
new_grid: np.ndarray = np.copy(grid)
for r in range(GRID_HEIGHT):
for c in range(GRID_WIDTH):
# Użyj max i min do obliczenia granic sąsiedztwa
r_start = max(0, r - 1)
r_end = min(GRID_HEIGHT, r + 2)
c_start = max(0, c - 1)
c_end = min(GRID_WIDTH, c + 2)
# Policz żywych sąsiadów
live_neighbors = np.sum(grid[r_start:r_end, c_start:c_end]) - grid[r, c]
# Zastosuj reguły Gry w Życie
if grid[r, c]: # Komórka żywa
if live_neighbors not in (2, 3):
new_grid[r, c] = 0 # Umiera
elif live_neighbors == 3: # Komórka martwa
new_grid[r, c] = 1 # Ożywa
return new_grid
def draw_grid(screen: pygame.Surface, grid: np.ndarray) -> None:
"""Rysuje siatkę na ekranie Pygame."""
pass
def game_event_loop() -> None:
"""Obsługuje główną pętlę gry, w tym zdarzenia, aktualizacje i rysowanie."""
paused = True
running = True
clock: pygame.time.Clock = pygame.time.Clock()
current_grid: np.ndarray = create_random_grid()
fps = DEFAULT_FPS
screen = pygame.display.set_mode((WIDTH, HEIGHT))
while running:
pass
def main() -> None:
"""Główna funkcja uruchamiająca Grę w Życie."""
pygame.init()
pygame.display.set_caption("Conway's Game of Life")
game_event_loop()
pygame.quit()
if __name__ == "__main__":
main()
Gra w Życie
Conway’s Game of Life to symulacja automatu komórkowego, w której stan każdej komórki w siatce ewoluuje w czasie na podstawie prostych reguł dotyczących jej sąsiadów.
Zasady Gry
Gra toczy się na dwuwymiarowej siatce komórek, z których każda może być w jednym z dwóch stanów:
- Żywa (oznaczona kolorem zielonym w implementacji)
- Martwa (oznaczona kolorem czarnym w implementacji)
Stan komórki w następnej generacji zależy od stanu jej ośmiu sąsiadów w obecnej generacji, zgodnie z następującymi regułami:
- Martwa komórka z dokładnie trzema żywymi sąsiadami staje się żywa (narodziny).
- Żywa komórka z mniej niż dwoma żywymi sąsiadami umiera z powodu niedoludnienia.
- Żywa komórka z dwoma lub trzema żywymi sąsiadami pozostaje żywa.
- Żywa komórka z więcej niż trzema żywymi sąsiadami umiera z powodu przeludnienia.
Zadanie
Twoim zadaniem jest uzupełnienie kodu symulacji Game of Life. Poniżej znajduje się szkielet kodu, który musisz wypełnić.
- Uzupełnij funkcję
draw_grid
, rysując na ekranie siatkę komórek z odpowiednimi kolorami (zielony dla komórek żywych, czarny dla martwych). - Uzupełnij brakującą część pętli
while
wgame_event_loop
tak aby gra wyświetlała kolejne generacje oraz reagowała na zdarzenia użytkownika. - Dodatkowe wyzwanie: Zaimplementuj różne początkowe wzory (np. Glider, Gosper glider gun).
- Dodatkowe wyzwanie: Dodaj kontrolę prędkości symulacji. Zaimplementuj możliwość przewijania generacji.
Przykładowe sterowanie
Spacja
: Wznawia/wstrzymuje symulację.R
: Resetuje siatkę do losowego układu.C
: Czyści siatkę (wszystkie komórki martwe).Lewy Przycisk Myszy
: Kliknięcie komórki przełącza jej stan (żywa/martwa), ale tylko gdy symulacja jest wstrzymana.
Przydatne zasoby:
Przygotowanie środowiska
Dla tego zadania będziesz potrzebować zainstalować Pygame i NumPy. Możesz to zrobić za pomocą poleceń: