How to Create a Tic-tac-toe Game Using Python

Python Beginner/Intermediate Project

How to Create a Tic-tac-toe Game Using Python

Tic-tac-toe (American English) is also called noughts and crosses (Commonwealth English), or Xs and Os (Irish English). It is a pencil and paper game between two players, where one of the players takes the mark X and the other player has the mark O. The players place their mark alternatively in the spaces available in the 3 by 3 grid of the game. Any player who first has 3 of his marks align either horizontally, vertically, or diagonally wins the game. If none of the players is able to align their mark when all spaces are filled, the game is a draw.

In this article, we would learn how to create a tic-tac-toe game between two human players. Functions, while loops, dictionaries, the global keyword, the try and except error handling, for loop, the os and platform modules, etc., will be used in the making of the game. Below is the full code. It would be explained in bits through this article.

# Tic-Tac-Toe Between Two Players
# Player 1 would be X; while player two would be O

import os                   # To clear the screen.
import platform             # To check the operating system in use for clearing the screen.

# theBoard is the dictionary of the board when it is empty.
theBoard = {'1': ' ', '2': ' ', '3': ' ',
            '4': ' ', '5': ' ', '6': ' ',
            '7': ' ', '8': ' ', '9': ' '}

# theNumBoard shows the players where to enter their input.
theNumBoard = {'1': '1', '2': '2', '3': '3',
               '4': '4', '5': '5', '6': '5',
               '7': '7', '8': '8', '9': '9'}


# Function to print out the board in an ordered form.
def ticTacToe(board):
    print(board['1'] + '|' + board['2'] + '|' + board['3'])
    print('-+-+-')
    print(board['4'] + '|' + board['5'] + '|' + board['6'])
    print('-+-+-')
    print(board['7'] + '|' + board['8'] + '|' + board['9'])


# Score Variables
playerOneWins = 0
playerTwoWins = 0
draws = 0

repeat = 'y'    # For the main game loop
turn = 'X'      # First player is player 1 (X)
loop = True     # For game loop used to break out of loop from function when there is a win

# Players' Details
playerOne = input('Player 1 Name: ')
playerTwo = input('Player 2 Name: ')
print(playerOne + ': X')
print(playerTwo + ': O')


# Print board with numbers to indicate position.
ticTacToe(theNumBoard)


# Function to check if a player has won.
def win(value1, value2, value3):
    """win() checks the tic-tac-toe board values against the possible wins combination to know if a player has won"""
    if theBoard[value1] == theBoard[value2] == theBoard[value3] != ' ':
        print('\033[0;32;40m' + theBoard[value1] + ' is the winner' + '\033[0;0m')

        # global keyword allows the global variables to be changed in the function
        global playerOneWins
        global playerTwoWins
        global loop

        # Check which of the players won
        if theBoard[value1] == 'X':
            playerOneWins = playerOneWins + 1

            loop = False
            return loop
        else:
            playerTwoWins = playerTwoWins + 1

            loop = False
            return loop


