K103: verschachtelte Verzweigungen

Mehrfachverzweigungen und verschachtelte Verzweigungen erlauben es, mehrere unterschiedliche Fälle auszuwerten. 

Inhaltsverzeichnis

Einordnung

Kursblog L8T4: Mehrfachverzweigungen und verschachtelte Verzweigungen

Dieser Blog wird vom IAIP gratis zur Verfügung gestellt. Der Blog ist ein  Bestandteil des Kurses K103 «Programmieren mit Turtle Graphics» und gehört zur Lektion 8, Themenblock 4 (L8T4).

Der Kurs führt dich durch die einzelnen Blogs, enthält Zusatzmaterialien und Quizze zur Lernkontrolle. Der Kurs hat eine Kursgebühr von CHF 50.- Mit dem Einschreiben zum Kurs hilfst du mit, dass solche Blogs auch zukünftig noch gratis zur Verfügung gestellt werden können.

Rückblick

In den letzten drei Themenblogs (K103: bedingte Anweisungen, K103: Bedingungen und ihre Möglichkeiten, K103: Verzweigungen) haben wir bedingte Anweisungen (if Statement) und Verzweigungen (if – else Statments) kennengelernt. 

Betrachten wir das folgende kleine Beispielprogramm aus dem Blogbeitrag zu den bedingten Anweisungen (siehe K103: bedingte Anweisungen):

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")

if zustand == "schlecht":
    write("Das tut mir aber leid.")

goto(0, -20)
write("Ende")

exitonclick()

Im Programm hat es 2 bedingte Anweisungsblöcke (Zeilen 7-9 und 11-12). Gibt der Benutzer auf die gestellte Frage (Zeile 3) mit der Tastatur «gut» ein, so erfolgt die Ausgabe «Das freut mich. Mir geht es auch gut!». Und gibt er «schlecht» ein, so wird «Das Tut mir aber leid.» auf den Bildschirm geschrieben. Unser Programm funktioniert einwandfrei, hat aber den Nachteil, dass bei einer Eingabe von beispielsweise «mies» gar nichts passiert. Unser Benutzer wird quasi im Regen stehen gelassen. Gibt der Benutzer etwas anderes als «gut» oder «schlecht» ein, dann passiert nichts. Es wird lediglich die ganz normale Ausgabe «Ende» geschrieben. 

Betrachten wir als nächstes das folgende Beispielprogramm mit einer Verzweigung:

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")
else:
    write("Dieses Wort verstehe ich leider nicht.")

goto(0, -20)
write("Ende")

exitonclick()

Wir haben dieses Programm ebenfalls bereits besprochen, namentlich im Blogbeitrag zu den Verzweigungen (siehe K103: Verzweigungen). Was ist anders? Bei Verzweigungen kommt zusätzlich das Schlüsselwort else zum Einsatz. Gibt der Benutzer bei Ausführung des Programms auf die gestellte Frage «gut» ein, so erfolgt die Ausgabe «Das freut mich. Mir geht es auch gut!», andernfalls wird «Dieses Wort verstehe ich leider nicht.» auf den Bildschirm geschrieben. In diesem Beispielprogramm haben wir heimlich etwas weggelassen. Nämlich die Möglichkeit, dass es unserem User schlecht geht. Während beim ersten Programm der Computer mit «Das tut mir aber leid.» geantwortet hat, gibt es im letzten Programm diese Option nicht mehr. Der Computer versteht das Wort einfach nicht.

Was wir konkret möchten ist:

  • Bei der Antwort «gut» die Ausgabe «Das freut mich. Mir geht es auch gut!»
  • Bei der Antwort «schlecht» die Ausgabe «Das Tut mir aber leid.»
  • Ansonsten: «Dieses Wort verstehe ich leider nicht.»

Eine Möglichkeit zur Lösung dieses Problems liegt in der Verschachtelung (engl.: nested) von bedingten Anweisungen. Eine andere Möglichkeit liegt in der Nutzung von Mehrfachverzweigungen.

Hinweis für fortgeschrittene Kursteilnehmer:

Es gibt theoretisch einige Möglichkeiten, um das Problem mit den uns bereits bekannten Mitteln zu lösen. Beispielsweise wenn wir einen dritten bedingten Anweisungsblock einfügen, in welchem die ersten 2 Varianten ausgeschlossen werden (siehe nachfolgend Zeile 14-15). 

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")

