Animal game v.2 with gui
import tkinter as tk
from tkinter import simpledialog, messagebox
import pickle
import os
class Node:
def __init__(self, question=None, animal=None):
self.question = question
self.animal = animal
self.yes = None
self.no = None
def is_leaf(self):
return self.animal is not None
class AnimalGuesserApp:
def __init__(self, master):
self.master = master
self.master.title(“Animal Guesser”)
self.master.geometry(“500×300”)
self.master.option_add(“*Font”, “Arial 16”)
self.label = tk.Message(master, text=””, width=460)
self.label.pack(pady=30)
btn_frame = tk.Frame(master)
btn_frame.pack()
self.yes_button = tk.Button(btn_frame, text=”Yes”, width=10, command=self.handle_yes)
self.no_button = tk.Button(btn_frame, text=”No”, width=10, command=self.handle_no)
self.yes_button.pack(side=”left”, padx=20)
self.no_button.pack(side=”right”, padx=20)
self.tree = self.load_tree()
self.current_node = self.tree
self.parent_stack = [] # Track the path for updating
self.mode = “ask” # ask / learn / done
self.display_current()
def display_current(self):
if self.current_node.is_leaf():
self.label.config(text=f”Is it a {self.current_node.animal}?”)
self.mode = “guess”
else:
self.label.config(text=self.current_node.question)
self.mode = “ask”
def handle_yes(self):
if self.mode == “ask”:
self.parent_stack.append((self.current_node, True))
self.current_node = self.current_node.yes
self.display_current()
elif self.mode == “guess”:
self.label.config(text=”Yay! I guessed it!\nPlay again?”)
self.mode = “done”
elif self.mode == “done”:
self.reset_game()
elif self.mode == “learn_step2”:
# user answered yes to: “for the new animal, what’s the answer?”
self.insert_new_knowledge(True)
def handle_no(self):
if self.mode == “ask”:
self.parent_stack.append((self.current_node, False))
self.current_node = self.current_node.no
self.display_current()
elif self.mode == “guess”:
self.start_learning()
elif self.mode == “done”:
self.master.quit()
elif self.mode == “learn_step2”:
# user answered no to: “for the new animal, what’s the answer?”
self.insert_new_knowledge(False)
def start_learning(self):
self.new_animal = simpledialog.askstring(“Teach me”, “I give up! What animal were you thinking of?”)
if not self.new_animal:
self.label.config(text=”Okay, I’ll try better next time.\nPlay again?”)
self.mode = “done”
return
self.new_question = simpledialog.askstring(“Help me learn”, f”Give me a yes/no question to tell a {self.new_animal} from a {self.current_node.animal}”)
if not self.new_question:
self.label.config(text=”No worries. Want to play again?”)
self.mode = “done”
return
self.label.config(text=f”For a {self.new_animal}, what is the answer to your question?”)
self.mode = “learn_step2”
def insert_new_knowledge(self, new_animal_answer_yes):
new_node = Node(question=self.new_question)
if new_animal_answer_yes:
new_node.yes = Node(animal=self.new_animal)
new_node.no = self.current_node
else:
new_node.no = Node(animal=self.new_animal)
new_node.yes = self.current_node
# Attach new node to parent
if self.parent_stack:
parent, went_yes = self.parent_stack[-1]
if went_yes:
parent.yes = new_node
else:
parent.no = new_node
else:
self.tree = new_node # Root replaced
self.save_tree()
self.label.config(text=”Thanks! I’ve learned something new.\nPlay again?”)
self.mode = “done”
def reset_game(self):
self.current_node = self.tree
self.parent_stack = []
self.display_current()
def save_tree(self, filename=”animal_tree.pkl”):
with open(filename, “wb”) as f:
pickle.dump(self.tree, f)
def load_tree(self, filename=”animal_tree.pkl”):
if os.path.exists(filename):
with open(filename, “rb”) as f:
return pickle.load(f)
else:
return Node(animal=”cat”)
if __name__ == “__main__”:
root = tk.Tk()
app = AnimalGuesserApp(root)
root.mainloop()