Benutzer-Werkzeuge

Webseiten-Werkzeuge


ws1920:dokumentierter_code_finale_version

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ws1920:dokumentierter_code_finale_version [2020/03/18 17:31]
hannariegel
ws1920:dokumentierter_code_finale_version [2020/03/26 22:50] (aktuell)
Labo neuste Version
Zeile 1: Zeile 1:
 Das Programm besteht aus zwei Dateien: Das Programm besteht aus zwei Dateien:
  
-  * 1. die Klassendatei ​GameOfLife.py+  * 1. die GameOfLife.py ​Datei
   * 2. die Ausführungsdatei   * 2. die Ausführungsdatei
  
-In der ersten sind das Game of life und seine Regeln implementiert (sie sollte ​GameOfLife.py heißen) und die zweite greift darauf zu und erstellt eine Animation mit der man interagieren kann.+In der ersten sind das Game of life und seine Regeln implementiert (sie sollte ​gameoflife.py heißen) und die zweite greift darauf zu und erstellt eine Animation mit der man interagieren kann.
  
  
  
-GameOfLife.py:+gameoflife.py:
  
 <​code>​ <​code>​
Zeile 14: Zeile 14:
 import numpy as np import numpy as np
 import matplotlib.pyplot as plt import matplotlib.pyplot as plt
-from PIL import Image 
-from math import floor, ceil 
 import time import time
  
-#in dieser Datei sind die benoetigten Funktionen definiert, um das Game of Life zu starten +class GameOfLife(object):​ 
-#zum Verstaendnis sollte man mit dem Game Of Life vertraut sein aber die Grundlagen sind: 0=tot und 1=lebend+    """​  
 +    Diese Klasse beschreibt einen Zustand eines Game of Lifes und stellt Funktionen dazu bereit. ​
  
 +    Attribute:
 +        zustand: der aktuelle Zustand des Game of Life
 +        groesse: die Seitenlänge des Spielfeldes
 +        tem: die Tripleeinheitsmatrix,​ die zur Berechnung benötigt wird
 +    """​
  
-#​Zusammengefassung des Codes: +    def __init__(selfzustand): 
-#wenn Initialisiere() aufgerufen wirdlegt der/die Benutzer/in die Feldgroesse (bis jetzt immer quadratisch+        """​ 
-#und die Anfangskonfiguration festhierbei ist aus 5 moeglichen Modi zu waehlen(s.u.)+        Erzeugt ein neues GameOfLife-Objekt.
  