if zustand == "schlecht":
    write("Das tut mir aber leid.")

if zustand != "gut" and zustand != "schlecht":
    write("Dieses Wort kenne ich nicht.")

goto(0, -20)
write("Ende")

exitonclick()

Alternativ könnten wir auch die ersten zwei Möglichkeiten in eine Liste packen. Die Bedingung in Zeile 14 würde dann wie folgt lauten:

if zustand not in ["gut", "schlecht"]:
    write("Dieses Wort kenne ich nicht.")

Solche Lösungen sind aber wenig elegant und vor allem bei vielen Auswahlmöglichkeiten unübersichtlich und kaum noch realisierbar.

Schwerpunkte

In diesem Block werden wir die Themen Verschachtelungen und Mehrfachverzweigungen behandeln. Im Zentrum stehen:

  • allgemeine Syntax und Funktionsweise von Mehrfachverzweigungen (if- elif – else Anweisungen)
  • Strukturierung über Einschübe (Identation)
  • Flussdiagramm und Struktogramm von Mehrfachverzweigungen oder verschachtelter Strukturen

Ergänzung

Der Blogbeitrag «Bedingte Anweisungen und Verzweigungen in Python» enthält neben der nachfolgenden Theorie weitere, darüber hinausgehende Informationen zum Thema bed. Anweisungen & Verzweigungen.

Mehrfachverzweigungen

Einführendes Beispiel

Über die if-Anweisung kann man eine Kommandofolge auszuführen, falls eine Bedingung erfüllt ist. Nutzt man zusätzlich das Schlüsselwort else, so entsteht eine Verzweigung. Es lässt sich eine Kommandofolge ausführen, wenn die Bedingung «wahr» ist, und eine andere, wenn sie «falsch» ist. 

Um Mehrfachverzweigungen zu erstellen, nutzt man in Python zusätzlich das Schlüsselwort elif (von: else – if). Hierzu ein kleines Beispiel:

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")
elif zustand == "schlecht":
    write("Das tut mir aber leid.")
else: 
    write("Dieses Wort kenne ich nicht.")

goto(0, -20)
write("Ende")

exitonclick()

Das Programm führt zu folgenden Ausgaben:

Syntax von Mehrfachverzweigungen

Bei Mehrfachverzweigungen (auch: Fallunterscheidungen) werden die Bedingungen der Reihe nach ausgewertet, solange bis eine davon zutrifft. Dann wird der zu dieser Bedingung gehörende Codeabschnitt ausgeführt und die Behandlung der mehrfachen Verzweigung ist damit beendet. Wenn keine der Bedingungen zutrifft, wird der else-Teil ausgeführt, falls er vorhanden ist.

Die Syntax einer Mehrfachverzweigung in Python ist wie folgt:

if Bedingung:
       Anweisung(en)
elif Bedingung:
       Anweisung(en)
elif Bedingung:
       Anweisung(en)

else:
       Anweisung(en)

Mehrfachverzweigungen können also durchaus mehrere elif Blöcke haben. Merke dir:

Verschachtelungen von bedingten Anweisungen und Verzweigungen

Einführendes Beispiel

Eine zweite Möglichkeit zur Lösung unseres Problems liegt in der Verschachtelung mehrerer Verzweigungen. Verschachtelte Strukturen trifft man in Programmcodes sehr oft an. Für uns ist das Thema eigentlich nichts Neues. Wir haben es bereits bei der for Schleife (siehe Blogbeitrag K103: verschachtelte Schleifen) kennengelernt. Bei Python muss man dabei besonders auf die Einschübe achten. Verschachtelungen bei bedingten Anweisungen und Verzweigungen funktionieren vom Prinzip her genau gleich. 

Der wichtige Punkt ist der Folgende:

Das ganze klingt komplizierter, als es in der Tat ist. Das Prinzip sieht man am besten anhand eines konkreten Beispiels:

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")
else:
     write("Es geht dir also nicht gut. ", move=True)
     if zustand == "schlecht":
        write("Tut mir aber leid.")
     else:
        write("Dieses Wort kenne ich nicht.")

goto(0, -20)
write("Ende")

exitonclick()

Wichtig hier sind die Einschübe. Zur Illustration sind nachfolgend wiederum drei mögliche Eingaben mit ihren zugehörigen Ausgaben abgebildet.

