Skip to content

Commit 1efa687

Browse files
Merge pull request steam-bell-92#1149 from yuvraj-k-singh/bug/mathQuiz-game
[Bug]: Game crash / failure to pause due to uninitialized game_paused attribute in math_quiz.py
2 parents 815836d + 591ede2 commit 1efa687

1 file changed

Lines changed: 80 additions & 120 deletions

File tree

games/Math-Quiz/Math-Quiz.py

Lines changed: 80 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ def __init__(self, root):
228228
self.root.geometry("900x650")
229229
self.root.resizable(False, False)
230230

231+
# Flag initializations to prevent uninitialized bugs
232+
self.game_active = False
233+
self.game_paused = False
234+
231235
# Background Canvas for Gradient
232236
self.bg_canvas = tk.Canvas(self.root, width=900, height=650,
233237
highlightthickness=0)
@@ -251,9 +255,9 @@ def clear_panel(self):
251255
def create_home_screen(self):
252256
self.clear_panel()
253257
self.game_active = False
258+
self.game_paused = False
254259

255260
self.root.bind("<Escape>", self.handle_escape)
256-
257261

258262
title = tk.Label(self.main_panel, text="🧠 MATH QUIZ",
259263
font=("Helvetica", 36, "bold"),
@@ -332,6 +336,9 @@ def start_game(self):
332336
self.hardest_question_time = 0
333337
self.hardest_question = "None"
334338

339+
self.game_active = True
340+
self.game_paused = False
341+
335342
if self.selected_difficulty == 4:
336343
self.difficulty = 1
337344
else:
@@ -361,6 +368,7 @@ def create_game_screen(self):
361368
font=("Helvetica", 16),
362369
fg="white", bg="#0f172a")
363370
self.lives_label.pack(side="right", padx=15)
371+
364372
pause_btn = RoundedButton(
365373
top_frame,
366374
text="⏸ Pause",
@@ -397,17 +405,14 @@ def create_game_screen(self):
397405
self.option_cells = []
398406

399407
for i in range(4):
400-
# Outer cell frame
401408
cell = tk.Frame(self.options_frame, bg="#1e293b")
402409
cell.grid(row=i // 2, column=i % 2, padx=12, pady=10)
403410

404-
# Inner frame to hold circle + button side by side
405411
inner = tk.Frame(cell, bg="#0f172a",
406412
highlightthickness=1,
407413
highlightbackground="#334155")
408414
inner.pack()
409415

410-
# Circle label with A / B / C / D
411416
circle_lbl = tk.Label(inner,
412417
text=LABELS[i],
413418
font=("Helvetica", 13, "bold"),
@@ -420,7 +425,6 @@ def create_game_screen(self):
420425
pady=8)
421426
circle_lbl.pack(side="left")
422427

423-
# Answer button
424428
btn = RoundedButton(inner, text="Option",
425429
width=240, height=50,
426430
bg="#0f172a",
@@ -431,7 +435,6 @@ def create_game_screen(self):
431435

432436
self.option_buttons.append(btn)
433437
self.option_cells.append(cell)
434-
# ────────────────────────────────────────────────
435438

436439
self.feedback_label = tk.Label(self.main_panel, text="",
437440
font=("Helvetica", 18, "bold"),
@@ -443,75 +446,88 @@ def update_status(self):
443446
self.score_label.config(text=f"⭐ Score: {self.score}")
444447
self.streak_label.config(text=f"🔥 Streak: {self.streak}")
445448
self.lives_label.config(text=hearts)
446-
# Pause Menu Implemented
447-
def toggle_pause(self):
448-
self.game_paused = not self.game_paused
449-
if self.game_paused:
450-
self.pause_window = tk.Toplevel(self.root)
451-
self.pause_window.title("Paused")
452-
self.pause_window.geometry("300x220")
453-
self.pause_window.resizable(False, False)
454-
self.pause_window.configure(bg="#1e293b")
455-
self.pause_window.transient(self.root)
456-
self.pause_window.grab_set()
457-
458-
pause_label = tk.Label(
459-
self.pause_window,
460-
text="⏸ GAME PAUSED",
461-
font=("Helvetica", 20, "bold"),
462-
fg="white",
463-
bg="#1e293b"
464-
)
465-
pause_label.pack(pady=25)
466-
467-
resume_btn = RoundedButton(
468-
self.pause_window,
469-
text="▶ Resume",
470-
width=180,
471-
height=45,
472-
bg="#10b981",
473-
active_bg="#059669",
474-
font=("Helvetica", 13, "bold"),
475-
command=self.resume_game
476-
477-
)
478-
resume_btn.pack(pady=10)
479-
480-
menu_btn = RoundedButton(
481-
self.pause_window,
482-
text="🏠 Main Menu",
483-
width=180,
484-
height=45,
485-
bg="#ef4444",
486-
active_bg="#b91c1c",
487-
font=("Helvetica", 13, "bold"),
488-
command=self.return_to_menu
489-
)
490-
menu_btn.pack(pady=10)
491-
for btn in self.option_buttons:
492-
btn.command = None
493-
else:
494-
self.resume_game()
495-
449+
496450
def handle_escape(self, event=None):
497451
if self.game_active:
498-
self.toggle_pause()
452+
self.pause_game()
499453
else:
500454
self.root.destroy()
455+
456+
def pause_game(self):
457+
if self.game_paused:
458+
return
459+
self.game_paused = True
460+
461+
# Strip button commands temporarily to block interactive triggers
462+
for btn in self.option_buttons:
463+
btn.command = None
501464

465+
self.pause_window = tk.Toplevel(self.root)
466+
self.pause_window.title("Paused")
467+
self.pause_window.geometry("320x220")
468+
self.pause_window.configure(bg="#1e293b")
469+
self.pause_window.resizable(False, False)
470+
self.pause_window.transient(self.root)
471+
self.pause_window.grab_set()
472+
473+
tk.Label(
474+
self.pause_window,
475+
text="⏸ GAME PAUSED",
476+
font=("Helvetica", 22, "bold"),
477+
fg="white",
478+
bg="#1e293b"
479+
).pack(pady=25)
480+
481+
resume_btn = RoundedButton(
482+
self.pause_window,
483+
text="▶ Resume",
484+
width=180,
485+
height=45,
486+
bg="#10b981",
487+
active_bg="#059669",
488+
font=("Helvetica", 13, "bold"),
489+
command=self.resume_game
490+
)
491+
resume_btn.pack(pady=10)
492+
493+
home_btn = RoundedButton(
494+
self.pause_window,
495+
text="🏠 Home Menu",
496+
width=180,
497+
height=45,
498+
bg="#ef4444",
499+
active_bg="#b91c1c",
500+
font=("Helvetica", 13, "bold"),
501+
command=self.return_to_menu
502+
)
503+
home_btn.pack(pady=10)
504+
505+
self.pause_window.protocol("WM_DELETE_WINDOW", self.resume_game)
506+
502507
def resume_game(self):
503508
self.game_paused = False
504-
if hasattr(self, "pause_window"):
509+
if hasattr(self, "pause_window") and self.pause_window.winfo_exists():
505510
self.pause_window.destroy()
506511

507-
options = [btn.itemcget(btn.text_item, "text") for btn in self.option_buttons]
508-
for btn, option in zip(self.option_buttons, options):
509-
510-
btn.command = lambda opt=option: self.check_answer(opt)
512+
# Safely restore context bindings matching current layouts
513+
for btn in self.option_buttons:
514+
option_text = btn.itemcget(btn.text_item, "text")
515+
if option_text in ["Yes", "No"]:
516+
btn.command = lambda opt=option_text: self.check_answer(opt)
517+
elif '.' in option_text:
518+
try:
519+
btn.command = lambda opt=float(option_text): self.check_answer(opt)
520+
except ValueError:
521+
btn.command = lambda opt=option_text: self.check_answer(opt)
522+
else:
523+
try:
524+
btn.command = lambda opt=int(option_text): self.check_answer(opt)
525+
except ValueError:
526+
btn.command = lambda opt=option_text: self.check_answer(opt)
511527

512528
def return_to_menu(self):
513529
self.game_paused = False
514-
if hasattr(self, "pause_window"):
530+
if hasattr(self, "pause_window") and self.pause_window.winfo_exists():
515531
self.pause_window.destroy()
516532
self.create_home_screen()
517533

@@ -537,7 +553,6 @@ def load_question(self):
537553
for btn, option in zip(self.option_buttons, options):
538554
btn.config_text(str(option))
539555
btn.command = lambda opt=option: self.check_answer(opt)
540-
# Reset button color on new question
541556
btn.itemconfig(btn.rect, fill="#0f172a")
542557
btn.itemconfig(btn.text_item, fill="white")
543558
btn.bg_color = "#0f172a"
@@ -589,61 +604,6 @@ def check_answer(self, selected):
589604
self.root.after(1500, self.game_over)
590605
else:
591606
self.root.after(1200, self.load_question)
592-
593-
# Pause menu implemented
594-
def pause_game(self):
595-
if self.game_paused:
596-
return
597-
self.game_paused = True
598-
pause_window = tk.Toplevel(self.root)
599-
pause_window.title("Paused")
600-
pause_window.geometry("320x220")
601-
pause_window.configure(bg="#1e293b")
602-
pause_window.resizable(False, False)
603-
604-
tk.Label(
605-
pause_window,
606-
text="⏸ GAME PAUSED",
607-
font=("Helvetica", 22, "bold"),
608-
fg="white",
609-
bg="#1e293b"
610-
).pack(pady=25)
611-
612-
def resume_game():
613-
self.game_paused = False
614-
pause_window.destroy()
615-
616-
def return_home():
617-
self.game_paused = False
618-
pause_window.destroy()
619-
self.create_home_screen()
620-
621-
622-
resume_btn = RoundedButton(
623-
pause_window,
624-
text="▶ Resume",
625-
width=180,
626-
height=45,
627-
bg="#10b981",
628-
active_bg="#059669",
629-
font=("Helvetica", 13, "bold"),
630-
command=resume_game
631-
)
632-
resume_btn.pack(pady=10)
633-
634-
home_btn = RoundedButton(
635-
pause_window,
636-
text="🏠 Home Menu",
637-
width=180,
638-
height=45,
639-
bg="#ef4444",
640-
active_bg="#b91c1c",
641-
font=("Helvetica", 13, "bold"),
642-
command=return_home
643-
)
644-
home_btn.pack(pady=10)
645-
646-
pause_window.protocol("WM_DELETE_WINDOW", resume_game)
647607

648608
def get_grade(self, accuracy):
649609
if accuracy >= 90: return "S 🌟"
@@ -723,4 +683,4 @@ def main():
723683
root.mainloop()
724684

725685
if __name__ == "__main__":
726-
main()
686+
main()

0 commit comments

Comments
 (0)