# Main program loop
while repeat.lower() == 'y':

    loop = True
    # This is used to determine the draw between the players. It decreases with each player's input.
    # When the whole box is filled, spaceRemaining = 0 and no winner, the game is a draw.
    spaceRemaining = 9

    # Print an empty board
    ticTacToe(theBoard)

    while loop is True:
        # Ask players for input
        position = input('It is player ' + turn + ' turn: ')

        # This check if the position is empty and also handles key Error
        try:
            if theBoard[position] != ' ':
                # '\033[0;31;40m' - black background, red text.
                print('\033[0;31;40m' + 'Already filled. Choose an empty slot' + '\033[0;0m')
                continue
        except KeyError:
            # '\033[0;31;40m' - black background, red text.
            print('\033[0;31;40m' + 'Invalid! Choose between 1 to 9.' + '\033[0;0m')
            continue

        # Updates theBoard with player's input
        theBoard[position] = turn

        # CLEAR SCREEN
        # Clear screen for Windows
        if platform.system().lower() == "windows":
            os.system('cls')

        # Clear screen for other operating systems
        else:
            os.system('clear')

        # Print the new board.
        ticTacToe(theBoard)

        # Alternates player's turns
        if turn == 'X':
            turn = 'O'
        else:
            turn = 'X'

        # POSSIBLE WINS PATTERNS
        # Check if a player has won

        # First Row
        win('1', '2', '3')

        # Second Row
        win('4', '5', '6')

        # Third Row
        win('7', '8', '9')

        # First Column
        win('1', '4', '7')

        # Second Column
        win('2', '5', '8')

        # Third Column
        win('3', '6', '9')

        # / Forward Slash Diagonal
        i = win('3', '5', '7')

        # \ Backward Slash Diagonal
        win('1', '5', '9')

        # DRAW
        # Check if all the spaces are filled with no winner
        spaceRemaining = spaceRemaining - 1

        # Check if the board is filled up.
        if spaceRemaining == 0 and loop is True:
            # '\033[0;33;40m' - black background, yellow text.
            print('\033[0;33;40m' + 'It is a draw!' + '\033[0;0m')
            draws = draws + 1

            break

    # SCOREBOARD
    # Print the scoreboard after a win or draw
    # '\033[7;32;40m' - Green background, black text.
    print('\033[7;32;40m' + '%s: %s; %s: %s; Draw: %s'
          % (playerOne.title(), playerOneWins, playerTwo.title(), playerTwoWins, draws) + '\033[0;0m')

    # Ask players if they want to continue the game
    # '\033[0;33;40m' - black background, yellow text.
    repeat = input('\033[0;33;40m' + 'Do you wish to continue? [y]es or [n]o: ' + '\033[0;0m')

    if repeat.lower() == 'y':

        # Empty the dictionary values of the game to start afresh
        for keys in theBoard:
            theBoard[keys] = ' '

           # If the players choose to continue, the player who lost
    # or is meant to play next (in cases of a draw) starts the next,
    # but if you want the winner or played last (in cases of a draw) to continue, uncomment the code below.


        # if turn == 'X':
            # turn = '0'
        # else:
            # turn = 'X'

        continue

    else:
        break

Firstly, we import the os and platform modules which we would use to clear the screen of the terminal during the game, so as to make the board stationed at the beginning of the terminal. We then create two dictionaries, theBoard and theNumBoard; theBoard is what would be used for saving the values inputted by the players into diverse positions selected, while theNumBoard is to show the position and keys to input the players marks in the positions they want.

import os
import platform

theBoard = {'1': ' ', '2': ' ', '3': ' ',
            '4': ' ', '5': ' ', '6': ' ',
            '7': ' ', '8': ' ', '9': ' '}

theNumBoard = {'1': '1', '2': '2', '3': '3',
               '4': '4', '5': '5', '6': '5',
               '7': '7', '8': '8', '9': '9'}

Next, we create a function to print the game board, and initialize the variables we would need for the game play, and we ask the players for their names.

def ticTacToe(board):
    print(board['1'] + '|' + board['2'] + '|' + board['3'])
    print('-+-+-')
    print(board['4'] + '|' + board['5'] + '|' + board['6'])
    print('-+-+-')
    print(board['7'] + '|' + board['8'] + '|' + board['9'])


# Score Variables
playerOneWins = 0
playerTwoWins = 0
draws = 0

repeat = 'y'
turn = 'X'
loop = True

# Players' Details
playerOne = input('Player 1 Name: ')
playerTwo = input('Player 2 Name: ')
print(playerOne + ': X')
print(playerTwo + ': O')

We then call the ticTacToe(theNumBoard) function which prints out the keys for all positions in the game board.

ticTacToe(theNumBoard)

Next, we create a function we would call later in the code to check all possible win combinations, after each player’s turn, against the marks in the board if there is a win. If there is a win, the function returns a False, which breaks out of the game loop. The global keyword is used in this function to effect changes in the global variables used in the function.

