K103: Hangman Numbers (Fallbeispiel)

In diesem Blogbeitrag lernst du, das Spiel Hangman in Python mit Turtle Graphics zu programmieren.

Table of Contents

Hangman und Hangman Numbers

Originalversion

Hangman (auch Galgenmännchen, Galgenraten, Hängemann, etc.) ist in seiner Originalversion ein einfaches Buchstabenratespiel.

Gegeben ist ein längeres Wort, von dem anfangs aber alle Buchstaben verdeckt bzw. als Striche markiert sind. Der Spieler nennt nun in beliebiger Reihenfolge nacheinander einzelne Buchstaben. Der Schiedsrichter muss jeweils sagen, wie oft und an welcher Stelle des Lösungswortes der Buchstabe vorkommt. So ergibt sich nach und nach das gesuchte Wort. Kommt ein genannter Buchstabe im Wort jedoch nicht vor, so ist es ein Fehler. Bei jedem Fehler wird ein Teil des Galgens gezeichnet.  Insgesamt besteht der Galgen (mit dem Mann) aus 10 Strichen. Der Spieler hat also genau 10 Versuche, um das Wort zu finden.

Hangman Numbers

Basis dieses Blogbeitrags bildet ein Spiel, welches wir Hangman Numbers nennen. Hier werden nicht Wörter, sondern Zahlen geraten. Der Spieler muss eine Zahl zwischen 1 und 100 erraten, wobei ihm insgesamt 10 Versuche zur Verfügung stehen. Damit es etwas einfacher ist, sagt der Computer nach jedem Versuch, ob die gewählte Zahl zu gross oder zu klein ist.

Einordnung

Das Programm dient als Fallbeispiel für die Lektionen 7-9, in welchen Kontrollstrukturen behandelt werden. Im Zentrum stehen bedingte Anweisungen & Verzweigungen sowie die while Schleife. Ferner absolute Koordinaten.

Hinweis: in der Praxis würde man solche Programme mit mehreren Schildkrötenobjekten und mit Funktionen programmieren. Dadurch würde der Code kürzer und vor allem deutlich übersichtlicher. Diese zwei Hilfsmittel wurden jedoch im Kurs innerhalb der Lektionen 1 bis 9 noch nicht behandelt. 

Grundversion

Vorab: Galgen und Mann zeichen

Bevor wir mit dem eigentlichen Programm starten, wollen wir einmal einen Galgen mit Mann zeichnen. In unserem Beispiel geht es darum, absolute Koordinaten zu üben. Nachfolgend findest du eine Entwurfsskizze mit den wichtigsten Koordinaten. Natürlich kannst du auch einen eigenen Entwurf machen. 

Als erstes versuchen wir also das skizzierte Bild nachzuzeichnen. Ein möglicher Code sieht wie folgt aus: 

# Bibliothek importieren
from turtle import *

# Boden, Gras
goto(-150,0)
pensize(10)
pencolor("darkgreen")
goto(150,0)

# Podest
goto(120,0)
pensize(4)
pencolor("burlywood4")
goto(120,20)
pensize(8)
goto(-120,20)
pensize(4)
goto(-120,0)

# vertikaler Balken
penup()
goto(-110,20)
pendown()
pensize(6)
pencolor("burlywood2")
goto(-110,270)

# horizontaler Balken
pensize(4)
pencolor("burlywood2")
goto(100,270)

# Schur
goto(60,270)
pensize(1)
pencolor("black")
goto(60,240)

# Kopf
goto(60,240)
circle(-10)

# Hals
penup()
goto(60,220)
pendown()
goto(60,200)

# linker Arm
goto(30,240)
goto(60,200)

# rechter Arm
goto(90,240)
goto(60,200)

# Körper
goto(60,140)

# linkes Bein
goto(30,90)
goto(60,140)

# rechtes Bein
goto(90,90)

# Ende
exitonclick()

