Lösungen
Lösungen#
import random
import celluloid as cld
import matplotlib.pyplot as plt
class Cell:
def __init__(self, row_pos, col_pos):
"""Zellen-Attribute festlegen"""
# Zeilen-Position der Zelle auf Grid
self.row_pos = row_pos
# Spalten-Position der Zelle auf Grid
self.col_pos = col_pos
# Lebendigkeits-Status der Zelle (1="lebend", 2="tot"). Wird anfangs zufällig festgelegt.
self.status = random.randint(0, 1)
# Lebendigkeits-Status der Zelle im nächsten Zeitschritt. (999="noch unbestimmt")
self.next_status = 999
# Liste, in welche alle Nachbarzellen eingespeichert werden
self.neighbor_cells = []
def find_neighbor_cells(self, grid):
"""Sucht alle 8 Nachbarn der Zelle auf Grid und speichert diese im Cell-Attribut 'neighbor_cells'."""
# Anzahl der Zeilen und Spalten des Grids herausfinden
n_rows = len(grid)
n_cols = len(grid[0])
# Zeilenposition überhalb, eigene Zeilenposition und die Zeilenposition unterhalb durchgehen
for row_deviation in [-1, 0, 1]:
# Spaltenposition links, eigene Spaltenposition und die Spaltenposition rechts durchgehen
for col_deviation in [-1, 0, 1]:
# Zeilenposition und Spaltenposition der Nachbarzelle berechnen
neighbor_row = (self.row_pos + row_deviation) % n_rows
neighbor_col = (self.col_pos + col_deviation) % n_cols
# Nachbarzelle auswählen
neighbor_cell = grid[neighbor_row][neighbor_col]
# Wenn es eine Nachbarzelle ist und nicht man selbst
if neighbor_cell != self:
# als Nachbarzelle einspeichern
self.neighbor_cells.append(neighbor_cell)
def set_next_status(self):
"""Prüft, wie viele Nachbarzellen lebendig sind und
leitet daraus für sich selbst den nächsten Lebendigkeitsstatus ab."""
# Zählvariable für die Anzahl der lebendigen Nachbarzellen
n_alive = 0
# Alle Nachbarzellen durchgehen
for neighbor_cell in self.neighbor_cells:
# Zählvariable erhöhen, wenn lebendig (0="tot", 1="lebendig")
n_alive += neighbor_cell.status
# Nächsten Lebendigkeitsstatus ableiten:
# Wenn man selbst lebendig ist
if self.status == 1:
# wenn 2 oder 3 Nachbarzellen lebendig sind
if n_alive == 2 or n_alive == 3:
# lebendig bleiben
self.next_status = 1
# ansonsten
else:
# sterben
self.next_status = 0
# wenn man selbst tot ist
else:
# wenn man 3 lebendige Nachbarzellen hat
if n_alive == 3:
# lebendig werden
self.next_status = 1
# ansonsten
else:
# tot bleiben
self.next_status = 0
def update_status(self):
"""Ersetzt den aktuellen Lebendigkeitsstatus durch den nächsten Lebendigkeitsstatus."""
if self.next_status != 999:
self.status = self.next_status
self.next_status = 999
def create_grid(n_rows, n_cols):
"""Erstellt ein Grid als geschachtelte Liste, welche Cell-Objekte enthält.
Zudem wird für jede Zelle die Nachbarschaft herausgesucht und eingespeichert."""
# Geschachtelte Liste erstellen und Cell-Objekte einfügen
grid = []
for i in range(n_rows):
row = []
for j in range(n_cols):
cell = Cell(row_pos=i, col_pos=j)
row.append(cell)
grid.append(row)
# Nachbarzellen finden und einspeichern
for row in grid:
for cell in row:
cell.find_neighbor_cells(grid)
return grid
def create_color_matrix(grid):
"""
Erstellt ein grafisch darstellbares Abbild des Grids, wobei der Lebendigkeitsstatus der Zellen farblich kodiert werden.
Eine tote Zelle wird mit der Farbe weiss, eine lebendige Zelle mit der Farbe schwarz kodiert.
"""
color_matrix = []
for row in grid:
color_row = []
for cell in row:
if cell.status == 0:
color = [255, 255, 255]
else:
color = [0, 0, 0]
color_row.append(color)
color_matrix.append(color_row)
return color_matrix
# Matplotlib & Celluloid-Objekte für grafische Darstellung/Animation erstellen
fig, ax = plt.subplots()
camera = cld.Camera(fig)
# Das Grid mit Zellen erstellen - HIER KANN DIE GRÖSZE DES GRIDS EINGESTELLT WERDEN
grid = create_grid(50, 50)
# Simulationsloop
# für jeden Zeitschritt - HIER KANN DIE ZEITLICHE LÄNGE DER SIMULATION EINGESTELLT WERDEN
for tick in range(500):
# Grafische Darstellung
# Grid in farblich darstellbare Matrix übersetzen, diese als Diagramm darstellen und Foto davon schießen
color_matrix = create_color_matrix(grid)
plt.imshow(color_matrix)
camera.snap()
# Synchrone Aktualisierung Schritt 1: Interne Veränderung
# jede Zelle durchgehen und nächsten Lebendigkeitsstatus festlegen
for row in grid:
for cell in row:
cell.set_next_status()
# Synchrone Aktualisierung Schritt 2: Veränderung sichtbar machen
# jede Zelle durchgehen und den nächsten Lebendigkeitsstatus in den aktuellen Lebendigkeitsstatus umwandeln
for row in grid:
for cell in row:
cell.update_status()
# Animation erstellen & speichern
animation = camera.animate()
animation.save("game_of_life_animation.mp4", fps=10, dpi=500)
Bei Ausführung des obigen Codes müsste ein Video namens game_of_life_animation.mp4
auf deinem Computer erscheinen. Dieses sollte ungefähr so aussehen:
from IPython.display import Video
Video("game_of_life_animation.mp4", embed = True, width = 600)