Head image

You’ve surely played tic-tac-toe as a child. Do you remember how annoying it was to draw out the board each time? Good news, you no longer have to. In this post, I’m going to show you how to program a two player tic-tac-toe game using Python. It is a surprisingly simple implementation, requiring only about 100-150 lines of code. By the end of this post, you will have gained a better understanding of functions, control flow, and other core topics in Python programming. Let’s get started!!

 

Prerequisites

In order for you to get the most out of this tutorial, you should have a basic working knowledge of python and know how to implement the following:

  • If/else statements
  • For/while loops
  • Basic functions

 

If you are new to python or need a refresher on the above concepts, you should first check out my post on How To Build Your First Game in Python. There, you will gain the background knowledge necessary for this tutorial.

 

On the other hand, if you have already built many games in python, this tutorial may be underwhelming. Be on the lookout for parts 2 and 3 of this series where I will show you how to implement a GUI based tic-tac-toe game and build a tic-tac-toe AI using the minimax algorithm respectively.

 

With that being said, let’s start building our tic-tac-toe game!!

 

Tic-Tac-Toe in Python: A Step by Step Tutorial

start-image
I XOXO programming in Python!

 

We will be building a command line tic-tac-toe game as opposed to a GUI. This means that there will be no graphics and we will interact with the game entirely through the computer terminal and shell.  Here are some features of our game:

  • To make a move, we will be prompted to enter a row and column to place our piece.
  • Our program will check to make sure that the user entered a valid move (space not filled & on the board)
  • If the user enters a valid move, the board will update and print
  • After each move is made, our program will check for 3’s in a row.
  • If all spots have been filled without a 3 in a row, the game will end in a tie.

 

Let’s start implementing these features one by one.

 

Step 1. Initialize and Print the Board

We will define our board as a 3 x 3 numpy array. We will then loop through each row and column and replace the default None value with an empty space (which we can later fill in with an X or O). The code is as follows:

import numpy as np

def init_board():
  board = np.empty(shape=(3,3), dtype='object')
  for r in range(3):
    for c in range(3):
      board[r] = " "
  return board

 

Next, we will draw the tic-tac-toe board.

def draw_board():
 print(board[0][0] + '|' + board[0][1] + '|' + board[0][2])
 print("-----")
 print(board[1][0] + '|' + board[1][1] + '|' + board[1][2])
 print("-----")
 print(board[2][0] + '|' + board[2][1] + '|' + board[2][2])

 

Finally, let’s call these methods to visualize the board.

board = init_board()
draw_board()

 

Checkpoint: Your program should print a blank tic-tac-toe board.

 

Step 2. Prompt The Users to Make Their Moves

We will prompt the user to enter the row and column where they want to place their piece. We will collect the user’s responses using the input() function. We subtract 1 from the input because indexing starts at 0 in Python.

row = int(input("Player enter a row (1-3): ")) - 1
col = int(input("Player enter a column (1-3): ")) - 1

 

Now let’s alternate between the two players and ask each to make a move. To do this, we will define a while loop which will alternate the players’ turns (and pieces), and prompt each player to go on their turn.

#DEFINE KEY VARIABLES
turn = 0
piece = 'X'
gameover = False

#GAME LOOP
while not gameover:
  #ASK PLAYER 1 TO MOVE
  if turn == 0:
    row = int(input("P1 enter a row (1-3): ")) - 1
    col = int(input("P1 enter a column (1-3): ")) - 1

  ASK PLAYER 2 TO MOVE
  if turn == 1:
    row = int(input("P2 enter a row (1-3): ")) - 1
    col = int(input("P2 enter a column (1-3): ")) - 1
  
  #ALTERNATE THE PLAYERS TURNS
  turn += 1
  turn = turn % 2

  #ALTERNATE THE PLAYERS TURNS
  if piece == 'X':
    piece = 'O'
  else:
    piece = 'X'

 

Checkpoint: Your program should endlessly alternate between the two players and ask each to enter a row and column.

 

Step 3. Check if Move is Valid and Update Board

