Tic Tac Toe is a well-known, straightforward game that serves as an excellent tool for illustrating fundamental programming principles.
In this article, we will walk you through the process of developing a Tic Tac Toe game using Python.
Initially, the game will be designed for two human players, and later, we will enhance it by incorporating an artificial intelligence (AI) opponent.
The game will utilize the command line for both input and output.
If you want a more visual implementation built with Pygame, check this article: https://developer-service.blog/how-to-make-a-tic-tac-toe-game-in-pygame/
Step 1: Setting Up the Game Board
Let's start our game by creating a main.py
file.
First, we need to create the game board. A Tic Tac Toe board is a 3x3 grid:
# Create a 3x3 board
def create_board():
return [[' ' for _ in range(3)] for _ in range(3)]
# Print the board
def print_board(board):
for row in board:
print('|'.join(row))
print('-' * 5)
# Main function to run the game
if __name__ == '__main__':
_board = create_board()
print_board(_board)
This code defines two functions, create_board()
and print_board(board)
, which are used to create and display a 3x3 Tic Tac Toe game board.
create_board()
: This function generates a 3x3 board by creating a list of lists, where each inner list represents a row, and each element in the inner list represents a column. The elements are initialized with a single space character (' '), indicating an empty cell on the board.print_board(_board)
: This function takes a 3x3 board (a list of lists) as an input and prints it in a visually appealing format. It iterates through each row of the board and uses the'|'.join(row)
method to join the elements within a row with a vertical bar ('|') as a separator. After printing each row, it also prints a horizontal line of five dashes ('-') to separate the rows visually. This creates the appearance of a grid.if __name__ == '__main__'
: main function that runs the game. It create a board withcreate_board()
which is stored in_board
and then prints the game board withprint_board()
passing the_board
variable.
You can run the game as you would any Python script with:
python main.py
And you should see the following output in the terminal:
| |
-----
| |
-----
| |
-----
This shows the Tic Tac Toe board of 3x3 rows and columns.
Get the eBook
Inside, you'll discover a plethora of Python secrets that will guide you through a journey of learning how to write cleaner, faster, and more Pythonic code. Whether it's mastering data structures, understanding the nuances of object-oriented programming, or uncovering Python's hidden features, this ebook has something for everyone.
Step 2: Handling Player Moves
Next, we need to handle player moves. We'll create functions to check if a move is valid, place a move on the board, and check for a win or a draw.
# Check if a move is valid
def is_valid_move(board, row, col):
return board[row][col] == ' '
# Make a move
def make_move(board, row, col, player):
if is_valid_move(board, row, col):
board[row][col] = player
return True
return False
# Check if the game is over
def check_win(board, player):
# Check rows, columns and diagonals for a win
for row in board:
if all(s == player for s 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
# Check if the game is a draw
def check_draw(board):
return all(all(cell != ' ' for cell in row) for row in board)
Here's a description of each function:
is_valid_move(board, row, col)
: This function checks if a move is valid by examining the game board, specified row, and column. It returnsTrue
if the cell at the given row and column is empty (contains a space character), indicating that the move is valid. Otherwise, it returnsFalse
.make_move(board, row, col, player)
: This function makes a move for the specified player on the game board at the given row and column. It first checks if the move is valid using theis_valid_move()
function. If the move is valid, it updates the cell with the player's symbol (either 'X' or 'O') and returnsTrue
. Otherwise, it does not modify the board and returnsFalse
.check_win(board, player)
: This function checks if the specified player has won the game by examining the game board. It looks for winning patterns in rows, columns, and diagonals. If the player has won, the function returnsTrue
. Otherwise, it returnsFalse
.check_draw(board)
: This function checks if the game is a draw by examining the game board. It returnsTrue
if all cells on the board are occupied (not containing a space character), indicating that there are no more valid moves and no player has won. Otherwise, it returnsFalse
.
Step 3: Two Human Players
Now we can create a game loop for two human players.
# Human vs human game
def human_vs_human():
# Initialize the game
board = create_board()
current_player = 'X'
# Play the game
while True:
# Print the board
print_board(board)
# Get the move from the current player
row = int(input(f"Player {current_player}, enter row (0, 1, 2): "))
col = int(input(f"Player {current_player}, enter col (0, 1, 2): "))
# Make the move (if valid)
if make_move(board, row, col, current_player):
# Check if the game is over
if check_win(board, current_player):
print_board(board)
print(f"Player {current_player} wins!")
break
# Check if the game is a draw
if check_draw(board):
print_board(board)
print("It's a draw!")
break
# Switch players
current_player = 'O' if current_player == 'X' else 'X'
else:
print("Invalid move. Try again.")
# Main function to run the game
if __name__ == '__main__':
human_vs_human()
Here's a detailed description of the human_vs_human()
function:
- The function initializes the game by creating a new 3x3 game board using the
create_board()
function and setting the current player to 'X'. - It then enters an infinite loop, which represents the main gameplay. The loop continues until the game is over (either a player wins or it's a draw).
- Inside the loop, the function first prints the current state of the game board using the
print_board(board)
function. - It then prompts the current player to enter the row and column for their move.
- The function attempts to make the move on the game board using the
make_move(board, row, col, current_player)
function. If the move is valid, it proceeds to the next steps. Otherwise, it displays an "Invalid move. Try again." message and continues with the same player's turn. - If the move is valid, the function checks if the game is over. It first checks if the current player has won using the
check_win(board, current_player)
function. If the player has won, it prints the final game board and a victory message, then breaks the loop to end the game. - If the game is not yet over, the function checks if it's a draw using the
check_draw(board)
function. If it is, it prints the final game board and a draw message, then breaks the loop to end the game. - If the game is still in progress, the function switches the current player to the other player ('O' if the current player is 'X', and vice versa).
It also includes the updated main entry point of the game, which executes the human_vs_human()
function when the script is run.
Running the game now, you can now play against yourself (for example):
| |
-----
| |
-----
| |
-----
Player X, enter row (0, 1, 2): 0
Player X, enter col (0, 1, 2): 0
X| |
-----
| |
-----
| |
-----
Player O, enter row (0, 1, 2): 1
Player O, enter col (0, 1, 2): 1
X| |
-----
|O|
-----
| |
-----
[ ... More moves, hidden for brevity ... ]
X|O|O
-----
X|O|
-----
O|X|X
-----
Player O wins!
Step 4: Adding an AI Player
To add an AI player, we need to implement a basic strategy. A simple AI can make random valid moves.
This article is for paid members only
To continue reading this article, upgrade your account to get full access.
Subscribe NowAlready have an account? Sign In