Für unsere Zwecke passen wir das Programm noch etwas an.  Bei den Kommentarzeilen haben wir anfangs noch eine Zahl ergänzt. Sie gibt an, bei welchem Fehler dieser Teil des Bildes gemalt werden soll. Wie du vielleicht gesehen hast, besteht unser Bild aktuell aus 12 Einzelteilen. Der Spieler hat aber nur 10 Versuche, um die richtige Zahl zu finden. Wir gehen deshalb davon aus, dass die ersten zwei Teile (Boden und Podest) bereits am Anfang des Spiels gezeichnet werden.

Ferner zeichnen wir jedes Element «als Einzelteil». Das soll heissen, dass wir jeweils den Stift anheben, zum Start des Elements gehen, den Stift senken und das Element zeichnen, um dann am Ende den Stift wieder anzuheben. Warum? Wir werden später mit unserer Schildkröte ja noch andere Sachen machen, wie beispielsweise Texte an gewisse Stellen auf dem Bildschirm schreiben. Wir können also nicht davon ausgehen, dass sich unsere Schildkröte zu Beginn bereits am richtigen Ort befindet. Zur Sicherheit, heben wir vor der Verschiebung an den Startpunkt den Stift an.

# Bibliothek importieren
from turtle import *

# 0: Boden, Gras 
penup()
goto(-150,0)
pendown()
pensize(10)
pencolor("darkgreen")
goto(150,0)
penup()

# 0: Podest
penup()
goto(120,0)
pendown()
pensize(4)
pencolor("burlywood4")
goto(120,20)
pensize(8)
goto(-120,20)
pensize(4)
goto(-120,0)
penup()

# 1: vertikaler Balken
penup()
goto(-110,20)
pendown()
pensize(4)
pencolor("burlywood2")
goto(-110,270)
penup()

# 2: horizontaler Balken
penup()
goto(-110,270)
pendown()
pensize(4)
pencolor("burlywood2")
goto(100,270)
penup()

# 3: Schur
penup()
goto(60,270)
pendown()
pensize(1)
pencolor("black")
goto(60,240)
penup()

# 4: Kopf
penup()
goto(60,240)
setheading(0)
pendown()
circle(-10)
penup()

# 5: Hals
penup()
goto(60,220)
pendown()
goto(60,200)
penup()

# 6: linker Arm
penup()
goto(60,200)
pendown()
goto(30,240)
penup()

# 7: rechter Arm
penup()
goto(60,200)
pendown()
goto(90,240)
penup()

# 8: Körper
penup()
goto(60,200)
pendown()
goto(60,140)
penup()

# 9: linkes Bein
penup()
goto(60,140)
pendown()
goto(30,90)
penup()

# 10: rechtes Bein
penup()
goto(60,140)
pendown()
goto(90,90)
penup()

# Ende
exitonclick()

Spiel

Zusammenfassend ergibt sich der nachfolgende Code. Am Ende wir noch ausgegeben, wer gewonnen hat. Viel Spass!

# Bibliotheken
from turtle import *
import random
import time

# Bildschirm
title("Hangman")
setup(width=700,height=700)

# Intro
hideturtle()
penup()
sety(150)
write("Hangman Numbers", align="center", font=("Times", 50, "bold"))
sety(100)
write("(c) by Hans Mustermann", align="center", font=("Times", 20, "normal"))
time.sleep(3)

