Название: Routineaufgaben mit Python automatisieren
Автор: Al Sweigart
Издательство: Bookwire
Жанр: Математика
isbn: 9783960889571
isbn:
# Conways Spiel des Lebens
import random, time, copy
WIDTH = 60
HEIGHT = 20
Da wir die Funktionen random.randint.(), time.sleep() und copy.deepcopy() benötigen, importieren wir als Erstes die entsprechenden Module.
# Erstellt eine Liste aus Listen für die Zellen
nextCells = []
for x in range(WIDTH):
column = [] # Erstellt eine neue Spalte
for y in range(HEIGHT):
if random.randint(0, 1) == 0:
column.append('#') # Fügt eine lebende Zelle hinzu
else:
column.append(' ') # Fügt eine tote Zelle hinzu
nextCells.append(column) # nextCells ist eine Liste aus Spaltenlisten
Der erste Schritt unseres zellulären Automaten ist völlig willkürlich. Wir müssen eine Liste aus Listen erstellen, in denen wir die Strings '#' und ' ' zur Darstellung lebender und toter Zellen speichern, wobei die Position dieser Strings in den Listen die Position der entsprechenden Zellen auf dem Bildschirm bestimmt. Die inneren Listen stehen jeweils für eine Zellenspalte. Mit random.randint(0, 1) sorgen wir dafür, dass jede Zelle zu Anfang mit gleicher Wahrscheinlichkeit lebendig oder tot sein kann.
Diese Liste aus Listen stellen wir in die Variable nextCells, da der erste Schritt in der Hauptschleife des Programms darin besteht, nextCells in currentCells zu kopieren. In unserer Liste aus Listen wird die x-Koordinate bei 0 beginnend von links nach rechts gezählt und die y-Koordinate von oben nach unten. Daher entspricht nextCells[0][0] der Zelle in der oberen linken Ecke, nextCells[1][0] der Zelle rechts daneben und nextCells[0][1] der Zelle darunter.
while True: # Hauptschleife des Programms
print('\n\n\n\n\n') # Trennt die einzelnen Schritte durch Zeilenumbrüche
currentCells = copy.deepcopy(nextCells)
Jede Iteration der Hauptschleife bildet einen Schritt des zellulären Automaten. Dabei kopieren wir jeweils nextCells in currentCells, geben currentCells auf dem Bildschirm aus und berechnen dann anhand der Zellen in currentCells die Zellen in nextCells.
# Gibt currentCells auf dem Bildschirm aus
for y in range(HEIGHT):
for x in range(WIDTH):
print(currentCells[x][y], end='') # Gibt # oder Leerzeichen aus
print() # Gibt am Zeilenende einen Zeilenumbruch aus
Mit diesen verschachtelten for-Schleifen geben wir jeweils eine komplette Zeilenreihe auf dem Bildschirm aus, gefolgt von einem Zeilenumbruch am Ende. Dieser Vorgang wird für jede Zeile in currentCells wiederholt.
# Berechnet die Zellen des nächsten Schritts anhand der aktuellen Zellen
for x in range(WIDTH):
for y in range(HEIGHT):
# Ruft die Koordinaten der Nachbarn ab
# Durch % WIDTH liegt leftCoord immer zwischen 0 und WIDTH - 1
leftCoord = (x - 1) % WIDTH
rightCoord = (x + 1) % WIDTH
aboveCoord = (y - 1) % HEIGHT
belowCoord = (y + 1) % HEIGHT
Als Nächstes brauchen wir zwei verschachtelte for-Schleifen, um die einzelnen Zellen für den nächsten Schritt zu berechnen. Ob eine Zelle lebendig oder tot ist, hängt von ihren Nachbarn ab, weshalb wir als Erstes die Indizes der Zellen links, rechts, über und unter der aktuellen x- und y-Koordinate bestimmen müssen.
Mit dem Modulo-Operator % können wir auch den Umlauf an den Rändern berücksichtigen. Die äußerste linke Spalte hat den Index 0, der linke Nachbar einer Zelle in dieser Spalte hat also rein rechnerisch den Index 0 - 1 oder -1. Um stattdessen auf den Index der äußersten rechten Spalte zu kommen, nämlich 59, rechnen wir (0 - 1) % WIDTH. Da WIDTH den Wert 60 hat, wird dieser Ausdruck zu 59 ausgewertet. Diese Umlauftechnik mit dem Modulo-Operator funktioniert ebenso auch für die rechten, oberen und unteren Nachbarn.
# Zählt die lebenden Nachbarn
numNeighbors = 0
if currentCells[leftCoord][aboveCoord] == '#':
numNeighbors += 1 # Nachbarzelle oben links lebt
if currentCells[x][aboveCoord] == '#':
numNeighbors += 1 # Nachbarzelle oben lebt
if currentCells[rightCoord][aboveCoord] == '#':
numNeighbors += 1 # Nachbarzelle oben rechts lebt
if currentCells[leftCoord][y] == '#':
numNeighbors += 1 # Nachbarzelle links lebt
if currentCells[rightCoord][y] == '#':
numNeighbors += 1 # Nachbarzelle rechts lebt
if currentCells[leftCoord][belowCoord] == '#':
numNeighbors += 1 # Nachbarzelle unten links lebt
if currentCells[x][belowCoord] == '#':
numNeighbors += 1 # Nachbarzelle unten lebt
if currentCells[rightCoord][belowCoord] == '#':
numNeighbors += 1 # Nachbarzelle unten rechts lebt
Um zu bestimmen, ob die Zelle in nextCells[x][y] lebendig oder tot sein soll, müssen wir die lebenden Nachbarzellen von currentCells[x][y] zählen. Die vorstehende Folge von if-Anweisung prüft jeden der acht Nachbarn der Zelle und addiert für jeden lebenden 1 zu numNeighbors.
# Bestimmt Zellenzustand nach den Regeln
if currentCells[x][y] == '#' and (numNeighbors == 2 or
numNeighbors == 3):
# Lebende Zelle mit 2 oder 3 lebenden Nachbarn lebt weiter
nextCells[x][y] = '#'
elif currentCells[x][y] == ' ' and numNeighbors == 3:
# Tote Zelle mit 3 Nachbarn wird lebendig
nextCells[x][y] = '#'
else:
# Alle anderen Zellen sterben oder bleiben tot
nextCells[x][y] СКАЧАТЬ