Let us create a simple Tic Tac Toe game in Python. It will help you to build up game logic and understand how to structure code.

Gaming is one of the entertainment that humans have. We can find different types of games on the web, mobile, desktop, etc. We are not here to make one of those heavy games now. We are going to create a CLI tic-tac-toe game using Python.

If you are not familiar with Tic Tac Toe, play it visually here to understand. Don’t worry, even if you don’t understand it, we are going to see it.

Tic Tac Toe

The tutorial is divided into three different sections. In the first section, you will get to know how to play the tic-tac-toe game. After that, we will see an algorithm that helps us to come up with the game logic. Finally, we will see the structured code and its explanation.

You may skip the first section if you already know how to play Tic Tac Toe.

So, without further ado, let’s dive into our first section.

Playing Tic Tac Toe

There will be two players in a game. Two signs represent each player. The general signs used in the game are and O. Finally, there will be a board with 9 boxes.

See the tic-tac-toe board visually.

Tic Tac Toe Board
Tic Tac Toe Board

The gameplay will be as follows.

  • First, one user will place their sign in one of the available empty boxes.
  • Next, the second user will place their sign in one of the available empty boxes.
  • The goal of the players is to place their respective signs completely row-wise or column-wise, or diagonally.
  • The game goes on until a player wins the game or it ended up in a draw by filling all boxes without a winning match.

Let’s see some gameplays visually.

Tic Tac Toe Win Gameplay
Tic Tac Toe Win Gameplay

The player wins the game in the above gameplay. All boxes diagonally fill with signs. So, the respective player wins the game.

There are a total of 8 ways to arrange the same sign and win the game. Let’s see all the 8 arrangements that can win the game.

Tic Tac Toe Winning Arrangements
Tic Tac Toe Winning Arrangements

And finally, a draw fills the board without any winning arrangement. I hope you understand how to Tic Tac Toe now.

Now, it’s playtime for you. You may go here and play it to understand the gameplay completely. Leave it if you have already got it.

Now, it’s time to move the algorithm section.

 Algorithm

We will now discuss the algorithm to write the code. This algorithm will help you to write code in any programming language of your choice. Let’s see how it’s done.

  • Create a board using a 2-dimensional array and initialize each element as empty.
    • You can represent empty using any symbol you like. Here, we are going to use a hyphen. '-'.
  • Write a function to check whether the board is filled or not.
    • Iterate over the board and return false if the board contains an empty sign or else return true.
  • Write a function to check whether a player has won or not.
    • We have to check all the possibilities that we discussed in the previous section.
    • Check for all the rows, columns, and two diagonals.
  • Write a function to show the board as we will show the board multiple times to the users while they are playing.
  • Write a function to start the game.
    • Select the first turn of the player randomly.
    • Write an infinite loop that breaks when the game is over (either win or draw).
      • Show the board to the user to select the spot for the next move.
      • Ask the user to enter the row and column number.
      • Update the spot with the respective player sign.
      • Check whether the current player won the game or not.
      • If the current player won the game, then print a winning message and break the infinite loop.
      • Next, check whether the board is filled or not.
      • If the board is filled, then print the draw message and break the infinite loop.
    • Finally, show the user the final view of the board.

You may be able to visualize what’s happening. Don’t worry, even if you didn’t understand it completely. You will get more clarity once you see the code.

So, let’s jump into the code section. I assume you have Python installed on your PC to try the code.

Code

Go through the below code.

import random


class TicTacToe:

    def __init__(self):
        self.board = []

    def create_board(self):
        for i in range(3):
            row = []
            for j in range(3):
                row.append('-')
            self.board.append(row)

    def get_random_first_player(self):
        return random.randint(0, 1)

    def fix_spot(self, row, col, player):
        self.board[row][col] = player

    def is_player_win(self, player):
        win = None

        n = len(self.board)

        # checking rows
        for i in range(n):
            win = True
            for j in range(n):
                if self.board[i][j] != player:
                    win = False
                    break
            if win:
                return win

        # checking columns
        for i in range(n):
            win = True
            for j in range(n):
                if self.board[j][i] != player:
                    win = False
                    break
            if win:
                return win

        # checking diagonals
        win = True
        for i in range(n):
            if self.board[i][i] != player:
                win = False
                break
        if win:
            return win

        win = True
        for i in range(n):
            if self.board[i][n - 1 - i] != player:
                win = False
                break
        if win:
            return win
        return False

        for row in self.board:
            for item in row:
                if item == '-':
                    return False
        return True

    def is_board_filled(self):
        for row in self.board:
            for item in row:
                if item == '-':
                    return False
        return True

    def swap_player_turn(self, player):
        return 'X' if player == 'O' else 'O'

    def show_board(self):
        for row in self.board:
            for item in row:
                print(item, end=" ")
            print()

    def start(self):
        self.create_board()

        player = 'X' if self.get_random_first_player() == 1 else 'O'
        while True:
            print(f"Player {player} turn")

            self.show_board()

            # taking user input
            row, col = list(
                map(int, input("Enter row and column numbers to fix spot: ").split()))
            print()

            # fixing the spot
            self.fix_spot(row - 1, col - 1, player)

            # checking whether current player is won or not
            if self.is_player_win(player):
                print(f"Player {player} wins the game!")
                break

            # checking whether the game is draw or not
            if self.is_board_filled():
                print("Match Draw!")
                break

            # swapping the turn
            player = self.swap_player_turn(player)

        # showing the final view of board
        print()
        self.show_board()


# starting the game
tic_tac_toe = TicTacToe()
tic_tac_toe.start()

Check out the sample output of the code.

$ python tic_tac_toe.py 
Player X turn
- - -
- - -
- - -
Enter row and column numbers to fix spot: 1 1

Player O turn
X - -
- - -
- - -
Enter row and column numbers to fix spot: 2 1

Player X turn
X - -
O - -
- - -
Enter row and column numbers to fix spot: 1 2

Player O turn
X X -
O - -
- - -
Enter row and column numbers to fix spot: 1 3

Player X turn
X X O
O - -
- - -
Enter row and column numbers to fix spot: 2 2

Player O turn
X X O
O X -
- - -
Enter row and column numbers to fix spot: 3 3

Player X turn
X X O        
O X -        
- - O
Enter row and column numbers to fix spot: 3 2

Player X wins the game!

X X O
O X -
- X O

Some major points that help you understand the structure of the code.

  • We have used a class to have all the methods in one place. It can easily be a reusable bundle in some other code as well.
  • Next, we have defined different functions for each responsibility, even if it is a small task. It helps to maintain the code with ease.
  • The above two approaches help us update the app effortlessly if we want to update the game.

Feel free to adapt the structure and improve it based on your project. Structuring the code is not limited.

Final Words

Hurray! 😎 You have created a game completely from scratch. It is not one of the visual games that we play daily. But it helps you to write logic and maintain clean structure in code. Follow similar guidelines to create some interesting games like this. You can find similar games if you go back some years to your childhood.

Happy Coding! 👩‍💻

Next, explore how to create number guessing game and Unit Testing with Python unittest Module.