To check if a move if valid, let’s define a helper function that takes the coordinates that the user entered and checks if that space on the board is empty:

def is_empty(row, col):
  return board[row][col] == " "

 

If the player’s initial move is not valid, we will prompt the user to enter a new row and column. We keep prompting the user to do this until she enters valid coordinates.

while not is_empty(row, col):
    print("Not a valid move. Try again.")
    if turn == 0:
      row = int(input("P1 enter a row (1-3): ")) - 1
      col = int(input("P1 enter a column (1-3): ")) - 1
    if turn == 1:
      row = int(input("P2 enter a row (1-3): ")) - 1
      col = int(input("P2 enter a column (1-3): ")) - 1

 

If the user’s move is valid, we need to update the board accordingly. Let’s define a function to do this.

def update_board(row, col, piece):
  board[row][col] = piece

 

Update and draw the board after we prompt the user for a move and check its validity.

update_board(row, col, piece)
draw_board()

 

Checkpoint: Your program should ask each player to go and print the updated board with their move. If the player enters an invalid position, the program should alert them and prompt them to try again.

 

Step 4. Check For Winner

We are approaching a finished game. However, we still need to check the board for a winner after each move. We can do this by defining a function that takes in the last piece that was played and checks if there are 3 of those pieces in a row. The function is as follows:

def check_win(piece):
  #CHECK HORIZONTAL
  for r in range(3):
    if (board[r][0] == piece and board[r][1] == piece and board[r][2] == piece):
      return True
  #CHECK VERTICAL
  for c in range(3):
    if (board[0] == piece and board[1] == piece and board[2] == piece):
      return True
  #CHECK MAIN DIAGONAL
  if (board[0][0] == piece and board[1][1] == piece and board[2][2] == piece):
    return True
  
  #CHECK OTHER DIAGONAL
  if (board[0][2] == piece and board[1][1] == piece and board[2][0] == piece):
    return True

 

Let’s check for a winner after we have updated the board. If there is one, let’s set gameover equal to true and notify the players who won.

 #CHECK FOR WINNER
  if (check_win(piece)):
    gameover = True
    print("P{} WINS!!".format(turn + 1))

 

Checkpoint: Your program should be able to check if a player has won and display the appropriate message.

 

Step 5. Check For a Tie

If nobody wins the game, we want to let the players know that they tied. Let’s define a function that checks for a tie by checking if there are any blank spaces left on the board.

def check_tie():
  for row in range(3):
    for col in range(3):
      if is_empty(row, col):
        return False
  return True

 

After we update the board, let’s check if there is a tie.

#CHECK FOR TIE
  if (check_tie()):
    gameover = True
    print("There is a tie.")

 

Checkpoint: Your program should notify the users that there is a tie if all spaces have been filled and nobody has won.

 

Testing and Debugging the Code

If you’ve carefully followed all of the steps above, you should be rewarded with a fully functional game of tic-tac-toe. Here is what a sample game looks like for me:

Please take a minute to check that you’re game is running like mine.

 

If you have any issues, go back to the checkpoints and make sure that you have done each step correctly.

 

If your game still is not working, try troubleshooting the issue by looking it up on Stack Overflow or Quora.

 

As a last resort, you can check out my source code. However, I strongly advise against this approach as you will learn best by writing the code yourself.

 

Conclusion and Next Steps

At least someone appreciates what we’ve built!

 

Congratulations on Making Tic-Tac-Toe in Python

You should feel proud of yourself! You have leveraged your python skills to build your child’s favorite game! In addition, you have solidified your understand of key topics in python such as:

  • Writing / calling functions
  • Control flow
  • Iterating through lists
  • Defining / indexing a numpy array

 

I encourage you to tinker around. Try adding additional features to enhance the quality of the game. Here are some ideas to get you started:

  • Add an error message when the user enters a row and column that are out of bounds.
  • Give the player hints when she or the other player is about to win.
  • Design a slightly modified version of tic-tac-toe.

 

Thank you for reading and be sure to leave your comments below.

 

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *