DEV Community

Cover image for Create Tic Tac Toe with Python
nasirpi
nasirpi

Posted on

Create Tic Tac Toe with Python

This post will demonstrate how to make Tic Tac Toe in Python. Hopefully this will help someone relatively new to Python see how to make a simple program. Note that Python 3.7 is used for this tutorial although most versions of Python 3 should work.

Chances are high you have heard of Tic Tac Toe but I will briefly explain the game just in case. The game is played on a 3x3 grid that starts out initially blank. Players then alternate placing their letter (X for player 1, O for player 2) inside a blank square of the grid. If one player gets 3 in a line either vertically, horizontally, or diagonally, they win the game. If the grid is filled and there are no 3-in-a-rows, then the game is a tie which is the result if both players play properly.

We will encode the rules of the game in Python with the program asking for the moves of each player and then displaying the current state of the board. To build the game, we will need:

  • a way to display the current state of the game
  • a way to update to grid with a move
  • a way to check for the end of the game
  • a way to verify if a move is valid
  • prompts for players to make their moves

A sample run of the game

0   1   2   
3   4   5   
6   7   8   
Player 1 [X], make your move: 4
0   1   2   
3   X   5   
6   7   8   
Player 2 [O], make your move: 1
0   O   2   
3   X   5   
6   7   8   
Player 1 [X], make your move: 3
0   O   2   
X   X   5   
6   7   8   
Player 2 [O], make your move: 5
0   O   2   
X   X   O   
6   7   8   
Player 1 [X], make your move: 6
0   O   2   
X   X   O   
X   7   8   
Player 2 [O], make your move: 0
O   O   2   
X   X   O   
X   7   8   
Player 1 [X], make your move: 2
O   O   X   
X   X   O   
X   7   8   
Player 1 Wins
Good Game!
Enter fullscreen mode Exit fullscreen mode

a way to display the current state of the game
Our program will be a console program since it will not have a GUI. Instead, it will collect moves in the console through the players typing input and it will display the board after each move. We can display the current state of the game by printing out the 3x3 grid row by row with spaces between each square. Player 1 will use 'X', Player 2 will use 'Y', and blanks will be represented as '-'. The board will start out initially with all squares as blank. For displaying purposes, blanks will show a number corresponding to what a player will type to place their letter in that square (0 to 8).

PLAYER_ONE_MOVE = "X"
PLAYER_TWO_MOVE = "O"
BLANK = "-"
BOARD_SIZE = 3
VALID_MOVES = ["0", "1", "2", "3", "4", "5", "6", "7", "8"]

board = [[BLANK, BLANK, BLANK], [BLANK, BLANK, BLANK], [BLANK, BLANK, BLANK]]

def print_board():
    for i in range(BOARD_SIZE):
        for j in range(BOARD_SIZE):
            next_square = board[i][j]
            if next_square == BLANK:
                next_square = BOARD_SIZE * i + j
            print(next_square, end = "   ")
        print("")
Enter fullscreen mode Exit fullscreen mode

a way to update to grid with a move
A move is a number from 0 to 8 which corresponds to a specific square. If we think about it, move // BOARD_SIZE gives us the row number and move % BOARD_SIZE gives us the column number. Note that in Python, "//" is integer division where as "/" will give a floating point result. We will place an "X" or "O" depending on which player is making the move. We will always print the board after a move so that the next player can see the current state of the board.

def update_board(move, is_player_one):
    row = move // BOARD_SIZE
    column = move % BOARD_SIZE
    if is_player_one:
        board[row][column] = PLAYER_ONE_MOVE
    else:
        board[row][column] = PLAYER_TWO_MOVE
    print_board()
Enter fullscreen mode Exit fullscreen mode

a way to check for the end of the game
A game can end because the board becomes full or because one player gets 3-in-a-row. We will make one function for checking if the board is full and another to check for 3-in-a-rows. The board is full if all squares are not blank so we can just use nested for loops to check for this. Detecting 3-in-a-rows can be done by checking for 1 of 8 of the possible ways to get one (3 horizontal, 3 vertical, 2 diagonals). Note that "\" is used to have the boolean condition across multiple lines.

def board_full():
    for i in range(BOARD_SIZE):
        for j in range(BOARD_SIZE):
            if board[i][j] == BLANK:
                return False
    return True

def is_win(letter):
    if (board[0][0] == letter and board[0][1] == letter and board[0][2] == letter) \
            or (board[1][0] == letter and board[1][1] == letter and board[1][2] == letter) \
            or (board[2][0] == letter and board[2][1] == letter and board[2][2] == letter) \
            or (board[0][0] == letter and board[1][0] == letter and board[2][0] == letter) \
            or (board[0][1] == letter and board[1][1] == letter and board[2][1] == letter) \
            or (board[0][2] == letter and board[1][2] == letter and board[2][2] == letter) \
            or (board[0][0] == letter and board[1][1] == letter and board[2][2] == letter) \
            or (board[0][2] == letter and board[1][1] == letter and board[2][0] == letter):
       return True
    return False
Enter fullscreen mode Exit fullscreen mode

a way to verify if a move is valid
An attempted move is valid if it is a number from 0 to 8 (representing a square) and if that square is not already taken. We can first check if the move is in a predetermined list of valid moves and return False otherwise. If it is a valid move, we just need to make sure that square currently has a blank.

def valid_move(move):
    if move not in VALID_MOVES:
        return False
    move = int(move)
    row = move // BOARD_SIZE
    column = move % BOARD_SIZE
    return board[row][column] == BLANK
Enter fullscreen mode Exit fullscreen mode

prompts for players to make their moves
Unlike languages such as Java, there is not a sense of a main method. if __name__ == '__main__' will evaluate to true if the source file is run as the main program. The game loop and player input will be placed in this if block.

One iteration of the game loop consists of two player moves. The game loop runs until the board is full or a win is detected early. Input for player moves is retrieved through input() and is re-prompted repeatedly if the move is not a valid one. The board is updated and printed after each move so that the next player can make an informed decision. The final result is printed to the console in the case of a player win or a tie.

if __name__ == '__main__':
    print_board()
    while not board_full():
        # player 1
        player_one_move = input("Player 1 [X], make your move: ")
        while not valid_move(player_one_move):
            player_one_move = input("Player 1 [X], please enter a proper move: ")
        update_board(int(player_one_move), True)
        if is_win(PLAYER_ONE_MOVE):
            print("Player 1 Wins")
            break
        elif board_full():
            print("Tie")
            break
        # player 2
        player_two_move = input("Player 2 [O], make your move: ")
        while not valid_move(player_two_move):
            player_two_move = input("Player 2 [O], please enter a proper move: ")
        update_board(int(player_two_move), False)
        if is_win(PLAYER_TWO_MOVE):
            print("Player 2 Wins")
            break
    print("Good Game!")
Enter fullscreen mode Exit fullscreen mode

Challenge
Hopefully you got something out of this. You can test if you understand it by seeing if you can build Connect Four!

Top comments (2)

Collapse
 
chrisshokry profile image
Neo mounir

''''
import random
board = [" ", " ", " ", " ", " ", " ", " ", " ", " ", " "]
game_letters = ['X', 'O']

# 0 | 1 | 2
#---+---+---
# 3 | 4 | 5
#---+---+---
# 6 | 7 | 8
''''''

drawing 3x3 board.

def draw_board(board):
print('---------')
print(board[0] , '|' , board[1] , '|' , board[2])
print('---------')
print(board[3] , '|' , board[4] , '|' , board[5])
print('---------')
print(board[6] , '|' , board[7] , '|' , board[8])
print('---------')

game introduction and choosing which player take what letter.

def main():
draw_board(board)
print("Welcome to TIC TAC TOE Game")
player_1 = print("Player 1 please enter your name: ")
player_1 = input()
player_2 = print("Player 2 please enter your name: ")
player_2 = input()
turn = input("Player " + str(player_1) + " would you like to
choose X or O?")
player_2_turn = player_turn(player_1)
if(turn != str("X") and turn != str("O")):
turn = input("Please enter X or O: ")
print(str(player_1) + " take " + (turn) + str(player_2) +

" take " + str(player_2_turn) )

while True:
draw_board(board)
move = int(input(" Make a move (X): "))
board[move] = "X"
if board[move] != "X" or board[move] != "O":
print(" Please make another move ")
draw_board(board)
move_2 = int(input(" Make a move (O): "))
board[move] = "O"
if board[move] != "X" or board[move] != "O":
print("Please make another move ")
# player_1 choices
#across the top row
if board[0] == board[1] == board[2] == "X":  
    print(str(player_1)  +  "wins" )
    break
#across the middle row
if board[3] == board[4] == board[5] == "X":  
    print(str(player_1)  +  "wins" )
    break
#across the bottom row
if board[6] == board[7] == board[8] == "X":  
    print(str(player_1)  +  "wins" )
    break
if board[0] == board[3] == board[6] == "X":  #first column
    print(str(player_1)  +  "wins" )
    break
if board[1] == board[4] == board[7] == "X":  #secondcolumn
    print(str(player_1)  +  "wins" )
    break
if board[2] == board[5] == board[8] == "X":  #third column
    print(str(player_1)  +  "wins" )
    break
if board[0] == board[4] == board[8] == "X":  #leftdiagonal
    print(str(player_1)  +  "wins" )
    break
if board[2] == board[4] == board[6] == "X": #rightdiagonal
    print(str(player_1)  +  "wins" )
    break

# player_2 choices
#across the top row
if board[0] == board[1] == board[2] == "O": 
    print(str(player_2)  +  "wins" )
    break
#across the middle row
if board[3] == board[4] == board[5] == "O":   
    print(str(player_2)  +  "wins" )
    break
#across the bottom row
if board[6] == board[7] == board[8] == "O":  
    print(str(player_2)  +  "wins" )
    break
if board[0] == board[3] == board[6] == "O":  #first column
    print(str(player_2)  +  "wins" )
    break
if board[1] == board[4] == board[7] == "O": #second column
    print(str(player_2)  +  "wins" )
    break
if board[2] == board[5] == board[8] == "O":  #third column
    print(str(player_2)  +  "wins" )
    break
if board[0] == board[4] == board[8] == "O": #left diagonal
    print(str(player_2)  +  "wins" )
    break
if board[2] == board[4] == board[6] == "O":#right diagonal
    print(str(player_2)  +  "wins" )
    break
else:
    print(" Tie ")
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode



switch players 2-->1, 1-->2

def player_turn(player_1):
if player_turn == "X":
return "O"
else:
return "X"

if name == 'main':
main()

Collapse
 
chrisshokry profile image
Neo mounir

good day, im trying to create the same tic tac toe project but after testing the code it didnt really work well , kindly could you assist in looking up my code.
thanks in advance.