lehrkraefte:snr:informatik:glf21:python:chaos-game

Das Chaos-Spiel geht wie folgt:

Seien $A$, $B$, $C$ die Ecken eines gleichseitigen Dreiecks auf der Tafel.

Wähle zufällig einen weiteren Punkt $P$. Wir lassen diesen Punkt „springen“, indem wir die folgenden Anweisungen unendlich oft wiederholen:

  1. Wähle zufällig einen der Eckpunkte $A$, $B$, $C$, etwa mit Hilfe eines Würfels:
    • $A$ falls der Würfel 1 oder 2 zeigt;
    • $B$ falls er 3 oder 4 zeigt;
    • $C$ falls er 5 oder 6 zeigt.
  2. Der „neue“ Punkt $P$ sei der Mittelpunkt zwischen dem „alten“ Punkt $P$ und dem erwürfelten Eckpunkt.
  3. Markiere diesen neuen Punkt $P$.

Kannst Du erraten, welche geometrische Figur herauskommt?

Eine solche Folge von Handlungsanweisungen nennt man einen Algorithmus. Jedes Kochrezept oder jede Bastelanleitung oder jede Spielanleitung ist ein Beispiel für einen Algorithmus.

Das folgende Python-Programm ist eine Implementierung des Chaos-Spiel-Algorithmus - wir sagen dem Computer also mit Hilfe der Programmiersprache Python in präziser, computerverständlicher Form, was er tun soll.

Ob es heutzutage bereits KI-Systeme (KI = Künstliche Intelligeny) gibt, die sprachliche Anweisungen wie oben direkt „verstehen“ und ausführen können, ist mir nicht bekannt.

Lies das Python-Programm (auf dem eigenen Rechner) und versuche, es zu verstehen!

Wer noch kein Python kann, wird beim ersten Lesen nichts oder nur wenig verstehen - der Sinn ist aber, dass ihr ähnlich wie beim äusserst effektiven frühkindlichen Erlernen der Muttersprache nun einer neuen Programmiersprache in einer nicht-trivialen Situation ausgesetzt werdet und durch Nachfragen und Erklärungen meinerseits mit der Zeit ein gewisses Verständnis entwickelt.

# Sierpinski-Dreieck per Chaos-Spiel
 
from gpanel import *
from random import * 
 
breite = 10000
hoehe = 8660
 
makeGPanel("Sierpinski triangle chaos game", 0, breite, 0, hoehe)
 
# Koordinaten des Punkts A
xA = 0
yA = 0
 
# Koordinaten des Punkts B
xB = breite
yB = 0
 
# Koordinaten des Punkts C
xC = int(breite / 2)
yC = hoehe
 
# Zum Ändern der Dicke des Stifts bzw. für "dickere" Pixel:
# lineWidth(2)
 
line (xA, yA, xB, yB)
line (xB, yB, xC, yC)
line (xC, yC, xA, yA)
 
# zufaellige Startkoordinaten des springenden Punktes
x = randint(0, breite)
y = randint(0, hoehe)
 
point(int(x), int(y))
 
iterationen = 1000000
 
for i in range(0, iterationen):
    zufall = randint(1, 3)
    if zufall == 1:
        x = (x + xA) / 2
        y = (y + yA) / 2
    if zufall == 2:
        x = (x + xB) / 2
        y = (y + yB) / 2
    if zufall == 3: 
        x = (x + xC) / 2        
        y = (y + yC) / 2
 
    point(int(x), int(y))
 
print(iterationen, "Iterationen durchgeführt.")

Click to display ⇲

Click to hide ⇱

# Sierpinski-Dreieck per Chaos-Spiel
# Alle Zeilen, die mit dem Hash- oder Doppelkreuz-Symbol # beginnen, sind Kommentare
# und werden vom Computer beim Ausführen des Programms ignoriert.
# Leerzeilen dienen nur der besseren Strukturierung und werden ebenfalls vom Computer ignoriert.
 
