lehrkraefte:snr:informatik:glf23:python:chaos-game-mit-pygame

  • HTML-Seite mit Lieblingslinks zur Home-Seite (oder Start-Seite) machen, falls noch nicht geschehen.
  • Wer hat iPad statt Laptop? alte Schul-Linux-Laptops ausleihbar

Unterrichtsgespräch, Algorithmus umgangssprachlich formulieren, dann gemeinsam in VS Code eintippen in Python (zuerst Verzeichnis öffnen)

Flussdiagramm: Was ist die Ausgabe des hier verlinkten Flussdiagramms?

Zusatzaufgaben:

  • Schreibe ein neues Programm (neue Datei!), das alle geraden Zahlen bis zu einer eingegebenen Zahl ausgibt.
  • … das alle geraden Zahlen rückwärts ausgibt
  • erweitere das Teiler-Programm, so dass es am Ende ausgibt, ob die eingegebene Zahl eine Primzahl ist
  • Schreibe ein neues Programm, das alle Primzahlen bis zu einer eingegebenen Zahl ausgibt.

Spielerisch-chaotische Einführung in Python

1. Installiere Python auf deinem Rechner. Am einfachsten geht dies über den Windows App Store.1) (Man kann die App “Python” starten und dann direkt in der “Python-Shell” Python-Befehle eingeben. Das brauchen wir aber heute nicht.)

2. Versuche, das gemeinsam geschriebene Programm teiler.py zum Laufen zu bringen (mit dem Shortkey Ctrl+F5 oder über das Menü per RunRun without debugging (oder deutsch AusführenAusführen ohne Debugging)).

(eventuell Würfel mitnehmen…)

Das Chaos-Spiel geht wie folgt:

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

Führe nun den folgenden Algorithmus (= Handlungsanweisung) aus:

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$.

chaos-game.py
import pygame
from random import *
 
breite = 500
hoehe = 433                     # ungefähr sqrt(3)/2 * breite;     sqrt = square root = Quadratwurzel
iterationen = 10000
 
weiss = (255, 255, 255)         # Ein Tupel aus drei Zahlen, kodiert die Farbe Weiss im RGB-Modell, das wir später kennenlernen werden.
 
# Koordinaten des Punkts A
xA = 0
yA = hoehe
 
# Koordinaten des Punkts B
xB = breite
yB = hoehe
 
# Koordinaten des Punkts C
xC = int(breite / 2)            # Der Befehl "int" macht eine Kommazahl (= reelle Zahl = real number) durch Abschneiden der Nachkommastellen zu einer ganzen Zahl (= integer).
yC = 0
 
pygame.init()
pygame.display.set_caption("Das Chaos-Spiel")
 
leinwand = pygame.display.set_mode((breite + 1, hoehe + 1))
 
pygame.draw.line(leinwand, weiss, (xA, yA), (xB, yB))
pygame.draw.line(leinwand, weiss, (xB, yB), (xC, yC))
pygame.draw.line(leinwand, weiss, (xC, yC), (xA, yA))
 
pygame.display.update()
 
x = randint(0, breite)
y = randint(0, hoehe)
 
i = 0
while i <= iterationen:
    zufall = randint(1, 3)
    if zufall == 1:
        x = x + 0.5 * (xA - x)
        y = y + 0.5 * (yA - y)
    if zufall == 2:
        x = x + 0.5 * (xB - x)
        y = y + 0.5 * (yB - y)
    if zufall == 3: 
        x = x + 0.5 * (xC - x)
        y = y + 0.5 * (yC - y)
    leinwand.set_at((round(x),round(y)), weiss)               # Zeichnet ein Pixel am Punkt (x,y) bzw. genauer an den gerundeten Koordinaten.
    pygame.display.update((round(x), round(y), 1, 1))
    # denn das ist deutlich schneller als
    # pygame.display.update()
    pygame.time.delay(1)
 
    if i % 1000 == 0:                                        # "Prozent-Division" liefert den Rest der Division.
        print(i)
    i = i + 1
 
print("Fertig! Das Fenster wird in 5 Sekunden geschlossen.") # Ausgabe der Zeichenkette (= string) zwischen den Anführungszeichen.
print(f"Insgesamt wurden {iterationen} Punkte gezeichnet.")  # f-string = formatted string
 
 
pygame.time.delay(5000)                                      # Pause in Millisekunden
pygame.quit()

Programm-Code mit Erklärungen