-#Um die GameOfLife Update Regel anzuwenden werden in Schritt() die Anzahl der Nachbarn einer jeden Zelle  +        Parameter: 
-#und daraus ​der jeweils naechste ​Zustand(1 oder 0) berechnet+            ​zustand: ​der initiale ​Zustand 
 +        """​ 
 +        self.zustand = zustand 
 +        self.groesse = zustand.shape[0
 +        self.generiereTripleeinheitsmatrix()
  
-#Zum Aufsummieren der Nachbarn multipliziert man die vorher mit Tripleeinheitsmatrix(z,​s) erstellte Tridiagonalmatrix von beiden Seiten  +    def generiereTripleeinheitsmatrix(self):​ 
-#an die Matrix, in der die Zustaende der zellen gespeichert sind (einmal um die horizontalen und einmal um die vertikalen Partner zu addieren) +        self.tem = np.zeros((self.groesse,​ self.groesse)) 
-#als gleichung sieht das ungefaehr so aus:(tem steht hier fuer die tridiagonalmatrix) +        for i in range(0, self.groesse):​ 
-#​anzahlnachbarn = tem*Zustand*tem +            for j in range(0, self.groesse):​ 
-#mit diesen zwei Matrixmultiplikationen kann man sehr recheneffektiv die 9 nachbarn(zelle selbst mitgezaehlt) +                if i == j: 
-#aller Zellen gleichzeitig aufsummieren und dabei haben wir auch noch direkt etwas ueber lineare Algebra gelernt!+                    self.tem[(i,​j)] = 1 
 +                else: 
 +                    self.tem[(i,​j)] = 0 
 +                     
 +        for i in range(0, self.groesse):​ 
 +            for j in range(0, self.groesse):​ 
 +                if i == (j + 1): 
 +                    self.tem[(i,​j)] = 1 
 +        for i in range(0, self.groesse):​ 
 +            for j in range(0, self.groesse):​ 
 +                if j == (i + 1): 
 +                    self.tem[(i,​j)] = 1 
 +                     
 +        self.tem[0, self.tem.shape[1] - 1] = 1 
 +        self.tem[self.tem.shape[1] - 1, 0] = 1 
 +                     
 +    def berechneAnzahlNachbarn(self):​ 
 +        ​# Zum Aufsummieren der Nachbarn multipliziert man die vorher mit Tripleeinheitsmatrix(z,​s) erstellte Tridiagonalmatrix von beiden Seiten  
 +        # an die Matrix, in der die Zustaende der zellen gespeichert sind (einmal um die horizontalen und einmal um die vertikalen Partner zu addieren) 
 +        # als gleichung sieht das ungefaehr so aus:(tem steht hier fuer die tridiagonalmatrix) 
 +        # anzahlnachbarn = tem*Zustand*tem 
 +        # mit diesen zwei Matrixmultiplikationen kann man sehr recheneffektiv die 9 nachbarn(zelle selbst mitgezaehlt) 
 +        # aller Zellen gleichzeitig aufsummieren und dabei haben wir auch noch direkt etwas ueber lineare Algebra gelernt! 
 +        z = np.dot(self.tem,​ self.zustand) ​       
 +        k = np.dot(z, self.tem) 
 +        anzahlNachbarn = k - self.zustand 
 +             
 +        return anzahlNachbarn
  
-#der neue Zustand ​wird dann einfach abhaengig von der anzahl der nachbarn, entsprechend der regeln des game of life bestimmt+    def schritt(self):​ 
 +        """​ Führt einen Berechnungsschritt aus und gibt den neuen Zustand ​zurück. """​ 
 +        anzahlNachbarn = self.berechneAnzahlNachbarn()
  
-#die 5 Konfigurationsmodi sind: +        ​berechne neuen Zustand
-#​1.zufaellig:​ hier wird jede Zelle zufaellig einen wert 1 oder 0 bekommen +
-#​2.alternierend:​ hier wird das Feld in abwechselnd 1- und 0-Spalten eingeteilt, mit einem kleinen Fehler in der Mitte +
-#3.Datei: hier kann direkt eine Konfiguration eingelesen werden. z.B. um eine gleiterkanone oder Aehnliches einzulesen +
-#4.Bild: eine Bilddatei kann eingelesen und in eine annaehernd erkennbare anfangskonfiguration umgewandelt werden (da der kontrast zu schwarzweiss und die groesse geaendert wird)  +
-#5.Leer: hier wird das Feld mit Nullen gefuellt+
  
-#da das Programm nur mit quadratischen Zustandsmatrizen funktioniert,​ wird bei Modi und 4 die MachQuadrat(pixel) Funktion angewandt +        ​Ursprungszelle Tod + genau lebende Nachbarn ​lebend 
- +        ​# Ursprungszelle Lebend + genau lebenden Nachbarn ​tot 
-def Tripleeinheitsmatrix(zeilen,​spalten):​ +        ​# Ursprungszelle Lebend ​2 o. 3 Nachbarn ​lebend 
-    tem np.zeros ((zeilen,​spalten)) +        ​# Ursprungszelle lebend ​4 oder mehr Nachbarn ​tot
-    for i in range(0, zeilen): +
-        ​for j in range(0, spalten): +
-            if i==j: +
-                tem[(i,j)] = 1 +
-            else: +
-                tem[(i,​j)] ​+
-                 +
-    for i in range(0, zeilen): +
-        ​for j in range(0, spalten): +
-            if i==(j+1): +
-                tem[(i,​j)] ​+
-    for i in range(0, zeilen): +
-        ​for j in range(0, spalten): +
-            if j==(i+1): +
-                tem[(i,j)] = 1 +
-                 +
-    tem[0,​tem.shape[1]-1] = 1 +
-    tem[tem.shape[1]-1,​0] = 1 +
-            +
-    return tem +
-                 +
-def BerechneAnzahlNachbarn(zustand):​ +
-    z = np.dot(tem, zustand) ​       +
-    k = np.dot(z, tem) +
-    anzahlNachbarn ​k - zustand+
         ​         ​
-    return ​anzahlNachbarn+        for i in range(0, self.groesse):​ 
 +            for j in range(0, self.groesse):​ 
 +                if self.zustand[(i,​j)] == 1 and (anzahlNachbarn[(i,j)] in range(2) or anzahlNachbarn[(i,​j)] in range(4,​9)):​ 
 +                    self.zustand[(i,​j)] = 0 
 +                elif self.zustand[(i,​j)] == 0 and anzahlNachbarn[(i,​j)] == 3: 
 +                    self.zustand[(i,​j)] = 1 
 +                         
 +        return self.zustand 
 +</​code>​
  
-def BerechneNeuenZustand(zustandanzahlNachbarn): + 
-    ​#​Ursprungszelle Tod + genau 3 lebende Nachbarn = lebend +Die Animationsdatei ​(anzeige.py):​ 
-    ​#​Ursprungszelle Lebend + genau 1 lebenden Nachbarn = tot + 
-    ​#​Ursprungszelle Lebend + 2 o. 3 Nachbarn = lebend +<​code>​ 
-    ​#​Ursprungszelle lebend + 4 oder mehr Nachbarn = tot+from gameoflife import GameOfLife 
 +import numpy as np 
 +from matplotlib import pyplot as plt 
 +from matplotlib import animation 
 +import matplotlib.pyplot as plt 
 +from PIL import Image 
 +from math import floorceil 
 + 
 +class Anzeige(object): 
 +    ​"""​ 
 +    ​Diese Klasse animiert ein GameOfLife-Objekt mithilfe der matplotlib. 
 + 
 +    ​Attribute:​ 
 +        gol: das GameOfLife-Objekt,​ das animiert wird 
 +        canvas: der matplotlib-Canvas,​ auf den gezeichnet wird 
 +        im: die aktuell angezeigte Bitmap 
 +        zellAlter: speichert für jede Zelle, für wie viele Generationen sie schon lebendig ist 
 +        animationLaeuft:​ gibt an, ob die Animation läuft (also nicht pausiert ist) 
 +        benutzerZeichnet:​ gibt an, ob der Benutzer gerade auf den Canvas zeichnet 
 +        anim: das matplotlib-Animationsobjekt 
 +    ​"""​
     ​     ​
-    ​for i in range(0zeilen): +    ​# unterschiedliche colourmaps ​(weil ein buntes Lebenlebenswerter ist
-        for j in range(0, spalten): +    # diese werden zufaellig aufgerufen 
-            if zustand[(i,​j)] ​== 1 and (anzahlNachbarn[(i,j)] in range(2) or anzahlNachbarn[(i,j)] in range(4,9)): +    ​colormaps ​= ['​Accent'​'​Accent_r'​'​Blues'​'​Blues_r'​'​BrBG'​'​BrBG_r'​'​BuGn'​'​BuGn_r',​ '​BuPu',​ '​BuPu_r',​ '​CMRmap',​ '​CMRmap_r',​ '​Dark2',​ '​Dark2_r',​ '​GnBu',​ '​GnBu_r',​ '​Greens',​ '​Greens_r',​ '​Greys',​ '​Greys_r',​ '​OrRd',​ '​OrRd_r',​ '​Oranges',​ '​Oranges_r',​ '​PRGn',​ '​PRGn_r',​ '​Paired',​ '​Paired_r',​ '​Pastel1',​ '​Pastel1_r',​ '​Pastel2',​ '​Pastel2_r',​ '​PiYG',​ '​PiYG_r',​ '​PuBu',​ '​PuBuGn',​ '​PuBuGn_r',​ '​PuBu_r',​ '​PuOr',​ '​PuOr_r',​ '​PuRd',​ '​PuRd_r',​ '​Purples',​ '​Purples_r',​ '​RdBu',​ '​RdBu_r',​ '​RdGy',​ '​RdGy_r',​ '​RdPu',​ '​RdPu_r',​ '​RdYlBu',​ '​RdYlBu_r',​ '​RdYlGn',​ '​RdYlGn_r',​ '​Reds',​ '​Reds_r',​ '​Set1',​ '​Set1_r',​ '​Set2',​ '​Set2_r',​ '​Set3',​ '​Set3_r',​ '​Spectral',​ '​Spectral_r',​ '​Wistia',​ '​Wistia_r',​ '​YlGn',​ '​YlGnBu',​ '​YlGnBu_r',​ '​YlGn_r',​ '​YlOrBr',​ '​YlOrBr_r',​ '​YlOrRd',​ '​YlOrRd_r',​ '​afmhot',​ '​afmhot_r',​ '​autumn',​ '​autumn_r',​ '​binary',​ '​binary_r',​ '​bone',​ '​bone_r',​ '​brg',​ '​brg_r',​ '​bwr',​ '​bwr_r',​ '​cividis',​ '​cividis_r',​ '​cool',​ '​cool_r',​ '​coolwarm',​ '​coolwarm_r',​ '​copper',​ '​copper_r',​ '​cubehelix',​ '​cubehelix_r',​ '​flag',​ '​flag_r',​ '​gist_earth',​ '​gist_earth_r',​ '​gist_gray',​ '​gist_gray_r',​ '​gist_heat',​ '​gist_heat_r',​ '​gist_ncar',​ '​gist_ncar_r',​ '​gist_rainbow',​ '​gist_rainbow_r',​ '​gist_stern',​ '​gist_stern_r',​ '​gist_yarg',​ '​gist_yarg_r',​ '​gnuplot',​ '​gnuplot2',​ '​gnuplot2_r',​ '​gnuplot_r',​ '​gray',​ '​gray_r',​ '​hot',​ '​hot_r',​ '​hsv',​ '​hsv_r',​ '​inferno',​ '​inferno_r',​ '​jet',​ '​jet_r',​ '​magma',​ '​magma_r',​ '​nipy_spectral',​ '​nipy_spectral_r',​ '​ocean',​ '​ocean_r',​ '​pink',​ '​pink_r',​ '​plasma',​ '​plasma_r',​ '​prism',​ '​prism_r',​ '​rainbow',​ '​rainbow_r',​ '​seismic',​ '​seismic_r',​ '​spring',​ '​spring_r',​ '​summer',​ '​summer_r',​ '​tab10',​ '​tab10_r',​ '​tab20',​ '​tab20_r',​ '​tab20b',​ '​tab20b_r',​ '​tab20c',​ '​tab20c_r',​ '​terrain',​ '​terrain_r',​ '​twilight',​ '​twilight_r',​ '​twilight_shifted',​ '​twilight_shifted_r',​ '​viridis',​ '​viridis_r',​ '​winter',​ '​winter_r'​]
-                zustand[(i,j)]=0 +
-            elif zustand[(i,j)] == 0 and anzahlNachbarn[(i,j)]==3: +
-                zustand[(i,j)]=1 +
-                     +
-    return zustand+
  
-def Schritt(): +    ​def __init__(selfgol): 
-    global zustand +        """​ 
-    anzahlNachbarn = BerechneAnzahlNachbarn(zustand) +        ​Erzeugt ein neues Anzeige-Objekt und beginnt die Animation.
-    ergebnis = BerechneNeuenZustand(zustandanzahlNachbarn) +
-    return ergebnis +
-                 +
-def Wiederhole(t): +
-    for i in range(t): +
-        ​Schritt()+
  
