Routineaufgaben mit Python automatisieren. Al Sweigart
Чтение книги онлайн.

Читать онлайн книгу Routineaufgaben mit Python automatisieren - Al Sweigart страница 58

Название: Routineaufgaben mit Python automatisieren

Автор: Al Sweigart

Издательство: Bookwire

Жанр: Математика

Серия:

isbn: 9783960889571

isbn:

СКАЧАТЬ wir uns diesen Code nun Zeile für Zeile an:

      # 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] СКАЧАТЬ