# Import von Grafik- und Zufallsbefehlen (bitte ignorieren)
from gpanel import *
from random import * 
 
# Es folgen zwei Zuweisungen, kodiert durch das Gleichheitszeichen "=":
# Wir weisen der Variablen "breite" den Wert 10000 rechts des Gleichheitszeichens zu.
# Das Gleichheitszeichen ist NICHT als mathematische Gleichheit zu verstehen. 
# Es handelt sich um eine Zuweisung! (Dies wird weiter unten klarer.)
# (Wir werden die Variable "breite" im Programm nicht ändern - es handelt sich also genauer um eine Konstante.)
# Analog wird die Variable/Konstante "hoehe" auf 8660 gesetzt.
breite = 10000
hoehe = 8660
 
# Der folgende Befehl "makeGPanel" erzeugt ein Fenster mit einem rechteckigem Ausschnitt der Zeichenebene.
# Genauer wird der Bereich mit x-Koordinaten von 0 bis "breite" und
# y-Koordinaten von 0 bis "hoehe" bereitgestellt.
# Jedes Pixel (= jeder Bildpunkt) mit ganzzahligen Koordinaten in diesem Bereich kann später gefärbt werden.
# In der Titelleiste des Fensters erscheint die Zeichenkette (englisch string)
# "Sierpinski triangle chaos game".
# Der englische Begriff "panel" bedeutet "Tafel".
makeGPanel("Sierpinski triangle chaos game", 0, breite, 0, hoehe)
 
# Wir haben die Variable "hoehe" so gewählt, dass ein gleichseitiges Dreieck
# mit horizontaler Grundseite genau in unseren Zeichenbereich passt:
# Die Höhe eines gleichseitigen Dreiecks mit Grundseite 1 ist nach
# Pythagoras gerade Quadratwurzel(3)/2. Etwas komplizierter hätten wir oben
# hoehe = int(sqrt(3)/2 * breite)
# schreiben können: Die Funktion "sqrt" fuer englisch "square root" berechnet die Quadratwurzel.
# Die Funktion "int" wandelt eine Gleitkommazahl (also eine Zahl mit endlich vielen Nachkommastellen)
# durch Abschneiden der Nachkommastellen in eine ganze Zahl (engl. integer) um.
 
# Koordinaten des Punkts A
xA = 0
yA = 0
 
# Koordinaten des Punkts B
xB = breite
yB = 0
 
# Koordinaten des Punkts C
xC = int(breite / 2)
yC = hoehe
# Die Funktion "int" ist oben erklärt.
 
# Zum Ändern der Dicke des Stifts bzw. für "dickere" Pixel:
# lineWidth(2)
 
# Zeichnet gerade Linien zwischen den angegebenen Punkten
line (xA, yA, xB, yB)
line (xB, yB, xC, yC)
line (xC, yC, xA, yA)
 
# zufaellige Startkoordinaten des springenden Punktes
x = randint(0, breite)
y = randint(0, hoehe)
 
# Markiere das Pixel mit Koordinaten (x,y) oder genauer (int(x), int(y)). 
# Die Funktion "point" nimmt zwei ganze Zahlen als Argumente und zeigt das Pixel mit den entsprechenden
# Koordinaten in der aktuellen Zeichenfarbe (schwarz) an. 
point(int(x), int(y))
 
# Anzahl der Iterationen. Eigentlich ist es guter Programmierstil, Konstanten, die man beim Testen 
# eventuell rasch ändern muss, am Anfang zu definieren. 
iterationen = 1000000
 