Ebenso eine farbliche Markierung der Einschübe.

Verschachtelungen

Grundsätzlich kann man wie gezeigt bedingte Anweisungen und Verzweigungen verschachteln. Manchmal ist es aber nicht sehr elegant. Und eine solche Lösung wird bei vielen Möglichkeiten ziemlich schnell unübersichtlich. Siehe hierzu Aufgabe 2c im Vergleich zu 2b. Falls möglich sollte man deshalb eher Mehrfachverzweigungen verwenden. 

Die Verschachtelung von Programmstrukturen ist aber ein ganz allgemeines Prinzip, welches an vielen unterschiedlichen Stellen zur Anwendung kommt. Es werden nicht nur Verzweigungen in Verzweigungen, sondern auch in Funktionen, Schleifen, etc. verschachtelt. Mit Mehrfachverzweigungen kann man nur einige ganz bestimmte Anwendungsfälle abdecken. 

Du findest in den Aufgaben 5 – 5d Beispiele, in welchen Verzweigungen in  Schleifen vorkommen.

Struktogramm und Flussdiagramm (ergänzende Informationen)

Wir haben in den vorangehenden Themenblogs das Flussdiagramm und das Struktogramm für bedingte Anweisungen und Verzweigungen erläutert. Nachfolgend sind das Flussdiagramm und das Struktogramm für eine Mehrfachverzweigung abgebildet.

Sie folgen der bekannten Logik. Die Pfeile bzw. der Ablauf von oben nach unten gibt die Reihenfolge der Anweisungen an. Zur Illustration findest du nachfolgend die zwei Diagramme für unser weiter oben vorgestelltes Beispielprogramm einer Mehrfachverzweigung.

 Der Unterschied zu verschachtelten bedingten Anweisungen und Verzweigungen kommt beim Struktogramm besonders gut zum Ausdruck.

Übungsaufgaben

Nachfolgend findest Du ein paar Übungsaufgaben. 

Aufgabe 1: Sesam öffne dich V

Geben ist unser Programm aus Aufgabe 2 des vorangehenden Themenblogs, welches den User zur Eingabe eines Passworts aufforderte. Entspricht die Eingabe der Zeichenfolge «Sesam öffne dich» oder der Zeichenfolge «sesam öffne dich», so erfolgt wiederum die Ausgabe «Das Passwort ist korrekt». Gibt er etwas anderes ein, so soll die Ausgabe «Das Passwort ist falsch!» geschrieben werden. 

Versuche jetzt diesen Fall über eine Mehrfachverzweigung (ohne or und ohne !=) zu programmieren.

 

Aufgabe 1b: Sesam öffne dich VI

Geben ist unser Programm «Sesam öffne dich V» aus Aufgabe 1. Versuche jetzt diesen mit zwei (einfachen) Verzweigungen zu programmieren. 

Hinweis: Du musst die Verzweigungen verschachteln.

 

Aufgabe 2: Figur nach Wunsch III

Im Themenblog zu den bedingten Anweisungen haben wir in Aufgabe 2 den Benutzer gefragt, was gezeichnet werden soll. Anschliessend wurde noch die Grösse der Figur abgefragt. Hatte der Benutzer «Viereck» eingegeben, so wurde ein Viereck in der gewünschten Grösse gezeichnet. Hatte er «Kreis» eingegeben, so wurde ein Kreis in der gewünschten Grösse gezeichnet. 

Erweitere nun das Programm. Je nach Eingabe soll er ein Viereck, einen Kreis oder ein Dreieck zeichnen. Gibt der Benutzer etwas anderes ein, dann wird «Diese Figur kenne ich nicht» geschrieben.

Aufgabe 2b: Figur nach Wunsch IV

Gegeben ist Aufgabe 2. Neu soll der Benutzer für ein Viereck die Wörter «Viereck», «viereck» oder «4eck», für einen Kreis die Wörter «Kreis» oder «kreis» und für ein Dreieck die Wörter «Dreieck», «dreieck» oder «3eck» eingeben können.

Hinweis: Ergänze die jeweiligen Bedingungen, in dem du die einzelnen Möglichkeiten pro Figur mit or oder and verknüpfst.

