A game of Tic-Tac-Toe.

★★★

Noughts and crosses, also known as Tic-Tac-Toe is a game for two players. It is played on a 3x3 grid of squares. Player one plays with counters marked "X". Player two plays with counters marked "O". The aim of the game is to win by having placed three of your own counters adjacent to each other either horizontally, vertically or diagonally. On a players turn they place just one of their counters onto an empty square.

Noughts and crosses

Make

Write the program to play the game.

Success Criteria

Remember to add a comment before a subprogram or selection statement to explain its purpose.

  1. In the main program, initialise the game board as a 3x3 array of -1 values.

-1 indicates an empty square, 0 indicates an “O” and 10 indicates an “X”.

Numbers will make it easier to calculate if there is a winner.

Complete the subprogram called get_move that:

  1. Prompts the user to enter the xy position of where they want to place their counter. E.g. 00 would be the top left corner, 22 would be the bottom right corner.
  2. Checks that a counter is only being placed on an empty square.
  3. Places a counter on a valid square.

Complete the subprogram called draw_board that:

  1. Outputs the board for the players using the format shown in the typical inputs and outputs below.

Complete the subprogram called won that:

  1. Checks if a player has won, returning True if they have or False if they have not.

Complete the subprogram called play_game that:

  1. Plays the game until either a player has won or the game is a draw. The game is a draw when a player cannot place a counter on the board.
  2. Outputs the result of the game.

Complete the main program so that:

  1. The play_game subprogram is called.

Typical inputs and outputs from the program would be:

  0 1 2
0  | | 
---------
1  | | 
---------
2  | | 
 
Enter xy position: 11
  0 1 2
0  | | 
---------
1  |X| 
---------
2  | | 
 
Enter xy position: 21
  0 1 2
0  | | 
---------
1  |X|O
---------
2  | | 
 
Enter xy position: 20
  0 1 2
0  | |X
---------
1  |X|O
---------
2  | | 
 
Enter xy position: 02
  0 1 2
0  | |X
---------
1  |X|O
---------
2 O| | 
 
Enter xy position: 00
  0 1 2
0 X| |X
---------
1  |X|O
---------
2 O| | 
 
Enter xy position: 10
  0 1 2
0 X|O|X
---------
1  |X|O
---------
2 O| | 
 
Enter xy position: 22
  0 1 2
0 X|O|X
---------
1  |X|O
---------
2 O| |X
X wins.

Restricted automated feedback

Automated feedback for this assignment is still under construction. Submitted programs are checked for syntax errors and their source code is checked for potential errors, bugs, stylistic issues, and suspicious constructs. However, no checks are performed yet to see if the program correctly implements the behaviour specified in the assignment.

🆘 If you're really stuck, use this Parsons code sorting exercise
get_move
# Get the player move
def get_move(player):
---
    valid_move = False
    x = 0
    y = 0
---
    # Check valid move
    while not valid_move:
---
        valid_move = True
---
        move = input("Enter xy position: ")
        x = int(move[0])
        y = int(move[1])
---
        # Cannot move on top of another counter
        if board[x][y] != -1:
---
            valid_move = False
---
    # Put a 10 on the board for X or O on the board for 0
    if player == 1:
---
        board[x][y] = 10
---
    else:
---
        board[x][y] = 0
draw_board
# Draw the board
def draw_board():
---
    print("  0 1 2")
---
    # Draw rows
    for y in range(3):
---
        print(y, "", end="")
---
        # Draw columns
        for x in range(3):
---
            # Output the counter X, O or a blank space
            match board[x][y]:
---
                case - 1:
                    print(" ", end="")
                case 10:
                    print("X", end="")
                case 0:
                    print("O", end="")
---
            # Draw vertical line
            if x < 2:
---
                print("|", end="")
---
        print()
---
        # Draw horizontal line
        if y < 2:
---
            print("---------")
won
# Check if a player has won
def won():
---
    # Check horizontal & vertical win conditions
    # Check all rows
    for y in range(3):
---
        htotal = 0
        vtotal = 0
---
        # Check all columns
        for x in range(3):
---
            htotal = htotal + board[x][y]
            vtotal = vtotal + board[y][x]
---
        # Game is won with XXX or OOO
        if htotal == 30 or htotal == 0 or vtotal == 30 or vtotal == 0:
---
            return True
---
    # Check left to right diagonal win condition 
---
    dtotal = board[0][0] + board[1][1] + board[2][2]
---
    # Game is won with XXX or OOO
    if dtotal == 30 or dtotal == 0:
---
        return True
---
    # Check right to left diagonal win condition
---
    dtotal = board[2][0] + board[1][1] + board[0][2]
---
    # Game is won with XXX or OOO
    if dtotal == 30 or dtotal == 0:
---
        return True
---
    return False
play_game, main program
# Play the game
def play_game():
---
    turns = 0
    player = 1
    game_over = False
    draw_board()
---
    # Play until the game is won or draw
    while not game_over:  
---
        turns = turns + 1
---
        get_move(player)
---
        draw_board()
---
        # If the game has been won...
        if won():
---
            game_over = True
---
            # ... output the winner
            if player == 1:
---
                print("X wins.")
---
            else:
---
                print("O wins.")
---
        # If no player has won...
        else:
---
            # ...check if it is a draw
            if turns == 9:
---
                game_over = True
---
                print("Draw.")
---
        player = player + 1
---
        # Change the player back to player 1 after player 2's turn
        if player == 3:
---
            player = 1
---
        

# -------------------------
# Main program
# -------------------------
# Empty squares have the value -1
board = [[-1 for x in range(3)] for y in range(3)]
play_game()