Skip to content

Commit 7f59d44

Browse files
authored
PR #80: Added History Feature to Tic Tac Toe
Add move history panel to display game moves Merge pull request #80 from paltannistha/move-history-panel
2 parents a781572 + 6e339f3 commit 7f59d44

File tree

1 file changed

+66
-47
lines changed

1 file changed

+66
-47
lines changed

TIC_TAC_TOE/TIC_TAC_TOE.py

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,116 +9,135 @@
99
p1 = StringVar()
1010
p2 = 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
2219
current_player = "X"
2320
moves_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

2628
def 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-
3233
def 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

3838
def 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-
7476
def 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-
93105
def 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)
111119
for 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
115129
score_label = Label(tk, text="", font='Times 14 bold', bg='yellow')
116130
score_label.grid(row=6, column=0, columnspan=3)
117-
118131
update_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

Comments
 (0)