top of page

Tic-Tac-Toe Game


What is Tic-Tac-Toe?


Tic-Tac-Toe is a simple table game played between two players. Players take turns placing "X" or "O" on a 3x3 board. The goal is to form a row of three horizontally, vertically, or diagonally. If all squares are filled and neither player has formed a row of three, the game ends in a draw.


Project Goals and Student Benefits

With this project, students will reinforce their ability to develop simple and functional programs using basic Python knowledge. Additionally, they will gain experience in game simulations and user interaction.


Project Objectives

  • Creating a game simulation using basic Python structures and control flows.

  • Receiving data from the user and managing the game flow by processing this data.

  • Writing more modular and readable code with the help of functions.


Step-by-Step Tasks of the Project

  1. Creating the board and setting the initial state.

  2. Printing the board on the screen.

  3. Receiving a move from the user and checking its validity.

  4. Placing the move on the board.

  5. Checking if the game is won or if it is a draw.

  6. Printing the result of the game on the screen.

  7. Making the code more modular using functions.


Step 1: Creating the Board and Setting the Initial State

As the first step, a game board will be created and the initial state will be set.

# Creating the board and setting the initial state
board = [[" " for _ in range(3)] for _ in range(3)]

This code snippet creates a 3x3 game board and sets all squares to empty.


Step 2: Printing the Board on the Screen

In the second step, the current state of the board will be printed on the screen.

# Printing the board on the screen
def print_board(board):
    """Prints the board on the screen."""
    for row in board:
        print("|".join(row))
        print("-" * 5)

This function prints the current state of the board on the screen.


Step 3: Receiving a Move from the User and Checking Its Validity

In the third step, a move will be received from the user and its validity will be checked.

# Receiving a move from the user and checking its validity
def get_move(player):
    """Receives a valid move from the user."""
    while True:
        move = input(f"Player {player}, enter your move (row and column separated by space): ").split()
        if len(move) != 2:
            print("Invalid input. Please enter row and column separated by space.")
            continue
        row, column = move
        if not (row.isdigit() and column.isdigit()):
            print("Invalid input. Please enter numbers.")
            continue
        row, column = int(row), int(column)
        if row < 0 or row > 2 or column < 0 or column > 2:
            print("Invalid input. Please enter a number between 0 and 2.")
            continue
        if board[row][column] != " ":
            print("This square is already filled. Choose another square.")
            continue
        return row, column

This function receives a valid move from the user and returns it.


Step 4: Placing the Move on the Board

In the fourth step, the user move will be placed on the board.

# Placing the move on the board
def place_move(board, row, column, player):
    """Places the move on the board."""
    board[row][column] = player

This function places the user move on the board.


Step 5: Checking if the Game is Won or if It is a Draw

In the fifth step, it will be checked if the game is won or if it is a draw.

# Checking if the game is won or if it is a draw
def check_winner(board, player):
    """Checks if the game is won or if it is a draw."""
    # Checking rows
    for row in board:
        if all([cell == player for cell in row]):
            return True

    # Checking columns
    for column in range(3):
        if all([board[row][column] == player for row in range(3)]):
            return True

    # Checking diagonals
    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

def check_draw(board):
    """Checks if the game is a draw."""
    for row in board:
        if " " in row:
            return False
    return True

These functions check if the game is won or if it is a draw.


Step 6: Printing the Result of the Game on the Screen

In the sixth step, the result of the game will be printed on the screen.

# Printing the result of the game on the screen
def game_result(board, player):
    """Prints the result of the game on the screen."""
    if check_winner(board, player):
        print(f"Player {player} wins!")
        return True
    if check_draw(board):
        print("The game is a draw!")
        return True
    return False

This function prints the result of the game on the screen.


Step 7: Solution with Functions


Starting the Game Function

This function starts the Tic-Tac-Toe game and manages the game flow.

def start_game():
    """Starts the Tic-Tac-Toe game."""
    board = [[" " for _ in range(3)] for _ in range(3)]
    player = "X"

    while True:
        print_board(board)
        row, column = get_move(player)
        place_move(board, row, column, player)

        if game_result(board, player):
            print_board(board)
            break

        player = "O" if player == "X" else "X"

# Starting the game
start_game()

This function starts the Tic-Tac-Toe game and manages the game flow. It receives player moves, places the moves on the board, and checks the result of the game.


Topics Covered

  • Data Types: Lists (board) and strings (player moves) were used in this project.

  • Lists: The game board and moves were stored as lists.

  • Conditional Statements: if-else structures were used to check player moves and determine the result of the game.

  • Functions: Functions ensured the code was modular and reusable.

  • Loops: while loops were used to manage the game flow and receive player moves.

bottom of page