# Es folgt eine sogenannte "for-Schleife" (englisch "for loop").
# Die Variable i nimmt nacheinander die Werte 0, 1, 2, ..., iterationen - 1 an.
# Beachte, dass der Wert iterationen nicht angenommen wird.
# (Hierbei ist iterationen - 1 unser Ersatz für unendlich.)
# Für jeden dieser Werte wird der nachfolgende eingerückte Bereich (Einrückung jeweis vier Leerzeichen)
# genau einmal durchlaufen.
# ACHTUNG: Falsche Einrückungen verursachen Fehler.
for i in range(0, iterationen):
 
    # Weise der Variablen "zufall" eine Zufallszahl zu, die den Wert 1,2 oder 3 hat.
    # Wir wuerfeln sozusagen mit einem dreiseitigen Wuerfel. Dabei sind alle Zahlen 1, 2, 3 gleich wahrscheinlich.
    zufall = randint(1, 3)
 
    # Es folgt eine sogenannte "if-Bedingung" (englisch "if condition"): 
    # Falls die Variable "zufall" den Wert 1 hat (Gleichheit von Variablen wird mit "==" und nicht mit "=" abgefragt),
    # werden die folgenden eingerueckten Zeilen durchgeführt.
    if zufall == 1:
 
        # Die neue x-Koordinate unseres springenden Punktes liegt genau zwischen der alten x-Koordinate
        # des springenden Punktes und der x-Koordinate von A.
        # Hier wird nun klar, dass "=" eine Zuweisung ist und kein Gleichheitszeichen:
        # Der Variablen x links wird als neuem Wert das zugewiesen,
        # was die Berechnung rechts ergibt - in dieser Berechnung wird der alte Wert von x verwendet.
        x = (x + xA) / 2
 
        # Analog fuer die neue y-Koordinate
        y = (y + yA) / 2
 
        # Hier endet der eingerückte Befehlsblock, der ausgefuehrt wird, wenn zufall == 1 gilt.
 
    # Die beiden folgenden if-Bedingungen sind nun hoffentlich klar.
    if zufall == 2:
        x = (x + xB) / 2
        y = (y + yB) / 2
    if zufall == 3: 
        x = (x + xC) / 2        
        y = (y + yC) / 2
 
    point(int(x), int(y))
 
#    Die folgenden Zeilen auskommentieren, wenn man will, dass das Programm anfangs langsamer durchgefuehrt wird:
#    Beispielsweise macht "delay(42)" macht eine Pause von 42 Millisekunden.
#
#    if i < 1000:
#        delay (10)
#    if i < 10000:
#        delay (1)
#    if i == 0: 
#        print("lange Pausen")
#    if i == 1000: 
#        print("kurze Pausen")
#    if i == 10000: 
#        print("keine Pausen")    
 
# Hier endet die for-Schleife, denn der folgende Befehl ist nicht mehr eingerueckt.
 
# Gib aus, wie viele Punkte gezeichnet wurden.
print(iterationen, "Iterationen durchgeführt.")

Bringe Tigerjython auf deinem Rechner zum Laufen.

Richte das Browser-Fenster links ein und das Tigerjython-Fenster rechts, so dass sie jeweils die halbe Bildschirmbreite einnehmen - dies ermöglicht effektives Arbeiten.

Kopiere das obige Programm in das Tigerjython-Fenster! (Sind Ctrl-c, Ctrl-v zum Kopieren und Alt+Tab zum Fensterwechsel bekannt? Kann zum Kopieren auch den Clipboard-Icon rechts oben in der Code-Box nutzen.)

Bringe es mit dem Button (= Knopf) mit dem grünen Dreieck in der Menüleiste zum Laufen:

Lerne Tigerjython kennen: Schau alle Menüpunkte an, lass den Mauszeiger über den Buttons schweben (= let the mouse hover over the buttons).

Wer selbst etwas experimentieren und das Programm verändern möchte, findet Anregungen auf Wikipedia - Chaos game. Dort ist auch ein Link auf das Sierpiński-Dreieck - so heisst die Figur, die unser Chaos-Spiel produziert hat.

Wer mag, darf natürlich auch gerne die Einführung Tigerjython anschauen. Dort ist auch erklärt, wie man Tigerjython auf dem eigenen Rechner installiert. Wer kann es auf dem iPad installieren?

  • lehrkraefte/snr/informatik/glf21/python/chaos-game.txt
  • Last modified: 2021/09/15 17:26
  • by Olaf Schnürer