-def MachQuadrat(pixel)+        Parameter
-    ​breite = pixel.shape[0] +            gol: das GamoOfLife-Objekt 
-    hoehe = pixel.shape[1] +        """​ 
-    size max(breite, hoehe)+        self.gol gol
  
-    links floor((size - breite) / 2+        fig plt.figure() 
-    ​rechts ​ceil((size - breite) / 2) +        ​self.canvas ​fig.canvas 
-    oben = floor((size - hoehe) / 2) +        ​plt.axis('​off'​)
-    unten = ceil((size - hoehe) / 2)+
  
-    pad_width ​= ((linksrechts), (oben, unten)) +        #so wird bei jedem ausfuehren eine zufaellige colormap gewaehlt um ein angenehmeres,​ vielseitiges Langzeiterlebnis zu kreieren 
-    ​pixel ​= np.pad(pixel, pad_width, mode='​constant',​ constant_values=0+        self.im ​plt.imshow(self.gol.zustandanimated=Truecmap=plt.get_cmap(Anzeige.colormaps[int(np.random.random()*len(Anzeige.colormaps))])) 
-    ​return pixel+        ​self.zellAlter ​= np.zeros(self.gol.zustand.shape
 +        ​self.zeichne(self.gol.zustand)
  
-def Initialisiere():+        #Verbinden, der interaktionsevents mit dem figure, in dem die animation laeuft 
 +        self.canvas.mpl_connect('​key_press_event',​ self.onPress) 
 +        self.canvas.mpl_connect('​button_press_event',​ self.onClick) 
 +        self.canvas.mpl_connect('​button_release_event',​ self.onClickEnd) 
 +        self.canvas.mpl_connect('​motion_notify_event',​ self.onMove)
  
-    global zustand, tem, zeilen, spalten, cmap+        self.animationLaeuft = True 
 +        self.benutzerZeichnet = False
  
-    modus  ​int(input('Gib den Modus 1 (Zufall)2 (alternierend)3 (Datei), 4 (Bildoder 5 (Leerein '))+        #die tatsaechliche Ausfuehrung:​ 
 +        self.anim ​animation.FuncAnimation(figself.animationsschrittinterval=200) 
 +        plt.show() 
 +     
 +    def animationsschritt(self, e): 
 +        ​'''​ Führt einen Animationsschritt durch. '''​ 
 +        self.gol.schritt() 
 +        self.zeichne(self.gol.zustand) 
 +        return self.im,
  
-    ​if modus==1 or modus==2 or modus==5+    ​def zeichne(self,​ zustand)
-        ​spalten = zeilen = int(input('Gib die Anzahl der Zeilen/​Spalten ein: '))+        '''​ Zeichnet den angegebenen Zustand auf den matplotlib-Canvas. '''​ 
 +        # enthaelt Werte ueber die 'Lebensdauer'​ einer Zelle 
 +        self.zellAlter = self.zellAlter * zustand + zustand 
 +        # lebende Zellen aendern ihre Farbe, je laenger sie leben 
 +        self.im.set_array(np.ones(self.zellAlter.shape- np.power(0.5,​ self.zellAlter)) 
 +        self.canvas.draw()
  
-    if modus==1: +    ​#die vier folgenden Funktionen sind zum Interagieren mit dem Geschehen 
-        zustand = np.round(np.random.random((zeilen,spalten))).astype(int)+    def onPress(self,​ event): 
 +        # zum Pausieren mit der Leertaste 
 +        if event.key == ' ': 
 +            if self.animationLaeuft:​ 
 +                self.anim.event_source.stop() 
 +                self.animationLaeuft = False 
 +            else: 
 +                self.anim.event_source.start() 
 +                self.animationLaeuft = True 
 + 
 +    def onClick(self,​ event): 
 +        # mit dem Cursor kann man den Wert einer Zelle per Klick aendern von lebend zu tot, sowie andersherum 
 +        if event.button == 1 and event.xdata != None and event.ydata != None: 
 +            self.benutzerZeichnet = True 
 +            self.anim.event_source.stop() 
 +            self.zustandNeu = np.copy(self.gol.zustand) 
 +            pos_x = int(np.round(event.xdata)) 
 +            pos_y = int(np.round(event.ydata)) 
 +            self.zustandNeu[pos_y,​ pos_x] = 1 - self.gol.zustand[pos_y,​ pos_x] 
 +            self.zellAlter = np.zeros(self.zustandNeu.shape) 
 +            self.zeichne(self.zustandNeu) 
 +             
 +    def onMove(self,​ event): 
 +        # mit dem Cursor kann man den Wert mehrerer Zellen per Klick aendern, indem man die Maustaste gedrueckt haelt 
 +        # die Animation wird hierfuer pausiert 
 +        if event.button == 1 and self.benutzerZeichnet and event.xdata != None and event.ydata != None: 
 +            pos_x = int(np.round(event.xdata)) 
 +            pos_y = int(np.round(event.ydata)) 
 +            self.zustandNeu[pos_y,​ pos_x] = 1 - self.gol.zustand[pos_y,​ pos_x] 
 +            self.zellAlter = np.zeros(self.zustandNeu.shape) 
 +            self.zeichne(self.zustandNeu) 
 + 
 +    def onClickEnd(self,​ event): 
 +        # beim loslassen der Maustaste werden die geänderten Werte an die Animation gegeben und diese wird fortgesetzt 
 +        if event.button == 1 and self.benutzerZeichnet:​ 
 +            self.gol.zustand = self.zustandNeu 
 +            self.zellAlter = np.zeros(self.zustandNeu.shape) 
 +            self.zeichne(self.zustandNeu) 
 +            self.benutzerZeichnet = False 
 +            if self.animationLaeuft:​ 
 +                self.anim.event_source.start() 
 + 
 +###### Programmeinstieg ####### 
 + 
 +def main(): 
 +    # Erzeuge ein GameOfLife-Objekt anhand der Benutzereingaben 
 + 
 +    # die 5 Konfigurationsmodi sind: 
 +    # 1.zufaellig:​ hier wird jede Zelle zufaellig einen wert 1 oder 0 bekommen 
 +    # 2.alternierend:​ hier wird das Feld in abwechselnd 1- und 0-groesse eingeteilt, mit einem kleinen Fehler in der Mitte 
 +    # 3.Datei: hier kann direkt eine Konfiguration eingelesen werden. z.B. um eine gleiterkanone oder Aehnliches einzulesen 
 +    # 4.Bild: eine Bilddatei kann eingelesen und in eine annaehernd erkennbare anfangskonfiguration umgewandelt werden (da der kontrast zu schwarzweiss und die groesse geaendert wird)  
 +    # 5.Leer: hier wird das Feld mit Nullen gefuellt 
 +    modus = int(input('​Gib den Modus 1 (Zufall), 2 (alternierend),​ 3 (Datei) oder 4 (Bild) ein:  ')) 
 + 
 +    ​if modus == 1 or modus == 2 or modus == 5: 
 +        groesse = int(input('​Gib die Anzahl der Zeilen/​Spalten ein: ')) 
 + 
 +    if modus == 1: 
 +        # Zufall 
 +        zustand = np.round(np.random.random((groessegroesse))).astype(int)
     ​     ​
-    elif modus==2: +    elif modus == 2: 
-        zustand=np.zeros((zeilen,spalten)) +        # Alternierend 
-        for i in range(0,zeilen): +        zustand = np.zeros((groessegroesse)) 
-            for j in range (0,spalten):+        for i in range(0, ​groesse): 
 +            for j in range (0, groesse):
                 if j%2==0:                 if j%2==0:
                     zustand[(i,​j)]=0                     zustand[(i,​j)]=0
Zeile 137: Zeile 240:
                     zustand[(i,​j)]=1                     zustand[(i,​j)]=1
     ​     ​
-        if zustand[(int(zeilen/2),int(spalten/2))]==0: +        if zustand[(int(groesse/2), int(groesse/2))] == 0: 
-            zustand[(int(zeilen/2),int(spalten/2))]=1 +            zustand[(int(groesse/2), int(groesse/2))] = 1 
-            zustand[(int((zeilen/2)+1),int(spalten/2))]=1+            zustand[(int((groesse/2)+1), int(groesse/2))] = 1
             ​             ​
         else:         else:
-            zustand[(int(zeilen/2),int(spalten/2))]=0 +            zustand[(int(groesse/2), int(groesse/2))] = 0 
-            zustand[(int((zeilen/2)+1),int(spalten/2))]=0+            zustand[(int((groesse/2)+1), int(groesse/2))] = 0
     ​     ​
-    elif modus==3: +    elif modus == 3: 
-        ​DateiName ​= input('​was willste oeffnen? ') +        ​# Datei lesen 
-        ​Datei = open(DateiName)+        dateiName ​= input('​Was willste oeffnen? ') 
 +        ​datei = open(dateiName)
     ​     ​
-        ​DateiAlsListe ​= [] +        ​dateiAlsListe ​= [] 
-        for line in Datei+        for line in datei
-            ​DateiAlsListe.append([int(c) for c in list(line.rstrip())]) +            ​dateiAlsListe.append([int(c) for c in list(line.rstrip())]) 
-        ​DateiAlsMatrix ​= np.array(DateiAlsListe)+        ​dateiAlsMatrix ​= np.array(dateiAlsListe)
         ​         ​
-        zustand = MachQuadrat(DateiAlsMatrix) +        zustand = machQuadrat(dateiAlsMatrix)
-        zeilen = spalten = zustand.shape[0]+
         ​         ​
-    elif modus==4:+    elif modus == 4: 
 +        # Bild lesen
         dateiname = input('​Gib den Bildpfad ein: ')         dateiname = input('​Gib den Bildpfad ein: ')
         bild = Image.open(dateiname)         bild = Image.open(dateiname)
Zeile 165: Zeile 269:
         pixel = np.array(bild)         pixel = np.array(bild)
  
-        zustand = MachQuadrat(pixel) +        zustand = machQuadrat(pixel)
-        zeilen = spalten = zustand.shape[0]+
     ​     ​
-    ​elif modus==5: +    ​# erzeuge GameOfLife-Objekt 
-        ​zustand ​np.zeros((zeilen,​spalten)).astype(int)+    ​gol ​GameOfLife(zustand)
  
-    ​tem = Tripleeinheitsmatrix(zeilen, spalten)+    ​# initialisiere Anzeige 
 +    Anzeige(gol)
  
-</​code>​+def machQuadrat(pixel):​ 
 +    """​ Macht das angegebene zweidimensionale Numpy-Array quadratisch,​ indem es die Ränder mit Nullen auffüllt. """​ 
 +    breite = pixel.shape[0] 
 +    hoehe = pixel.shape[1] 
 +    size = max(breite, hoehe)
  
 +    links = floor((size - breite) / 2)
 +    rechts = ceil((size - breite) / 2)
 +    oben = floor((size - hoehe) / 2)
 +    unten = ceil((size - hoehe) / 2)
  
-Die Animationsdatei:​+    pad_width = ((links, rechts), (oben, unten)) 
 +    pixel = np.pad(pixel,​ pad_width, mode='​constant',​ constant_values=0) 
 +    return pixel
  
-<​code>​ +main()
-import GameOfLife as gol +
-import numpy as np +
-from matplotlib import pyplot as plt +
-from matplotlib import animation +
- +
-# in dieser Datei, wird die Animation der 'Game of Life' - Schritte ausgeführt  +
-# die vorletzte Zeile mit Funcanimation bildet das Grundgeruest,​ der Rest des Codes ist groesstenteils Vorbereitung +
-# und die Funktionen zum Interagieren +
- +
- +
-# unterschiedliche colourmaps (weil ein buntes Leben, lebenswerter ist) +
-# diese werden zufaellig aufgerufen +
-colormaps = ['​Accent',​ '​Accent_r',​ '​Blues',​ '​Blues_r',​ '​BrBG',​ '​BrBG_r',​ '​BuGn',​ '​BuGn_r',​ '​BuPu',​ '​BuPu_r',​ '​CMRmap',​ '​CMRmap_r',​ '​Dark2',​ '​Dark2_r',​ '​GnBu',​ '​GnBu_r',​ '​Greens',​ '​Greens_r',​ '​Greys',​ '​Greys_r',​ '​OrRd',​ '​OrRd_r',​ '​Oranges',​ '​Oranges_r',​ '​PRGn',​ '​PRGn_r',​ '​Paired',​ '​Paired_r',​ '​Pastel1',​ '​Pastel1_r',​ '​Pastel2',​ '​Pastel2_r',​ '​PiYG',​ '​PiYG_r',​ '​PuBu',​ '​PuBuGn',​ '​PuBuGn_r',​ '​PuBu_r',​ '​PuOr',​ '​PuOr_r',​ '​PuRd',​ '​PuRd_r',​ '​Purples',​ '​Purples_r',​ '​RdBu',​ '​RdBu_r',​ '​RdGy',​ '​RdGy_r',​ '​RdPu',​ '​RdPu_r',​ '​RdYlBu',​ '​RdYlBu_r',​ '​RdYlGn',​ '​RdYlGn_r',​ '​Reds',​ '​Reds_r',​ '​Set1',​ '​Set1_r',​ '​Set2',​ '​Set2_r',​ '​Set3',​ '​Set3_r',​ '​Spectral',​ '​Spectral_r',​ '​Wistia',​ '​Wistia_r',​ '​YlGn',​ '​YlGnBu',​ '​YlGnBu_r',​ '​YlGn_r',​ '​YlOrBr',​ '​YlOrBr_r',​ '​YlOrRd',​ '​YlOrRd_r',​ '​afmhot',​ '​afmhot_r',​ '​autumn',​ '​autumn_r',​ '​binary',​ '​binary_r',​ '​bone',​ '​bone_r',​ '​brg',​ '​brg_r',​ '​bwr',​ '​bwr_r',​ '​cividis',​ '​cividis_r',​ '​cool',​ '​cool_r',​ '​coolwarm',​ '​coolwarm_r',​ '​copper',​ '​copper_r',​ '​cubehelix',​ '​cubehelix_r',​ '​flag',​ '​flag_r',​ '​gist_earth',​ '​gist_earth_r',​ '​gist_gray',​ '​gist_gray_r',​ '​gist_heat',​ '​gist_heat_r',​ '​gist_ncar',​ '​gist_ncar_r',​ '​gist_rainbow',​ '​gist_rainbow_r',​ '​gist_stern',​ '​gist_stern_r',​ '​gist_yarg',​ '​gist_yarg_r',​ '​gnuplot',​ '​gnuplot2',​ '​gnuplot2_r',​ '​gnuplot_r',​ '​gray',​ '​gray_r',​ '​hot',​ '​hot_r',​ '​hsv',​ '​hsv_r',​ '​inferno',​ '​inferno_r',​ '​jet',​ '​jet_r',​ '​magma',​ '​magma_r',​ '​nipy_spectral',​ '​nipy_spectral_r',​ '​ocean',​ '​ocean_r',​ '​pink',​ '​pink_r',​ '​plasma',​ '​plasma_r',​ '​prism',​ '​prism_r',​ '​rainbow',​ '​rainbow_r',​ '​seismic',​ '​seismic_r',​ '​spring',​ '​spring_r',​ '​summer',​ '​summer_r',​ '​tab10',​ '​tab10_r',​ '​tab20',​ '​tab20_r',​ '​tab20b',​ '​tab20b_r',​ '​tab20c',​ '​tab20c_r',​ '​terrain',​ '​terrain_r',​ '​twilight',​ '​twilight_r',​ '​twilight_shifted',​ '​twilight_shifted_r',​ '​viridis',​ '​viridis_r',​ '​winter',​ '​winter_r'​] +
- +
- +
-def animate(e):​ +
-    '''​ die Funktion, die von Funcanimation ausgefuehrt wird  +
-     +
-    wie gol.Schritt funktioniert ist in der Klassendatei beschrieben '''​ +
-    gol.Schritt() +
-    draw(gol.zustand) +
-    return im, +
- +
-gol.Initialisiere() +
-fig = plt.figure() +
- +
-def draw(zustand):​ +
-    '''​ lebende Zellen aendern ihre Farbe, je laenger sie leben '''​ +
- +
-    global cmap #enthaelt Werte ueber die '​Lebensdauer'​ einer Zelle +
-    cmap = cmap * zustand + zustand +
-    im.set_array(np.ones(cmap.shape) - np.power(0.5,​ cmap)) +
-    fig.canvas.draw() +
- +
-zustand_neu = None +
-anim_running = True +
-drawing = False +
- +
-#die vier folgenden Funktionen sind zum Interagieren mit dem Geschehen +
-def onPress(event):​ +
-    '''​ zum Pausieren mit der Leertaste '''​ +
-    global anim_running ​    +
-    if event.key=='​ ': +
-        if anim_running:​ +
-            anim.event_source.stop() +
-            anim_running = False +
-        else: +
-            anim.event_source.start() +
-            anim_running = True +
- +
- +
-def onClick(event):​ +
-    '''​ mit dem Cursor kann man den Wert einer Zelle per Klick aendern +
-  +
-    von lebend zu tot, sowie andersherum '''​ +
-    global cmap, zustand_neu,​ drawing +
-    if event.button == 1 and event.xdata != None and event.ydata != None: +
-        drawing = True +
-        anim.event_source.stop() +
-        zustand_neu = np.copy(gol.zustand) +
-        pos_x = int(np.round(event.xdata)) +
-        pos_y = int(np.round(event.ydata)) +
-        zustand_neu[pos_y,​ pos_x] = 1 - gol.zustand[pos_y,​ pos_x] +
-        cmap = np.zeros(zustand_neu.shape) +
-        draw(zustand_neu) +
-         +
-def onMove(event):​ +
-    '''​ mit dem Cursor kann man den Wert mehrerer Zellen per Klick aendern, indem man die Maustaste gedrueckt haelt +
-   die Animation wird hierfuer pausiert'''​ +
-    global zustand_neu,​ cmap +
-    if event.button == 1 and drawing and event.xdata != None and event.ydata != None: +
-        pos_x = int(np.round(event.xdata)) +
-        pos_y = int(np.round(event.ydata)) +
-        zustand_neu[pos_y,​ pos_x] = 1 - gol.zustand[pos_y,​ pos_x] +
-        cmap = np.zeros(zustand_neu.shape) +
-        draw(zustand_neu) +
- +
-def onClickEnd(event):​ +
-    '''​ beim loslassen der Maustaste werden die geänderten Werte an die Animation gegeben und diese wird fortgesetzt '''​ +
-    global zustand_neu,​ cmap, drawing +
-    if event.button == 1 and drawing: +
-        gol.zustand = zustand_neu +
-        cmap = np.zeros(zustand_neu.shape) +
-        draw(zustand_neu) +
-        drawing = False +
-        if anim_running:​ +
-            anim.event_source.start() +
-               +
-plt.axis('​off'​) +
- +
-#so wird bei jedem ausfuehren eine zufaellige colormap gewaehlt um ein angenehmeres,​ vielseitiges Langzeiterlebnis zu kreieren +
-im = plt.imshow(gol.zustand,​ animated=True,​ cmap=plt.get_cmap(colormaps[int(np.random.random()*len(colormaps))])) +
-cmap = np.zeros(gol.zustand.shape) +
-draw(gol.zustand) +
- +
-#Verbinden, der interaktionsevents mit dem figure, in dem die animation laeuft +
-fig.canvas.mpl_connect('​key_press_event',​ onPress) +
-fig.canvas.mpl_connect('​button_press_event',​ onClick) +
-fig.canvas.mpl_connect('​button_release_event',​ onClickEnd) +
-fig.canvas.mpl_connect('​motion_notify_event',​ onMove) +
- +
-#die tatsaechliche Ausfuehrung:​ +
-anim = animation.FuncAnimation(fig,​ animate, interval=200) +
-plt.show()+
 </​code>​ </​code>​
- 
- 
- 
ws1920/dokumentierter_code_finale_version.1584549088.txt.gz · Zuletzt geändert: 2020/03/18 17:31 von hannariegel