Programm-Code mit Erklärungen

chaos-game-explained.py
# 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 Pakete/Bibliotheken (packages/libraries) mit Grafik- und Zufallsbefehlen
# (eigentlich ist pygame ein Paket zur Spieleprogrammierung, 
# jedoch eignet es sich auch zum Zeichnen einfacher Grafiken und ich habe nichts "Besseres" gefunden):
import pygame
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 = 500
hoehe = 433                        # ungefähr sqrt(3)/2 * breite;     sqrt = square root = Quadratwurzel
 
# Die folgende Variable gibt an, wie oft wir den Punkt springen lassen.
iterationen = 10000
 
weiss = (255, 255, 255)            # Ein Tupel aus drei Zahlen, kodiert die Farbe Weiss im RGB-Modell, das wir später kennenlernen werden.
 
# Koordinaten des Punkts A
xA = 0
yA = hoehe
 
# Koordinaten des Punkts B
xB = breite
yB = hoehe
 
# Koordinaten des Punkts C
xC = int(breite / 2)               # Der Befehl "int" macht eine Kommazahl (= reelle Zahl = real number) durch Abschneiden der Nachkommastellen zu einer ganzen Zahl (= integer).
yC = 0
 
 
# Die folgenden drei Befehle erzeugen ein Fenster mit dem Titel "Das Chaos-Spiel"
# 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.
# Beachte: Die x-Achse zeigt nach rechts, die y-Achse nach UNTEN!
# 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)
# "Das Chaos-Spiel".
pygame.init()
pygame.display.set_caption("Das Chaos-Spiel")
 
leinwand = pygame.display.set_mode((breite + 1, hoehe + 1))
 
# Zeichne gerade Linien zwischen den angegebenen Punkten (auf der "leinwand" mit Farbe "weiss"):
pygame.draw.line(leinwand, weiss, (xA, yA), (xB, yB))
pygame.draw.line(leinwand, weiss, (xB, yB), (xC, yC))
pygame.draw.line(leinwand, weiss, (xC, yC), (xA, yA))
 
# Die Linien werden zunächst "verborgen" gezeichnet. Um sie wirklich anzuzeigen, muss man
# das Display updaten. (Dies ist so gemacht, um ein Flackern des Bildschirms zu vermeiden.)
pygame.display.update()
 
 
# zufaellige Startkoordinaten des springenden Punktes
# "randint" ist eine Abkürzung für "random integer" = "zufällige ganze Zahl" 
# zwischen den angegebenen Grenzen (jeweils einschliesslich). 
x = randint(0, breite)
y = randint(0, hoehe)
 
 
# 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 die drei 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 + 0.5 * (xA - x)
 
        # Analog fuer die neue y-Koordinate
        y = y + 0.5 * (yA - y)
 
        # 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 + 0.5 * (xB - x)
        y = y + 0.5 * (yB - y)
    if zufall == 3: 
        x = x + 0.5 * (xC - x)
        y = y + 0.5 * (yC - y)
    leinwand.set_at((round(x),round(y)), weiss)               # Zeichnet ein Pixel am Punkt (x,y) bzw. genauer an den gerundeten Koordinaten.
    pygame.display.update((round(x), round(y), 1, 1))
    # Das Updaten eines kleinen rechteckigen Bereichs ist deutlich schneller als das Updaten
    # des gesamten Zeichenbereichs mit
    # pygame.display.update()
    pygame.time.delay(1)
 
    # Alle 1000 Iterationen wird die Variable i ausgegeben.
    if i % 1000 == 0:                                        # "Prozent-Division" liefert den Rest der Division.
        print(i)
 
# Hier endet die for-Schleife, denn der folgende Befehl ist nicht mehr eingerueckt.
 
print("Fertig! Das Fenster wird in 5 Sekunden geschlossen.") # Ausgabe der Zeichenkette (= string) zwischen den Anführungszeichen.
print(f"Insgesamt wurden {iterationen} Punkte gezeichnet.")  # f-string = formatted string
 
 
# Pause von 5000 Millisekunden, also 5 Sekunden
pygame.time.delay(5000)                                      
# Schliesse das Zeichenfenster.
pygame.quit()

1. Speichere das obige Python-Programm chaos-game.py in deinem Verzeichnis C:\Users\Vorname.Nachname\informatik\python (durch Anklicken des Programm-Namens über dem obigen Code mit der RECHTEN Maustaste, Save as/Speichern unter).

