-
Notifications
You must be signed in to change notification settings - Fork 12.5k
/
Copy pathtictactoe.py
130 lines (112 loc) · 4.3 KB
/
tictactoe.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import tkinter as tk
from tkinter import messagebox
def check_winner(board, player):
# Check rows, columns, and diagonals for a win
for i in range(3):
if all(board[i][j] == player for j in range(3)) or all(board[j][i] == player for j in range(3)):
return True
if all(board[i][i] == player for i in range(3)) or all(board[i][2 - i] == player for i in range(3)):
return True
return False
def is_board_full(board):
return all(all(cell != ' ' for cell in row) for row in board)
# Alpha-Beta Pruning version of minimax
def minimax(board, depth, is_maximizing, alpha, beta):
if check_winner(board, 'X'):
return -1
if check_winner(board, 'O'):
return 1
if is_board_full(board):
return 0
if is_maximizing:
max_eval = float('-inf')
for i in range(3):
for j in range(3):
if board[i][j] == ' ':
board[i][j] = 'O'
eval = minimax(board, depth + 1, False, alpha, beta)
board[i][j] = ' '
max_eval = max(max_eval, eval)
alpha = max(alpha, eval)
if beta <= alpha:
break # Prune
return max_eval
else:
min_eval = float('inf')
for i in range(3):
for j in range(3):
if board[i][j] == ' ':
board[i][j] = 'X'
eval = minimax(board, depth + 1, True, alpha, beta)
board[i][j] = ' '
min_eval = min(min_eval, eval)
beta = min(beta, eval)
if beta <= alpha:
break # Prune
return min_eval
# Determine the best move for AI with move prioritization
def best_move(board):
best_val = float('-inf')
best_move = None
# Prioritize center, then corners, then edges
move_order = [(1, 1), (0, 0), (0, 2), (2, 0), (2, 2), (0, 1), (1, 0), (1, 2), (2, 1)]
for i, j in move_order:
if board[i][j] == ' ':
board[i][j] = 'O'
move_val = minimax(board, 0, False, float('-inf'), float('inf'))
board[i][j] = ' '
if move_val > best_val:
best_val = move_val
best_move = (i, j)
return best_move
def make_move(row, col):
if board[row][col] == ' ':
board[row][col] = 'X'
buttons[row][col].config(text='X')
if check_winner(board, 'X'):
messagebox.showinfo("Tic-Tac-Toe", "You win!")
root.quit()
elif is_board_full(board):
messagebox.showinfo("Tic-Tac-Toe", "It's a draw!")
root.quit()
else:
root.after(200, ai_move) # Delay AI move slightly to improve responsiveness
else:
messagebox.showerror("Error", "Invalid move")
def ai_move():
row, col = best_move(board)
board[row][col] = 'O'
buttons[row][col].config(text='O')
if check_winner(board, 'O'):
messagebox.showinfo("Tic-Tac-Toe", "AI wins!")
root.quit()
elif is_board_full(board):
messagebox.showinfo("Tic-Tac-Toe", "It's a draw!")
root.quit()
def player_first():
first_turn.set('player')
def ai_first():
first_turn.set('ai')
root.after(200, ai_move) # Slight delay to ensure smooth AI move
root = tk.Tk()
root.title("Tic-Tac-Toe")
# Variable to track who goes first
first_turn = tk.StringVar()
first_turn.set('player')
board = [[' ' for _ in range(3)] for _ in range(3)]
buttons = []
# Create the buttons for the Tic-Tac-Toe board
for i in range(3):
row_buttons = []
for j in range(3):
button = tk.Button(root, text=' ', font=('normal', 30), width=5, height=2, command=lambda row=i, col=j: make_move(row, col))
button.grid(row=i, column=j)
row_buttons.append(button)
buttons.append(row_buttons)
# Create a window asking the player if they want to go first or second
choice_window = tk.Toplevel(root)
choice_window.title("Choose Turn")
tk.Label(choice_window, text="Do you want to go first or second?", font=('normal', 14)).pack(pady=10)
tk.Button(choice_window, text="First", command=lambda: [choice_window.destroy(), player_first()]).pack(pady=5)
tk.Button(choice_window, text="Second", command=lambda: [choice_window.destroy(), ai_first()]).pack(pady=5)
root.mainloop()