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()

Leave a Reply