def win(value1, value2, value3):
    if theBoard[value1] == theBoard[value2] == theBoard[value3] != ' ':
        print('\033[0;32;40m' + theBoard[value1] + ' is the winner' + '\033[0;0m')

        global playerOneWins
        global playerTwoWins
        global loop

        if theBoard[value1] == 'X':
            playerOneWins = playerOneWins + 1

            loop = False
            return loop
        else:
            playerTwoWins = playerTwoWins + 1

            loop = False
            return loop

Next, we move on to the main program loop. This runs the game once, and after a win or draw, the players are asked if they wish to continue. If y is selected, the game runs again, but if any other key is selected, the game ends.

while repeat.lower() == 'y':
…
    if repeat.lower() == 'y':
…
        continue

    else:
        break

We then initialize the variable, spaceRemaining, and give it the value of integer 9, which is to indicate the number of spaces remaining in the board. Its value decreases after each player’s turn. If none of the players wins when spaceRemaining equals zero (i.e., all spaces have been filled), then the game is a draw. At the start of a new game, the spaceRemaining is made to value 9 again. ticTacToe(theBoard) function is called to print an empty board at the start of the game, and the variable, loop, is made to have the Boolean value of True.

while repeat.lower() == 'y':

    loop = True

    spaceRemaining = 9

    ticTacToe(theBoard)
…
        # DRAW
        spaceRemaining = spaceRemaining - 1

        if spaceRemaining == 0 and loop is True:
            print('\033[0;33;40m' + 'It is a draw!' + '\033[0;0m')
            draws = draws + 1

            break

Next, we create another loop that continues until we have a win or a draw. The players are asked for the position they want to play. The values they selected are checked using the try and except error handling to check if the positions chosen are empty or are invalid. If confirmed to be valid, they are entered into the theBoard dictionary and theBoard is printed with the updated values, and the next player is made to play. The screen is cleared continuously so as to maintain the position of the board at the top of the terminal while the game is being played.

while loop is True:
        position = input('It is player ' + turn + ' turn: ')

        try:
            if theBoard[position] != ' ':
                print('\033[0;31;40m' + 'Already filled. Choose an empty slot' + '\033[0;0m')
                continue
        except KeyError:
            # '\033[0;31;40m' - black background, red text.
            print('\033[0;31;40m' + 'Invalid! Choose between 1 to 9.' + '\033[0;0m')
            continue

        theBoard[position] = turn

        # CLEAR SCREEN
        if platform.system().lower() == "windows":
            os.system('cls')

        else:
            os.system('clear')

        # Print the new board.
        ticTacToe(theBoard)

        # Alternates player's turns
        if turn == 'X':
            turn = 'O'
        else:
            turn = 'X'

We call the win() function to check all possible win combinations against the values on the board to know if there is a win.

# POSSIBLE WINS PATTERNS

        # First Row
        win('1', '2', '3')
…
        # \ Backward Slash Diagonal
        win('1', '5', '9')
After there is a win or draw, the scoreboard is printed.
    # SCOREBOARD

    print('\033[7;32;40m' + '%s: %s; %s: %s; Draw: %s'
          % (playerOne.title(), playerOneWins, playerTwo.title(), playerTwoWins, draws) + '\033[0;0m')

The players are asked if they wish to continue the game; if yes, theBoard values are emptied; if no, the game ends. If the players choose to continue the game, the player who lost or is meant to play next (in cases of a draw) starts the next round, but if you uncomment the code below, the player who won this round or played last (in cases of a draw) starts the next round.

# Ask players if they want to continue the game
    repeat = input('\033[0;33;40m' + 'Do you wish to continue? [y]es or [n]o: ' + '\033[0;0m')

    if repeat.lower() == 'y':

        # Empty the dictionary values of the game to start afresh
        for keys in theBoard:
            theBoard[keys] = ' '

        # if turn == 'X':
            # turn = '0'
        # else:
            # turn = 'X'

        continue

    else:
        break

There, you have it. You should be able to create a tic-tac-toe game now using Python. For questions and observations, kindly leave a comment. Thank you.

Play the game on Replit