99p1 = StringVar ()
1010p2 = StringVar ()
1111
12- player1_name = Entry (tk , textvariable = p1 , bd = 5 , bg = 'white' , width = 40 )
13- player1_name .grid (row = 1 , column = 1 , columnspan = 8 )
12+ Entry (tk , textvariable = p1 , bd = 5 , bg = 'white' , width = 40 ). grid ( row = 1 , column = 1 , columnspan = 3 )
13+ Entry ( tk , textvariable = p2 , bd = 5 , bg = 'white' , width = 40 ) .grid (row = 2 , column = 1 , columnspan = 3 )
1414
15- player2_name = Entry (tk , textvariable = p2 , bd = 5 , bg = 'white' , width = 40 )
16- player2_name .grid (row = 2 , column = 1 , columnspan = 8 )
17-
18- # Score tracking
19- score_p1 = 0
20- score_p2 = 0
15+ Label (tk , text = "Player 1:" , font = 'Times 20 bold' , bg = 'yellow' ).grid (row = 1 , column = 0 )
16+ Label (tk , text = "Player 2:" , font = 'Times 20 bold' , bg = 'yellow' ).grid (row = 2 , column = 0 )
2117
18+ # Game state
2219current_player = "X"
2320moves_count = 0
21+ score_p1 = 0
22+ score_p2 = 0
23+ move_number = 1
2424
25+ # Buttons
26+ buttons = [[None for _ in range (3 )] for _ in range (3 )]
2527
2628def update_scoreboard ():
2729 score_label .config (
28- text = f"{ p1 .get () or 'Player 1' } (X): { score_p1 } | { p2 .get () or 'Player 2' } (O): { score_p2 } "
30+ text = f"{ p1 .get () or 'Player 1' } (X): { score_p1 } | { p2 .get () or 'Player 2' } (O): { score_p2 } "
2931 )
3032
31-
3233def disable_buttons ():
3334 for row in buttons :
34- for button in row :
35- button .config (state = DISABLED )
36-
35+ for b in row :
36+ b .config (state = DISABLED )
3737
3838def check_winner ():
3939 global score_p1 , score_p2
4040
4141 win_positions = [
42- [(0 , 0 ), (0 , 1 ), (0 , 2 )],
43- [(1 , 0 ), (1 , 1 ), (1 , 2 )],
44- [(2 , 0 ), (2 , 1 ), (2 , 2 )],
45- [(0 , 0 ), (1 , 0 ), (2 , 0 )],
46- [(0 , 1 ), (1 , 1 ), (2 , 1 )],
47- [(0 , 2 ), (1 , 2 ), (2 , 2 )],
48- [(0 , 0 ), (1 , 1 ), (2 , 2 )],
49- [(0 , 2 ), (1 , 1 ), (2 , 0 )]
42+ [(0 ,0 ),(0 ,1 ),(0 ,2 )],
43+ [(1 ,0 ),(1 ,1 ),(1 ,2 )],
44+ [(2 ,0 ),(2 ,1 ),(2 ,2 )],
45+ [(0 ,0 ),(1 ,0 ),(2 ,0 )],
46+ [(0 ,1 ),(1 ,1 ),(2 ,1 )],
47+ [(0 ,2 ),(1 ,2 ),(2 ,2 )],
48+ [(0 ,0 ),(1 ,1 ),(2 ,2 )],
49+ [(0 ,2 ),(1 ,1 ),(2 ,0 )]
5050 ]
5151
5252 for combo in win_positions :
5353 if buttons [combo [0 ][0 ]][combo [0 ][1 ]]["text" ] == \
5454 buttons [combo [1 ][0 ]][combo [1 ][1 ]]["text" ] == \
5555 buttons [combo [2 ][0 ]][combo [2 ][1 ]]["text" ] != " " :
5656
57+ # ✅ Highlight winning cells
58+ for pos in combo :
59+ buttons [pos [0 ]][pos [1 ]].config (bg = "green" )
60+
5761 winner_symbol = buttons [combo [0 ][0 ]][combo [0 ][1 ]]["text" ]
5862
5963 if winner_symbol == "X" :
6064 score_p1 += 1
61- winner_name = p1 .get () or "Player 1"
65+ winner = p1 .get () or "Player 1"
6266 else :
6367 score_p2 += 1
64- winner_name = p2 .get () or "Player 2"
68+ winner = p2 .get () or "Player 2"
6569
6670 update_scoreboard ()
71+ messagebox .showinfo ("Winner" , f"{ winner } wins!" )
6772 disable_buttons ()
68- messagebox .showinfo ("Winner" , f"{ winner_name } wins!" )
6973 return True
70-
7174 return False
7275
73-
7476def button_click (row , col ):
75- global current_player , moves_count
77+ global current_player , moves_count , move_number
7678
7779 if buttons [row ][col ]["text" ] == " " :
7880 buttons [row ][col ]["text" ] = current_player
81+
82+ # ✅ Move History
83+ player = p1 .get () if current_player == "X" else p2 .get ()
84+ player = player or ("Player 1" if current_player == "X" else "Player 2" )
85+
86+ move = f"{ move_number } . { player } -> ({ row + 1 } ,{ col + 1 } )"
87+ history_box .insert (END , move + "\n " )
88+
89+ move_number += 1
7990 moves_count += 1
8091
8192 if check_winner ():
8293 return
8394
8495 if moves_count == 9 :
8596 messagebox .showinfo ("Tie" , "It's a Tie!" )
97+ disable_buttons () # ✅ prevent extra clicks
8698 return
8799
88100 current_player = "O" if current_player == "X" else "X"
101+
89102 else :
90103 messagebox .showinfo ("Invalid Move" , "Button already clicked!" )
91104
92-
93105def reset_game ():
94- global current_player , moves_count
106+ global current_player , moves_count , move_number
107+
95108 current_player = "X"
96109 moves_count = 0
110+ move_number = 1
97111
98- for row in buttons :
99- for button in row :
100- button .config (text = " " , state = NORMAL )
112+ history_box .delete (1.0 , END )
101113
114+ for i in range (3 ):
115+ for j in range (3 ):
116+ buttons [i ][j ].config (text = " " , bg = "black" , state = NORMAL )
102117
103- Label (tk , text = "Player 1:" , font = 'Times 20 bold' , bg = 'yellow' ).grid (row = 1 , column = 0 )
104- Label (tk , text = "Player 2:" , font = 'Times 20 bold' , bg = 'yellow' ).grid (row = 2 , column = 0 )
105-
106- buttons = [[Button (tk , text = " " , font = 'Times 20 bold' , bg = 'black' ,
107- fg = 'white' , height = 4 , width = 8 ,
108- command = lambda r = i , c = j : button_click (r , c ))
109- for j in range (3 )] for i in range (3 )]
110-
118+ # Create buttons (safe version)
111119for i in range (3 ):
112120 for j in range (3 ):
113- buttons [i ][j ].grid (row = i + 3 , column = j )
114-
121+ buttons [i ][j ] = Button (
122+ tk , text = " " , font = 'Times 20 bold' , bg = 'black' , fg = 'white' ,
123+ height = 4 , width = 8 ,
124+ command = lambda r = i , c = j : button_click (r , c )
125+ )
126+ buttons [i ][j ].grid (row = i + 3 , column = j )
127+
128+ # Scoreboard
115129score_label = Label (tk , text = "" , font = 'Times 14 bold' , bg = 'yellow' )
116130score_label .grid (row = 6 , column = 0 , columnspan = 3 )
117-
118131update_scoreboard ()
119132
120- reset_btn = Button (tk , text = "Reset Game" , font = 'Times 16 bold' ,
121- command = reset_game )
122- reset_btn .grid (row = 7 , column = 0 , columnspan = 3 )
133+ # Reset button
134+ Button (tk , text = "Reset Game" , font = 'Times 16 bold' ,
135+ command = reset_game ).grid (row = 7 , column = 0 , columnspan = 3 )
136+
137+ # Move history UI
138+ Label (tk , text = "Move History" , font = 'Times 16 bold' , bg = 'yellow' ).grid (row = 0 , column = 5 )
139+
140+ history_box = Text (tk , height = 18 , width = 28 , font = ("Consolas" , 11 ))
141+ history_box .grid (row = 1 , column = 5 , rowspan = 6 )
123142
124- tk .mainloop ()
143+ tk .mainloop ()
0 commit comments