while True:

  clear()
  # Titel
  goto(-100, 150)
  write("Hangman", align="left", font=("Times", 20, "bold"))

  # Menu 
  goto(-100, 100)
  write("1: Neues Spiel", align="left", font=("Times", 14, "normal"))
  goto(-100, 60)
  write("2: Spieler wechseln", align="left", font=("Times", 14, "normal"))
  goto(-100, 20)
  write("3: Hall of Fame (Rangliste)", align="left", font=("Times", 14, "normal"))
  goto(-100, -20)
  write("7: Einstellungen", align="left", font=("Times", 14, "normal"))
  goto(-100,-60)
  write("8: Anleitung", align="left", font=("Times", 14, "normal"))
  goto(-100,-100)
  write("9: Spiel beenden", align="left", font=("Times", 14, "normal"))
  
  wahl = textinput("Menüpunkt", "Bitte wählen Sie einen Menüpunkt: ")

  if wahl == "1":
    # zuerst einige Variablen
    zahl = random.randint(1, 100)
    max_versuche = 10
    versuche = 0

    # Hauptteil
    clear()

    # -Podest Zeichnen
    # 0: Boden, Gras
    goto(-150,0)
    pendown()
    pensize(10)
    pencolor("darkgreen")
    goto(150,0)
    penup()
    # 0: Podest
    goto(120,0)
    pendown()
    pensize(4)
    pencolor("burlywood4")
    goto(120,20)
    pensize(8)
    goto(-120,20)
    pensize(4)
    goto(-120,0)
    penup()
    
    while True:
      # Eingabe einer Zahl ...
      goto(-100, -70)
      pendown()
      pencolor("white")
      pensize(20)
      goto(100,-70)
      penup()
      
      goto(-100, -80)
      pencolor("blue")
      txt = "Du hast noch " + str(max_versuche - versuche) + " Versuche"
      write(txt)
  
      versuche = versuche + 1
      eingabe = int(numinput("Zahl", "Bitte eine Zahl eingeben: ", minval=0, maxval=100))
  
      # ... und Auswertung
      goto(-100, -90)
      pendown()
      pencolor("white")
      pensize(20)
      goto(100,-90)
      penup()

      goto(-100, -100)
      pencolor("blue")
      if eingabe < zahl:     
          txt = "Die gesuchte Zahl ist grösser als " + str(eingabe)
          write(txt) 
      elif eingabe > zahl:
          txt = "Die gesuchte Zahl ist kleiner als " + str(eingabe)
          write(txt) 
      elif eingabe == zahl: 
         write("Gratuliere! Die Zahl stimmt.")
         goto(-100,-200)
         write("Du hast gewonnen!", align="center", font=("Times", 20, "normal"))
         time.sleep(3)
         break
  
      # Zeichnung
      if versuche == 1:
        goto(-110,20)
        pendown()
        pensize(4)
        pencolor("burlywood2")
        goto(-110,270)
        penup()
        
      elif versuche == 2:
        goto(-110,270)
        pendown()
        pensize(4)
        pencolor("burlywood2")
        goto(100,270)
        penup()
        
      elif versuche == 3:
        goto(60,270)
        pendown()
        pensize(1)
        pencolor("black")
        goto(60,240)
        penup()

      elif versuche == 4:
        goto(60,240)
        setheading(0)
        pendown()
        pensize(2)
        pencolor("black")
        circle(-10)
        penup()
        
      elif versuche == 5:
        goto(60,220)
        pendown()
        pensize(2)
        pencolor("black")
        goto(60,200)
        penup()
        
      elif versuche == 6:
        goto(60,200)
        pendown()
        pensize(2)
        pencolor("black")
        goto(30,240)
        penup()

      elif versuche == 7:
        goto(60,200)
        pendown()
        pensize(2)
        pencolor("black")
        goto(90,240)
        penup()
        
      elif versuche == 8:
        goto(60,200)
        pendown()
        pensize(2)
        pencolor("black")
        goto(60,140)
        penup()
        
      elif versuche == 9:
        goto(60,140)
        pendown()
        pensize(2)
        pencolor("black")
        goto(30,90)
        penup()
        
      elif versuche == 10:
        goto(60,140)
        pendown()
        pensize(2)
        pencolor("black")
        goto(90,90)
        penup()
  
        goto(-100,-200)
        write("Du hast leider verloren!", align="center", font=("Times", 20, "normal"))
        time.sleep(3)
        break
      
  elif wahl == "2":
    pass
  
  elif wahl == "3":
    pass
  
  elif wahl == "7":
    pass
  
  elif wahl == "8":
    pass
  
  elif wahl == "9":
    # Spielende  
    clear()
    sicher = textinput("Beenden","Sie wollen das Spiel beenden. Sind Sie sicher? (y/n)")
    if sicher == "y" or sicher == "Y" or sicher == "j" or sicher == "J":
      break
  
# Ende
bye()

Comments