Akinator — Ein lernender Entscheidungsbaum in Python
Bauen Sie einen Akinator-Klon in Python, der durch Ja-oder-Nein-Fragen rät — und dazulernt, indem er sein Wissen als Entscheidungsbaum speichert.
- Sie können den Aufbau eines Entscheidungsbaums als verschachteltes Dictionary erklären.Verstehen
- Sie können ein Python-Programm mit Rekursion, Datei-Ein-/Ausgabe (JSON) und Dictionary-Manipulation umsetzen.Anwenden
- Sie können den Akinator um eigene Funktionen wie Statistik und erweiterte Benutzerführung ergänzen.Kreieren
In diesem Modul bauen Sie einen Akinator-Klon in Python. Das Programm stellt Ja-oder-Nein-Fragen, um zu erraten, woran Sie denken — und lernt aus seinen Fehlern. Kernkonzepte: Entscheidungsbaum, Rekursion, JSON-Dateien.
Was ist Akinator?
Akinator ist ein bekanntes Online-Spiel, das versuchen kann, eine Person, einen Gegenstand oder ein Tier zu erraten — nur durch Ja-oder-Nein-Fragen. Das Erstaunliche: Je öfter man spielt, desto besser wird es!
Dahinter steckt ein Entscheidungsbaum — eine Baumstruktur, bei der jede Frage zu zwei weiteren Ästen führt (ja/nein). Am Ende der Äste stehen die Antworten.
In diesem Modul bauen Sie Ihren eigenen Akinator in Python — und das Besondere: Er lernt dazu! Wenn er etwas nicht weiss, fragt er Sie und merkt es sich fürs nächste Mal.
Note
Wie funktioniert ein Entscheidungsbaum?
Stell dir einen Baum vor:
- Jeder Knoten enthält entweder eine Frage oder eine Antwort.
- Bei einer Frage gibt es zwei Wege: ja (links) und nein (rechts).
- Bei einer Antwort ist das Spiel vorbei — der Computer rät.
Beispiel:
[Ist es ein Lebewesen?]
├── ja → [Hat es vier Beine?]
│ ├── ja → "Hund"
│ └── nein → "Mensch"
└── nein → [Kann man es essen?]
├── ja → "Pizza"
└── nein → "Stein"
In Python speichern wir diesen Baum als verschachteltes Dictionary. Das Lernen funktioniert, indem wir neue Fragen und Antworten in den Baum einfügen.
import json
import os
DATEI = "wissen.json"
STANDARD_WISSEN = {
"frage": "Ist es ein Lebewesen?",
"ja": {
"frage": "Hat es vier Beine?",
"ja": {"antwort": "Hund"},
"nein": {"antwort": "Mensch"}
},
"nein": {
"frage": "Kann man es essen?",
"ja": {"antwort": "Pizza"},
"nein": {"antwort": "Stein"}
}
}
def wissen_laden():
if os.path.exists(DATEI):
with open(DATEI, "r", encoding="utf-8") as f:
return json.load(f)
return STANDARD_WISSEN
def wissen_speichern(wissen):
with open(DATEI, "w", encoding="utf-8") as f:
json.dump(wissen, f, ensure_ascii=False, indent=2)
def frage_stellen(text):
while True:
antwort = input(text + " (ja/nein): ").strip().lower()
if antwort in ["ja", "j", "yes", "y"]:
return True
if antwort in ["nein", "n", "no"]:
return False
print("Bitte antworte mit 'ja' oder 'nein'.")
def lernen(knoten, falsche_antwort):
richtige_antwort = input("Was hast du dir ausgedacht? ")
neue_frage = input(
"Gib mir eine Frage, die '" + richtige_antwort
+ "' von '" + falsche_antwort + "' unterscheidet: "
)
antwort_fuer_neu = frage_stellen(
"Ist die Antwort fuer '" + richtige_antwort + "' ja?"
)
knoten.clear()
knoten["frage"] = neue_frage
if antwort_fuer_neu:
knoten["ja"] = {"antwort": richtige_antwort}
knoten["nein"] = {"antwort": falsche_antwort}
else:
knoten["ja"] = {"antwort": falsche_antwort}
knoten["nein"] = {"antwort": richtige_antwort}
def spielen(knoten):
if "antwort" in knoten:
ratung = knoten["antwort"]
if frage_stellen("Ist es " + ratung + "?"):
print("Super! Ich hab's gewusst!")
else:
print("Oh, das wusste ich nicht.")
lernen(knoten, ratung)
return
if frage_stellen(knoten["frage"]):
spielen(knoten["ja"])
else:
spielen(knoten["nein"])
def main():
print("=== Akinator ===")
print("Denk dir etwas aus, und ich versuche es zu erraten!")
print()
wissen = wissen_laden()
while True:
spielen(wissen)
wissen_speichern(wissen)
if not frage_stellen("Nochmal spielen?"):
print("Bis bald!")
break
main()Challenge
Dein Auftrag: Erweitere den Akinator!
Der Code funktioniert — aber mit nur 4 Einträgen im Baum ist er schnell durch. Erweitern Sie ihn!
Teil 1 — Basis (alle)
- Kopiere den Code in eine Datei
akinator.pyund teste ihn. - Spielen Sie mehrmals und bringen Sie dem Akinator mindestens 5 neue Dinge bei.
- Schauen Sie sich die Datei
wissen.jsonan — wie wächst der Baum mit jedem neuen Eintrag? - Erweitern Sie
STANDARD_WISSENmit 3–5 weiteren Einträgen, damit der Start-Baum grösser ist.
Teil 2 — Mittel
- Bauen Sie einen Runden-Zähler ein: Das Programm zeigt an, wie viele Fragen es gestellt hat und wie oft es richtig geraten hat.
- Fügen Sie eine Statistik hinzu: "Ich habe schon X Mal gespielt und Y Mal richtig geraten." Speichern Sie die Statistik ebenfalls in der JSON-Datei.
Teil 3 — Fortgeschritten (optional)
- Fügen Sie eine "Vielleicht"-Antwort hinzu: Bei "vielleicht" soll der Akinator beide Äste des Baums durchsuchen und alle möglichen Antworten sammeln.
- Bauen Sie einen "Zurücksetzen"-Befehl ein, der den Baum auf den Anfangszustand zurücksetzt.
- Geben Sie den aktuellen Baum als Text-Diagramm aus (ähnlich wie im Infokasten oben).
Warning
Häufige Fehler
- Rekursion verstehen: Die Funktion
spielen()ruft sich selbst auf — das nennt man Rekursion. Bei jedem Aufruf geht man einen Knoten tiefer im Baum. Der Abbruch ist erreicht, wenn"antwort"im Knoten steht. - knoten.copy() im lernen(): Ohne
.copy()würden die alten Daten überschrieben. Der ursprüngliche Knoten wird zum neuen Frage-Knoten, die alte Antwort rutscht auf die "nein"-Seite. - JSON-Datei wird nicht erstellt: Beim ersten Spiel gibt es noch keine
wissen.json— deshalb prüftos.path.exists()zuerst, ob die Datei existiert. - Umlaute in JSON: Das
ensure_ascii=Falseinjson.dump()ist wichtig, damit Umlaute (ä, ö, ü) korrekt gespeichert werden.
# Tipp für die Statistik (Teil 2):
STATS_DATEI = "akinator_stats.json"
def stats_laden():
if os.path.exists(STATS_DATEI):
with open(STATS_DATEI, "r", encoding="utf-8") as f:
return json.load(f)
return {"spiele": 0, "richtig": 0}
def stats_speichern(stats):
with open(STATS_DATEI, "w", encoding="utf-8") as f:
json.dump(stats, f, ensure_ascii=False, indent=2)
# In main() einbauen:
# stats = stats_laden()
# ... nach jedem Spiel:
# stats["spiele"] += 1
# if gewonnen: stats["richtig"] += 1
# stats_speichern(stats)
# print(f"Statistik: {stats['richtig']} von {stats['spiele']} richtig.")Lokal gespeichert — melde dich an, um Antworten dauerhaft zu sichern.
Login