DEV Community

Mate Technologies
Mate Technologies

Posted on

🎉 Build a Mini Game Show Quiz App with Python & Tkinter (Step-by-Step)

In this tutorial, we’ll build a colorful, animated quiz game using Python and Tkinter—complete with:

Category selection

Countdown timer

Sound effects

Score tracking

Animated confetti 🎊

No advanced Python required—just basic functions, classes, and lists.

🧰 Step 1: Import Required Libraries

Let’s start by importing everything we’ll need.

import tkinter as tk
from tkinter import ttk
import threading
import random
import winsound  # Windows only (use playsound for Mac/Linux)
Enter fullscreen mode Exit fullscreen mode

What these do:

tkinter → GUI framework

ttk → modern widgets (progress bar)

threading → play sounds without freezing the UI

random → confetti randomness

winsound → play sound effects on Windows

🧠 Step 2: Create the Quiz Data

We’ll store questions using a dictionary of lists—one list per category.

quiz_categories = {
    "General Knowledge": [
        {
            "question": "What is the capital of France?",
            "options": ["Paris", "London", "Berlin", "Madrid"],
            "answer": "Paris"
        },
        {
            "question": "Which planet is known as the Red Planet?",
            "options": ["Earth", "Mars", "Jupiter", "Venus"],
            "answer": "Mars"
        }
    ],
    "Literature": [
        {
            "question": "Who wrote 'Romeo and Juliet'?",
            "options": ["Charles Dickens", "William Shakespeare", "Mark Twain", "Jane Austen"],
            "answer": "William Shakespeare"
        },
        {
            "question": "Which novel begins with 'Call me Ishmael'?",
            "options": ["Moby Dick", "1984", "Great Expectations", "The Odyssey"],
            "answer": "Moby Dick"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Why this structure?

Easy to add new categories

Each question contains text, choices, and the correct answer

🏗 Step 3: Create the Main Game Class

Everything lives inside a class to keep things organized.

class MiniGameShow:
    def __init__(self, root):
        self.root = root
        self.root.title("🎉 Mini Game Show 🎉")
        self.root.geometry("800x700")
        self.root.resizable(False, False)
        self.root.configure(bg="#1E1E2F")
Enter fullscreen mode Exit fullscreen mode

Initialize game state variables:

        self.score = 0
        self.current_question = 0
        self.selected_category = None
        self.questions = []
        self.time_left = 15
        self.timer_running = False
        self.animating = False
Enter fullscreen mode Exit fullscreen mode

Finally, load the first screen:

        self.create_category_screen()
Enter fullscreen mode Exit fullscreen mode

📂 Step 4: Category Selection Screen

This screen lets the player choose a quiz category.

def create_category_screen(self):
    self.stop_animations()
    self.clear_screen()
Enter fullscreen mode Exit fullscreen mode

Title label:

    title = tk.Label(
        self.root,
        text="Choose Your Category",
        font=("Helvetica", 28, "bold"),
        fg="#FFD700",
        bg="#1E1E2F"
    )
    title.pack(pady=50)
Enter fullscreen mode Exit fullscreen mode

Generate buttons dynamically:

    for category in quiz_categories:
        btn = tk.Button(
            self.root,
            text=category,
            font=("Helvetica", 20),
            width=25,
            bg="#4B0082",
            fg="white",
            command=lambda c=category: self.start_quiz(c)
        )
        btn.pack(pady=15)
Enter fullscreen mode Exit fullscreen mode

💡 Why lambda c=category?
It locks in the correct category value for each button.

▶️ Step 5: Start the Quiz

When a category is selected, we reset the game state.

def start_quiz(self, category):
    self.selected_category = category
    self.questions = quiz_categories[category]
    self.current_question = 0
    self.score = 0
    self.show_question()
Enter fullscreen mode Exit fullscreen mode

❓ Step 6: Display Questions & Options

def show_question(self):
    if self.current_question >= len(self.questions):
        self.show_result()
        return
Enter fullscreen mode Exit fullscreen mode

Reset the screen and timer:

    self.clear_screen()
    self.time_left = 15
    self.timer_running = True
Enter fullscreen mode Exit fullscreen mode

Question label:

    question_data = self.questions[self.current_question]

    self.question_label = tk.Label(
        self.root,
        text=question_data["question"],
        font=("Helvetica", 22, "bold"),
        fg="#00FFFF",
        bg="#1E1E2F",
        wraplength=750
    )
    self.question_label.pack(pady=50)
Enter fullscreen mode Exit fullscreen mode

⏱ Step 7: Add a Countdown Timer

    self.progress = ttk.Progressbar(
        self.root,
        orient="horizontal",
        length=500,
        mode="determinate",
        maximum=15
    )
    self.progress.pack(pady=10)
Enter fullscreen mode Exit fullscreen mode

Timer logic:

def update_timer(self):
    if self.time_left >= 0 and self.timer_running:
        self.progress["value"] = 15 - self.time_left
        self.time_left -= 1
        self.root.after(1000, self.update_timer)
    else:
        self.timer_running = False
        self.flash_color("#FF4500")
        self.root.after(800, self.next_question)
Enter fullscreen mode Exit fullscreen mode

✅ Step 8: Answer Buttons & Validation

for option in question_data["options"]:
    btn = tk.Button(
        self.root,
        text=option,
        font=("Helvetica", 18),
        width=30,
        bg="#6A5ACD",
        fg="white",
        command=lambda o=option: self.check_answer(o)
    )
    btn.pack(pady=10)
Enter fullscreen mode Exit fullscreen mode

Check the answer:

def check_answer(self, selected_option):
    if not self.timer_running:
        return

    self.timer_running = False
    correct_answer = self.questions[self.current_question]["answer"]
Enter fullscreen mode Exit fullscreen mode

Correct vs wrong feedback:

    if selected_option == correct_answer:
        self.score += 1
        self.flash_color("#00FF00")
        threading.Thread(target=self.play_sound, args=("correct.wav",)).start()
    else:
        self.flash_color("#FF4500")
        threading.Thread(target=self.play_sound, args=("wrong.wav",)).start()

    self.root.after(800, self.next_question)
Enter fullscreen mode Exit fullscreen mode

🎊 Step 9: Results Screen with Confetti

def show_result(self):
    self.clear_screen()
    self.animating = True
Enter fullscreen mode Exit fullscreen mode

Canvas setup:

    self.canvas = tk.Canvas(
        self.root,
        width=800,
        height=600,
        bg="#1E1E2F",
        highlightthickness=0
    )
    self.canvas.pack()
Enter fullscreen mode Exit fullscreen mode

Score text:

    self.result_text_id = self.canvas.create_text(
        400, 100,
        text=f"🏆 Game Over! Your Score: {self.score}/{len(self.questions)} 🏆",
        font=("Helvetica", 24, "bold"),
        fill="#FFD700"
    )
Enter fullscreen mode Exit fullscreen mode

Confetti count scales with score 🎉:

    particles_count = 50 + self.score * 50
    self.confetti_particles = []
    self.create_confetti(particles_count)
Enter fullscreen mode Exit fullscreen mode

🎈 Step 10: Confetti Animation Logic

Create particles:

def create_confetti(self, count):
    for _ in range(count):
        self.confetti_particles.append({
            "x": random.randint(0, 800),
            "y": random.randint(-600, 0),
            "size": random.randint(5, 12),
            "color": random.choice(["#FF0000", "#00FF00", "#0000FF"]),
            "speed": random.randint(3, 8)
        })
Enter fullscreen mode Exit fullscreen mode

Animate them:

def animate_confetti(self):
    if not self.animating:
        return

    self.canvas.delete("confetti")
    for p in self.confetti_particles:
        p["y"] += p["speed"]
        if p["y"] > 600:
            p["y"] = random.randint(-100, 0)

        self.canvas.create_oval(
            p["x"], p["y"],
            p["x"] + p["size"], p["y"] + p["size"],
            fill=p["color"],
            outline="",
            tags="confetti"
        )

    self.root.after(50, self.animate_confetti)
Enter fullscreen mode Exit fullscreen mode

🚀 Step 11: Run the App

if __name__ == "__main__":
    root = tk.Tk()
    game = MiniGameShow(root)
    root.mainloop()
Enter fullscreen mode Exit fullscreen mode

🧠 Final Thoughts

You’ve just built a fully interactive quiz game with:

UI state management

Timers

Threads

Animation

Sound effects

Want to extend it?

Add more categories

Load questions from a JSON file

Add difficulty levels

Add keyboard shortcuts

Top comments (0)