2. Öffne das Programm chaos-game.py mit VS-Code (etwa über das Menü per FileOpen File). Versuche, es dort zum Laufen zu bringen (über das Menü per RunRun without debugging (oder deutsch AusführenAusführen ohne Debugging) oder schneller mit dem Shortkey Ctrl+F5). - Vermutlich klappt das nicht: Du musst die Library pygame installieren wie im folgenden 4. Punkt beschrieben (dies ist eine Bibliothek von Befehlen, die das Programmieren von Spielen erleichtern (pygame = python game library); wir verwenden sie, da sie sich auch gut zum Erstellen von Zeichnungen eignet):

3. Öffne die Anwendung/App “Eingabeaufforderung” (= “command prompt” = “Befehlszeile”, auf manchen Schul-Windows-Rechnern muss man “cmd” suchen). Gib dort den Befehl pip install pygame ein, gefolgt von Enter: (pip ist ein Paketverwaltungsprogramm für Python; pip ist ein Akronym für “pip installs packages”, vgl. https://de.wikipedia.org/wiki/Pip_(Python))

(Falls das Probleme macht, vielleicht klappt das Folgende (nicht getestet): Probiere es mit python -m pip install pygame.)

4. Nun solltest du das Programm in VS-Code starten können (so wie im Punkt 3 beschrieben).

Die Figur, die das Chaos-Spiel produziert, heisst Sierpiński-Dreieck. Weitere Infos zum Chaos-Spiel findest du unter Wikipedia - Chaos game.

Installiere die beiden Extensions “Python” und “Pylance” in VS Code wie im Folgenden erklärt (eventuell wurde dir dies bereits von VS Code vorgeschlagen und du hast diese Aufgabe bereits erledigt). Sie erleichtern das Programmieren in Python.

  • In der linken Symbolleiste klicke auf das “Extension”-Icon (zweites von unten):
  • Im “Extensions-Fenster” werden dir vermutlich die beiden Erweiterungen Python und Pylance vorgeschlagen (sonst kannst du im Suchfeld nach ihnen suchen). Installiere sie (vermutlich wird Pylance (und anderes) mit Python gleich mitinstalliert): ,

Erklärung wichtiger Begriffe: Algorithmus, Implementierung, IDE:

  • Eine Folge von Handlungsanweisungen (wie unsere erste Erklärung des Chaos-Spiels oben) nennt man einen Algorithmus2). Jedes Kochrezept oder jede Bastelanleitung oder jede Spielanleitung ist ein Beispiel für einen Algorithmus.
  • Das oben angegebene 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.
  • Computerprogramme schreibt man in Editoren. Meist verwendet man Editoren, die das Programmieren sinnvoll unterstützen. Solche Editoren heissen Entwicklungsumgebungen (= integrierte Entwicklungsumgebungen = integrated development environment, kurz IDE). Wir arbeiten mit der IDE “Visual Studio Code”. In ihr kann man Python-Programm direkt ausführen (per Ctrl+F5).

Verändere den Programm-Code so, dass 1'000'000 Punkte gezeichnet werden und dass nach dem Zeichnen eines Punktes keine Pause von einer Millisekunde gemacht wird. (Ich habe diese Pause oben eingeführt, damit das Bild nicht “sofort” da ist; lösche den entsprechenden Befehl oder kommentiere ihn mit # aus.)

Passe das Python-Programm so an, dass einige der Bilder in https://en.wikipedia.org/wiki/Chaos_game#Jumps_other_than_1/2 entstehen. Wenn du zum Beispiel das “Vicsek fractal” zeichnen willst:

  • Sorge dafür, dass die Leinwand quadratisch ist (also Höhe = Breite).
  • Definiere fünf Punkte $A$, $B$, $C$, $D$, $E$.
  • Statt des Faktors 0.5 in den Programmzeilen, wo der Punkt springt, verwende den Faktor 2/3.

Du darfst natürlich kreativ sein und andere Punktekonstellationen und Faktoren ausprobieren.


1)
Alternative (nicht empfohlen, denn vermutlich muss man dann noch einige Pfad-Einstellungen von Hand vornehmen): Download von https://www.python.org/downloads/
2)
Oft wird von einem Algorithmus verlangt, dass er nach endlich vielen Schritten endet.
  • lehrkraefte/snr/informatik/glf23/python/chaos-game-mit-pygame.txt
  • Last modified: 2023/08/24 14:18
  • by Olaf Schnürer