Skip to content

Commit 6b898b8

Browse files
authored
Interface was build to tic-tac-toe
An Interface using pygame was build for the game and game will be in loop untill user closes it. The inteface was build in a way such that it shows different colors for different situations.
1 parent 902948d commit 6b898b8

File tree

1 file changed

+163
-97
lines changed

1 file changed

+163
-97
lines changed

AI Game/Tic-Tac-Toe-AI/tictactoe.py

+163-97
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,170 @@
1-
import tkinter as tk #provides a library of basic elements of GUI widgets
2-
from tkinter import messagebox #provides a different set of dialogues that are used to display message boxes
3-
import random
4-
5-
def check_winner(board, player):
6-
# Check rows, columns, and diagonals for a win
7-
for i in range(3):
8-
if all(board[i][j] == player for j in range(3)) or all(board[j][i] == player for j in range(3)):
1+
import sys
2+
import numpy as np
3+
import pygame
4+
5+
pygame.init()
6+
WHITE = (255, 255, 255)
7+
GRAY = (180, 180, 180)
8+
RED = (255, 0, 0)
9+
GREEN = (0, 255, 0)
10+
BLACK = (0, 0, 0)
11+
12+
WIDTH = 300
13+
HEIGHT = 300
14+
BOARD_ROWS = 3
15+
BOARD_COLS = 3
16+
SQUARE_SIZE = WIDTH // BOARD_COLS
17+
CIRCLE_RADIUS = SQUARE_SIZE // 3
18+
CIRCLE_WIDTH = 15
19+
CROSS_WIDTH = 25
20+
21+
screen = pygame.display.set_mode((WIDTH, HEIGHT))
22+
pygame.display.set_caption("TIC TAC WITH AI")
23+
screen.fill(BLACK)
24+
board = np.zeros((BOARD_ROWS, BOARD_COLS))
25+
26+
def draw_lines(color=WHITE):
27+
for i in range(1, BOARD_ROWS):
28+
pygame.draw.line(screen, color, start_pos=(0, SQUARE_SIZE * i), end_pos=(WIDTH, SQUARE_SIZE * i))
29+
pygame.draw.line(screen, color, start_pos=(SQUARE_SIZE * i, 0), end_pos=(SQUARE_SIZE * i, WIDTH))
30+
31+
def draw_figure(color=WHITE):
32+
for row in range(BOARD_ROWS):
33+
for col in range(BOARD_COLS):
34+
if board[row][col] == 1:
35+
pygame.draw.circle(screen, color, (int(col * SQUARE_SIZE + SQUARE_SIZE // 2), int(row * SQUARE_SIZE + SQUARE_SIZE // 2)), CIRCLE_RADIUS, CIRCLE_WIDTH)
36+
elif board[row][col] == 2:
37+
pygame.draw.line(screen, color, (col * SQUARE_SIZE + SQUARE_SIZE // 4, row * SQUARE_SIZE + SQUARE_SIZE // 4), (col * SQUARE_SIZE + 3 * SQUARE_SIZE // 4, row * SQUARE_SIZE + 3 * SQUARE_SIZE // 4), CROSS_WIDTH)
38+
pygame.draw.line(screen, color, (col * SQUARE_SIZE + SQUARE_SIZE // 4, row * SQUARE_SIZE + 3 * SQUARE_SIZE // 4), (col * SQUARE_SIZE + 3 * SQUARE_SIZE // 4, row * SQUARE_SIZE + SQUARE_SIZE // 4), CROSS_WIDTH)
39+
40+
def mark_square(row, col, player):
41+
board[row][col] = player
42+
43+
def available_square(row, col):
44+
return board[row][col] == 0
45+
46+
def is_board_full(check_board=board):
47+
for row in range(BOARD_ROWS):
48+
for col in range(BOARD_COLS):
49+
if check_board[row][col] == 0:
50+
return False
51+
return True
52+
53+
def check_win(player, check_board=board):
54+
for col in range(BOARD_COLS):
55+
if check_board[0][col] == player and check_board[1][col] == player and check_board[2][col] == player:
956
return True
10-
if all(board[i][i] == player for i in range(3)) or all(board[i][2 - i] == player for i in range(3)):
57+
for row in range(BOARD_ROWS):
58+
if check_board[row][0] == player and check_board[row][1] == player and check_board[row][2] == player:
59+
return True
60+
if check_board[0][0] == player and check_board[1][1] == player and check_board[2][2] == player:
61+
return True
62+
if check_board[0][2] == player and check_board[1][1] == player and check_board[2][0] == player:
1163
return True
1264
return False
1365

14-
def is_board_full(board):
15-
return all(all(cell != ' ' for cell in row) for row in board)
16-
17-
def minimax(board, depth, is_maximizing):
18-
if check_winner(board, 'X'):
19-
return -1
20-
if check_winner(board, 'O'):
21-
return 1
22-
if is_board_full(board): #if game is full, terminate
66+
def minimax(minimax_board, depth, is_maximizing):
67+
if check_win(2, minimax_board):
68+
return 1000 - depth
69+
elif check_win(1, minimax_board):
70+
return depth - 1000
71+
elif is_board_full(minimax_board):
2372
return 0
2473

25-
if is_maximizing: #recursive approach that fills board with Os
26-
max_eval = float('-inf')
27-
for i in range(3):
28-
for j in range(3):
29-
if board[i][j] == ' ':
30-
board[i][j] = 'O'
31-
eval = minimax(board, depth + 1, False) #recursion
32-
board[i][j] = ' '
33-
max_eval = max(max_eval, eval)
34-
return max_eval
35-
else: #recursive approach that fills board with Xs
36-
min_eval = float('inf')
37-
for i in range(3):
38-
for j in range(3):
39-
if board[i][j] == ' ':
40-
board[i][j] = 'X'
41-
eval = minimax(board, depth + 1, True) #recursion
42-
board[i][j] = ' '
43-
min_eval = min(min_eval, eval)
44-
return min_eval
45-
46-
#determines the best move for the current player and returns a tuple representing the position
47-
def best_move(board):
48-
best_val = float('-inf')
49-
best_move = None
50-
51-
for i in range(3):
52-
for j in range(3):
53-
if board[i][j] == ' ':
54-
board[i][j] = 'O'
55-
move_val = minimax(board, 0, False)
56-
board[i][j] = ' '
57-
if move_val > best_val:
58-
best_val = move_val
59-
best_move = (i, j)
60-
61-
return best_move
62-
63-
def make_move(row, col):
64-
if board[row][col] == ' ':
65-
board[row][col] = 'X'
66-
buttons[row][col].config(text='X')
67-
if check_winner(board, 'X'):
68-
messagebox.showinfo("Tic-Tac-Toe", "You win!")
69-
root.quit()
70-
elif is_board_full(board):
71-
messagebox.showinfo("Tic-Tac-Toe", "It's a draw!")
72-
root.quit()
73-
else:
74-
ai_move()
74+
if is_maximizing:
75+
best_score = float('-inf')
76+
for row in range(BOARD_ROWS):
77+
for col in range(BOARD_COLS):
78+
if minimax_board[row][col] == 0:
79+
minimax_board[row][col] = 2
80+
score = minimax(minimax_board, depth + 1, False)
81+
minimax_board[row][col] = 0
82+
best_score = max(score, best_score)
83+
return best_score
7584
else:
76-
messagebox.showerror("Error", "Invalid move")
77-
78-
#AI's turn to play
79-
def ai_move():
80-
row, col = best_move(board)
81-
board[row][col] = 'O'
82-
buttons[row][col].config(text='O')
83-
if check_winner(board, 'O'):
84-
messagebox.showinfo("Tic-Tac-Toe", "AI wins!")
85-
root.quit()
86-
elif is_board_full(board):
87-
messagebox.showinfo("Tic-Tac-Toe", "It's a draw!")
88-
root.quit()
89-
90-
root = tk.Tk()
91-
root.title("Tic-Tac-Toe")
92-
93-
board = [[' ' for _ in range(3)] for _ in range(3)]
94-
buttons = []
95-
96-
for i in range(3):
97-
row_buttons = []
98-
for j in range(3):
99-
button = tk.Button(root, text=' ', font=('normal', 30), width=5, height=2, command=lambda row=i, col=j: make_move(row, col))
100-
button.grid(row=i, column=j)
101-
row_buttons.append(button)
102-
buttons.append(row_buttons)
103-
104-
root.mainloop()
85+
best_score = float('inf')
86+
for row in range(BOARD_ROWS):
87+
for col in range(BOARD_COLS):
88+
if minimax_board[row][col] == 0:
89+
minimax_board[row][col] = 1
90+
score = minimax(minimax_board, depth + 1, True)
91+
# print(score)
92+
minimax_board[row][col] = 0
93+
best_score = min(score, best_score)
94+
return best_score
95+
96+
def best_move():
97+
best_score = float('-inf')
98+
move = (-1, -1)
99+
for row in range(BOARD_ROWS):
100+
for col in range(BOARD_COLS):
101+
if board[row][col] == 0:
102+
board[row][col] = 2
103+
score = minimax(board, 0, False)
104+
board[row][col] = 0
105+
if score > best_score:
106+
best_score = score
107+
move = (row, col)
108+
if move != (-1, -1):
109+
mark_square(move[0], move[1], 2)
110+
return True
111+
return False
112+
113+
def restart_game():
114+
screen.fill(BLACK)
115+
draw_lines()
116+
for row in range(BOARD_ROWS):
117+
for col in range(BOARD_COLS):
118+
board[row][col] = 0
119+
120+
draw_lines()
121+
player = 1
122+
game_over = False
123+
124+
while True:
125+
for event in pygame.event.get():
126+
if event.type == pygame.QUIT:
127+
pygame.quit()
128+
sys.exit()
129+
if event.type == pygame.MOUSEBUTTONDOWN and not game_over:
130+
mouseX = event.pos[0] // SQUARE_SIZE
131+
mouseY = event.pos[1] // SQUARE_SIZE
132+
133+
if available_square(mouseY, mouseX):
134+
mark_square(mouseY, mouseX, player)
135+
if check_win(player):
136+
game_over = True
137+
player = player % 2 + 1
138+
139+
if not game_over:
140+
if best_move():
141+
if check_win(2):
142+
game_over = True
143+
player = player % 2 + 1
144+
if not game_over:
145+
if is_board_full():
146+
game_over = True
147+
if event.type == pygame.KEYDOWN:
148+
if event.key == pygame.K_r:
149+
restart_game()
150+
game_over = False
151+
player = 1
152+
153+
draw_figure()
154+
pygame.display.update()
155+
156+
if game_over:
157+
if check_win(1):
158+
draw_figure(GREEN)
159+
draw_lines(GREEN)
160+
elif check_win(2):
161+
draw_figure(RED)
162+
draw_lines(RED)
163+
else:
164+
draw_figure(GRAY)
165+
draw_lines(GRAY)
166+
pygame.display.update()
167+
pygame.time.wait(3000)
168+
restart_game()
169+
game_over = False
170+
player = 1

0 commit comments

Comments
 (0)