Python Tic-Tac-Toe AI Tutorial
Creating a Python Tic-Tac-Toe AI Tutorial offers an excellent opportunity to explore game theory, algorithms, and artificial intelligence within a straightforward and engaging setting. This project aims to develop a Tic-Tac-Toe game that allows a human player to challenge an AI opponent. The AI will utilize strategic decision-making techniques to aim for victory or, at the very least, secure a draw.
A simple game, Python Code for Tic-Tac-Toe Game, is a great introduction to minimax, alpha-beta pruning, and other AI methods. Because of the tiny size of the game tree, the minimax algorithm is ideal for a game like Tic-Tac-Toe, where every potential move can be computed. This is how we'll design the AI.
Overview of the Game
In the 3x3 grid game Tic-Tac-Toe, two players alternately mark a cell with "X" or "O." The game is won by the first player to align three markings in a horizontal, vertical, or diagonal direction. The game is a draw if no player can align three marks and every cell is filled.
Key Features of the Project:
Python Code for Tic-Tac-Toe Game: A simple interface for the player to interact with AI.
AI Opponent: The minimax algorithm is used to Implement an AI that either wins or draws.Efficient
Move Calculation: AI evaluates every possible move to determine the best one.
Game End Detection: It detects when the game ends, either in a win, loss or draw.
Step-by-Step Implementation
Step 1: Define the Game Board
Using a list of lists (2D array), we will first define the board as a 3x3 grid. Every location will be either marked "X," "O," or left unfilled.
Python Code
# Function to print the current state of the board
def print_board(board):
for row in board:
print("|".join(row))
print("-" * 5)
# Initialize a 3x3 board with empty spaces
def initialize_board():
return [[" " for _ in range(3)] for _ in range(3)]
Explanation:
Step 2: Handle Player Moves
Python Code
# Function to check if a move is valid
def is_valid_move(board, row, col):
return board[row][col] == " "
# Function to place a mark on the board
def make_move(board, row, col, player):
if is_valid_move(board, row, col):
board[row][col] = player
return True
return False
# Function to check if the game has been won
def check_winner(board, player):
# Check rows, columns, and diagonals
for row in board:
if all([cell == player for cell in row]):
return True
for col in range(3):
if all([board[row][col] == player for row 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
Explanation:
Step 3: Check for a Draw
Python Code
# Function to check if the game is a draw
def check_draw(board):
return all([cell != " " for row in board for cell in row])
Explanation:
Step 4: Implement the AI Using Minimax
Python Code
import math
def minimax(board, depth, is_maximizing):
# Check for terminal states (win, loss, or draw)
if check_winner(board, "O"): # AI wins
return 1
elif check_winner(board, "X"): # Human wins
return -1
elif check_draw(board):
return 0
# Maximizing player's turn (AI)
if is_maximizing:
best_score = -math.inf
for row in range(3):
for col in range(3):
if is_valid_move(board, row, col):
board[row][col] = "O"
score = minimax(board, depth + 1, False)
board[row][col] = " " # Undo the move
best_score = max(score, best_score)
return best_score
# Minimizing the player's turn (Human)
else:
best_score = math.inf
for row in range(3):
for col in range(3):
if is_valid_move(board, row, col):
board[row][col] = "X"
score = minimax(board, depth + 1, True)
board[row][col] = " " # Undo the move
best_score = min(score, best_score)
return best_score
Explanation:
Step 5: AI Move Function
Explanation:
Step 6: Game Loop and User Interaction
Python Code
def tic_tac_toe():
board = initialize_board()
print_board(board)
while True:
# Human's turn (Player X)
row, col = map(int, input("Enter your move (row and column): ").split())
if make_move(board, row, col, "X"):
print_board(board)
if check_winner(board, "X"):
print("Congratulations! You won!")
break
if check_draw(board):
print("It's a draw!")
break
# AI's turn (Player O)
row, col = best_move(board)
make_move(board, row, col, "O")
print("AI's move:")
print_board(board)
if check_winner(board, "O"):
print("The AI won!")
break
if check_draw(board):
print("It's a draw!")
break
else:
print("Invalid move. Try again.")
Explanation:
Python Code
import math
def print_board(board):
for row in board:
print("|".join(row))
print("-" * 5)
def initialize_board():
return [[" " for _ in range(3)] for _ in range(3)]
def is_valid_move(board, row, col):
return board[row][col] == " "
def make_move(board, row, col, player):
if is_valid_move(board, row, col):
board[row][col] = player
return True
return False
def check_winner(board, player):
for row in board:
if all([cell == player for cell in row]):
return True
for col in range(3):
if all([board[row][col] == player for row 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 check_draw(board):
return all([cell != " " for row in board for cell in row])
def minimax(board, depth, is_maximizing):
if check_winner(board, "O"):
return 1
elif check_winner(board, "X"):
return -1
elif check_draw(board):
return 0
if is_maximizing:
best_score = -math.inf
for row in range(3):
for col in range(3):
if is_valid_move(board, row, col):
board[row][col] = "O"
score = minimax(board, depth + 1, False)
board[row][col] = " "
best_score = max(score, best_score)
return best_score
else:
best_score = math.inf
for row in range(3):
for col in range(3):
if is_valid_move(board, row, col):
board[row][col] = "X"
score = minimax(board, depth + 1, True)
board[row][col] = " "
best_score = min(score, best_score)
return best_score
def best_move(board):
best_score = -math.inf
move = None
for row in range(3):
for col in range(3):
if is_valid_move(board, row, col):
board[row][col] = "O"
score = minimax(board, 0, False)
board[row][col] = " "
if score > best_score:
best_score = score
move = (row, col)
return move
def tic_tac_toe():
board = initialize_board()
print_board(board)
while True:
row, col = map(int, input("Enter your move (row and column): ").split())
if make_move(board, row, col, "X"):
print_board(board)
if check_winner(board, "X"):
print("Congratulations! You won!")
break
if check_draw(board):
print("It's a draw!")
break
row, col = best_move(board)
make_move(board, row, col, "O")
print("AI's move:")
print_board(board)
if check_winner(board, "O"):
print("The AI won!")
break
if check_draw(board):
print("It's a draw!")
break
else:
print("Invalid move. Try again.")
if __name__ == "__main__":
tic_tac_toe()