@@ -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
725685if __name__ == "__main__" :
726- main ()
686+ main ()
0 commit comments