Erweitere nun das Programm. Für eine Seitenlänge (oder Radius) von 50 oder weniger wird mit einer Strichdicke von 2 gezeichnet. Im Bereich von 50 < Länge <= 100 mit einer Dicke von 4 und darüber mit einer Dicke von 6. Erstelle hierzu eine Mehrfachverzweigung und stelle die Stiftdicke mit pensize() ein.

Aufgabe 2c: Figur nach Wunsch V

Gegeben ist Aufgabe 2b. Versuche nun das Programm anstelle von mit Mehrfachverzweigungen neu mit verschachtelten Verzweigungen zu machen.

 

Aufgabe 5: 5000 rote Punkte (mit Grösse 4)

Gegeben ist das rechts abgebildete Programm. Es zeichnet 5000 Punkte auf den Bildschirm. Die Position des jeweiligen Punkts wird dabei zufällig gewählt.

Studiere die einzelnen Anweisungen und übertrage das Programm auf deinen PC. 

Hinweis: 
speed(0) : macht die Turtle schneller
import random: Bibliothek für Zufallszahlen importieren
random.randint(-200, 200): Zufallszahl zwischen -200 bis +200
goto(x,y): geht an die absoluten Koordinaten des Punkts
dot(size, color): setzt einen Punkt

 

from turtle import *
import random

title("Crazy Turtle")
speed(0)
durchgänge = 5000
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    dot(4, "red")
exitonclick()   

Aufgabe 5b: xcor

Gegeben ist unser Programm aus Aufgabe 5. Passe nun den Code an. Wir möchten für positive x-Koordinaten (x > 0) einen roten Punkt, für negative x-Koordinaten einen blauen Punkt.

Nutze hierzu die xcor() Anweisung. Sie gibt dir die x-Koordinate der Turtle zurück.

Hinweis: Du kannst anstelle xcor() auch direkt x verwenden.

Aufgabe 5c: ycor

Gegeben ist unser Programm aus Aufgabe 5. Passe nun den Code an. Wir möchten für  y-Koordinaten grösser 50 (y > 50) ein oranger Punkt in Punktgrösse 4, für y-Koordinaten zwischen 50 und -100 (50 >= y > -100) ein gelber Punkt in Punktgrösse 6 und für alle anderen y-Koordinaten ein grüner Punkt in Punktgrösse 8 gezeichnet wird.

Nutze hierzu die ycor() Anweisung. Sie gibt dir die y-Koordinate der Turtle zurück

Aufgabe 5d: xcor und ycor verschachtelt

Gegeben ist unser Programm aus Aufgabe 5. Passe nun den Code an, so dass das rechts abgebildete Bild entsteht. Erstelle hierzu zuerst eine Verzweigung zur y-Koordinate (if ycor() >0 :) und im zugehörigen else Teil eine verschachtelte Verzweigung zur x-Koordinate.

Aufgabe 6: Kreis

Versuche die rechts abgebildete Figur zu zeichnen.

Hinweis: Du kannst dir zu nutze machen, dass im Einheitskreis (Radius 1)  die zwei Koordinaten im Quadrat immer 1 sein müssen (Pythagoras).

c = (xcor()/200)**2 + (ycor()/200)**2
if c > 1:
   dot(4, "red")
else:
   ..... 

Aufgabe 7: Flussdiagramm

Versuche das Programm zum rechts abgebildeten Flussdiagramm zu schreiben. Im vorliegenden Fall handelt es sich um verschachtelte Verzweigungen. 

Hinweis: Du Farben und gestrichelten Linien dienen nur der Orientierung. 

Lösungen zu den Übungsaufgaben

Lösung zur Aufgabe 1: Sesam öffne dich V

Nachfolgend findest du das Programmbeispiel:

from turtle import *

write("Bitte Passwort eingeben, um die geheime Figur zu sehen")
passwort = textinput("Geheime Figur", "Bitte Passwort eingeben")
clear()

if passwort == "Sesam öffne dich":
    circle(100)
elif passwort == "sesam öffne dich":
    circle(50)
else:
    write("Das Passwort ist falsch!")
  
exitonclick()

Lösung zur Aufgabe 1b: Sesam öffne dich VI

Nachfolgend findest du das Programmbeispiel:

from turtle import *

zustand = textinput("Zustand", "Wie geht es dir heute?")
penup()
hideturtle()

if zustand == "gut":
    write("Das freut mich. ", move=True)
    write("Mir geht es auch gut!")
else:
     write("Es geht dir also nicht gut. ", move=True)
     if zustand == "schlecht":
        write("Tut mir aber leid.")
     else:
        write("Dieses Wort kenne ich nicht.")

goto(0, -20)
write("Ende")

exitonclick()

Lösung zur Aufgabe 2: Figur nach Wunsch III

Nachfolgend findest du das Programmbeispiel:

from turtle import *

fig = textinput("Figur", "Was soll gezeichnet werden")
g = numinput("Grösse", "Welche Grösse")

if fig == "Viereck":
    forward(g)
    right(90)
    forward(g)
    right(90)
    forward(g)
    home()
elif fig == "Kreis":
    circle(g)
elif fig == "Dreieck":
    forward(g)
    right(120)
    forward(g)
    home()    
else:
    write("Diese Figur kenne ich nicht!")

exitonclick()   

Lösung zur Aufgabe 2b: Figur nach Wunsch IV

Nachfolgend findest du das Programmbeispiel:

from turtle import *

fig = textinput("Figur", "Was soll gezeichnet werden")
g = numinput("Grösse", "Welche Grösse")

if g <= 50:
    pensize(2)
elif g > 50 and g <= 100:
    pensize(4)
else:
    pensize(6)

if fig == "Viereck" or fig == "viereck" or fig == "4eck":
    forward(g)
    right(90)
    forward(g)
    right(90)
    forward(g)
    home()
elif fig == "Kreis" or fig == "kreis":
    circle(g)
elif fig == "Dreieck" or fig == "dreieck" or fig == "3eck":
    forward(g)
    right(120)
    forward(g)
    home()    
else:
    write("Diese Figur kenne ich nicht!")

exitonclick()   

Lösung zur Aufgabe 2c: Figur nach Wunsach V

Nachfolgend findest du das Programmbeispiel:

from turtle import *

fig = textinput("Figur", "Was soll gezeichnet werden")
g = numinput("Grösse", "Welche Grösse")

if g <= 50:
    pensize(2)
else:
    if g > 50 and g <= 100:
        pensize(4)
    else:
        pensize(6)

if fig == "Viereck" or fig == "viereck" or fig == "4eck":
    forward(g)
    right(90)
    forward(g)
    right(90)
    forward(g)
    home()
else:
    if fig == "Kreis" or fig == "kreis":
        circle(g)
    else:
        if fig == "Dreieck" or fig == "dreieck" or fig == "3eck":
            forward(g)
            right(120)
            forward(g)
            home()    
        else:
            write("Diese Figur kenne ich nicht!")

exitonclick()

Lösung zur Aufgabe 5b: xcor

from turtle import *
import random

title("crazy screen")
speed(0)
durchgänge = 5000
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    if xcor() > 0:
        dot(4, "red")
    else:
        dot(4, "blue")

exitonclick() 

Lösung zur Aufgabe 5c: ycor

from turtle import *
import random

title("crazy screen")
speed(0)
durchgänge = 5000
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    if ycor() > 50:
        dot(4, "orange")
    elif ycor() > -100:
        dot(6, "yellow")
    else:
        dot(8, "green")

exitonclick()

Lösung zur Aufgabe 5d: xcor und ycor verschachtelt

from turtle import *
import random

title("crazy screen")
speed(0)
durchgänge = 5000
tracer(250)
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    if ycor() > 0:
        dot(4, "red")
    else:
        if xcor() < 0:
            dot(4, "green")
        else:
            dot(4, "blue")

exitonclick()

Lösung zur Aufgabe 6: Kreis

from turtle import *
import random

title("crazy screen")
speed(0)
tracer(500)
durchgänge = 5000
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    c = (xcor()/200)**2 + (ycor()/200)**2
    if c > 1:
        dot(4, "red")
    else:
        dot(4, "blue")

exitonclick() 

Lösung zur Aufgabe 7: Flussdiagramm

from turtle import *
import random

title("crazy screen")
speed(0)
tracer(500)
durchgänge = 5000
penup()

for i in range(durchgänge):
    x = random.randint(-200, 200)
    y = random.randint(-200, 200)
    goto(x,y)
    c = (xcor()/200)**2 + (ycor()/200)**2
    if c > 1:
        dot(4, "red")
    else:
        dot(4, "blue")

exitonclick() 

Comments