Search code examples
pythontic-tac-toe

Cannot get my tic-tac-toe game to run correctly in python


I did a code-along for a tic-tac-toe game written in python. I have followed the steps exactly but I think the game was written specifically for a Jupyter notebook because it is not working properly for me in a real python interpreter (I wrote out all the code in VS code). It randomly assigns which player will go first, which it's supposed to, but that player's marker is not assigned correctly and the other player never gets to move. Additionally, the player that does move, whenever they choose a spot on the top row (indexes 7-9), it is an automatic win.

This is in Python 3. I have tried to debug but the code is syntactically valid so I cannot pinpoint the logical issues with it.

def display_board(board):  # Board setup
  print('\n'*100)
  print(board[7] + '|' + board[8] + '|' + board[9])
  print(board[4] + '|' + board[5] + '|' + board[6])
  print(board[1] + '|' + board[2] + '|' + board[3])

def player_input():  # Player assignment - use while loop to keep asking until a valid character is entered

    marker = ''
    while marker != 'X' and marker != 'O':
        marker = input('Player1: Choose X or O: ').upper()

    if marker == 'X':
        return ('X','O')
    else:
        return ('O','X')

def place_marker(board, marker, position):   # Allows player to place their marker at specific board index

    board[position] = marker

def win_check(board, mark):  # Check all rows, columns, diagonals for sharing the same marker to check for a winner
    return ((board[1] and board[2] and board[3] == mark) or   # Rows
    (board[4] and board[5] and board[6] == mark) or
    (board[7] and board[8] and board[9] == mark) or
    (board[1] and board[4] and board[7] == mark) or   # Columns
    (board[2] and board[5] and board[8] == mark) or
    (board[3] and board[6] and board[9] == mark) or
    (board[1] and board[5] and board[9] == mark) or   # Diagonals
    (board[3] and board[5] and board[7] == mark))

import random

def choose_first():  # Randomize who goes first

    flip = random.randint(0,1)
    if flip == 0:
        return 'Player 1'
    else:
        return 'Player 2'

def space_check(board, position):   # Check to see if a space on the board is still available
   return board[position] == ' '

def full_board_check(board):  # Checks to see if board is full resulting in a draw
    for i in range(1,10):
        if space_check(board,i):  # If there is free space, board is NOT full
            return False
    return True

def player_choice(board):  # Asks for the player's next move choice
    position = 0

    while position not in [1,2,3,4,5,6,7,8,9] or not space_check(board, position):
        position = int(input('Choose a position: (1-9): '))

    return position

def replay():   # Asks if the players want to play again
    choice = input("Play again? Enter Yes or No: ")
    return choice == 'Yes'

# Logic to run the game
# While loop needed to keep running the game
# Need to break out of the while loop on replay()

print ('Welcome to TIC TAC TOE')

while True:
    # Game Setup (Board, Players, Player turns)
    the_board = [' ']*10
    player1_marker,player2_marker = player_input()

    turn = choose_first()
    print(turn + ' will go first')

    play_game = input('Ready to play? y or n: ')
    if play_game == 'y':
        game_on = True
    else: game_on = False

    # Game Play
    while game_on:
        if turn == 'Player1':
            # Show the board
            display_board(the_board)
            # Choose a place to move
            position = player_choice(the_board)
            # Place the marker on the position
            place_marker(the_board,player1_marker,position)

            # Check if they won
            if win_check(the_board,player1_marker):
                display_board(the_board)
                print('PLAYER 1 HAS WON!')
                game_on = False
            else:
                if full_board_check(the_board):  # Check for tie
                    display_board(the_board)
                    print("TIE GAME!")
                    game_on = False
                else:
                    turn = 'Player 2'

        else:   
            # Show the board
            display_board(the_board)
            # Choose a place to move
            position = player_choice(the_board)
            # Place the marker on the position
            place_marker(the_board,player2_marker,position)

            # Check if they won
            if win_check(the_board,player2_marker):
                display_board(the_board)
                print('PLAYER 2 HAS WON!')
                game_on = False
            else:
                if full_board_check(the_board):
                    display_board(the_board)
                    print("TIE GAME!")
                    game_on = False
                else:
                    turn = 'Player 1' 

    if not replay():
        break

I want the game to go back and forth between each player with the correct markers assigned to them and I cannot figure out why this isn't happening as it looks correct to me.


Solution

  • The reason the turn was not going properly to "Player 1" is because you had a space missing in the check for that player. You also are not properly checking for when a player wins, which is why you are having that weird top row behavior. You need to check every position, not just the last one. I also added a check on user input to make sure that what the user enters is a number and it does not crash if not.

    I totally do not understand why you basically print your board upside down but I left that as is.

    Try this:

    import random
    
    def display_board(board):  # Board setup
      print('\n'*100)
      print(board[7] + '|' + board[8] + '|' + board[9])
      print(board[4] + '|' + board[5] + '|' + board[6])
      print(board[1] + '|' + board[2] + '|' + board[3])
    
    def player_input():  # Player assignment - use while loop to keep asking until a valid character is entered
    
        marker = ''
        while marker != 'X' and marker != 'O':
            marker = input('Player1: Choose X or O: ').upper()
    
        if marker == 'X':
            return ('X','O')
        else:
            return ('O','X')
    
    def place_marker(board, marker, position):   # Allows player to place their marker at specific board index
    
        board[position] = marker
    
    def win_check(board, mark):  # Check all rows, columns, diagonals for sharing the same marker to check for a winner
        return ((board[1] == mark and board[2] == mark and board[3] == mark) or   # Rows
        (board[4] == mark and board[5] == mark and board[6] == mark) or
        (board[7] == mark and board[8] == mark and board[9] == mark) or
        (board[1] == mark and board[4] == mark and board[7] == mark) or   # Columns
        (board[2] == mark and board[5] == mark and board[8] == mark) or
        (board[3] == mark and board[6] == mark and board[9] == mark) or
        (board[1] == mark and board[5] == mark and board[9] == mark) or   # Diagonals
        (board[3] == mark and board[5] == mark and board[7] == mark))
    
    def choose_first():  # Randomize who goes first
        flip = random.randint(0,1)
        if flip == 0:
            return 'Player 1'
        else:
            return 'Player 2'
    
    def space_check(board, position):   # Check to see if a space on the board is still available
       return board[position] == ' '
    
    def full_board_check(board):  # Checks to see if board is full resulting in a draw
        for i in range(1,10):
            if space_check(board,i):  # If there is free space, board is NOT full
                return False
        return True
    
    def player_choice(board):  # Asks for the player's next move choice
        position = 0
    
        while position not in [1,2,3,4,5,6,7,8,9] or not space_check(board, position):
            try:
                position = int(input('Choose a position: (1-9): '))
            except:
                print("Please enter a valid number.")
    
        return position
    
    def replay():   # Asks if the players want to play again
        choice = input("Play again? Enter Yes or No: ")
        return choice == 'Yes'
    
    
    
    # Logic to run the game
    # While loop needed to keep running the game
    # Need to break out of the while loop on replay()
    
    print ('Welcome to TIC TAC TOE')
    
    while True:
        # Game Setup (Board, Players, Player turns)
        the_board = [' ']*10
        player1_marker,player2_marker = player_input()
    
        turn = choose_first()
        print(turn + ' will go first')
    
        play_game = input('Ready to play? y or n: ')
        if play_game == 'y':
            game_on = True
        else: game_on = False
    
        # Game Play
        while game_on:
            if turn == 'Player 1':
                # Show the board
                display_board(the_board)
                # Choose a place to move
                position = player_choice(the_board)
                # Place the marker on the position
                place_marker(the_board,player1_marker,position)
    
                # Check if they won
                if win_check(the_board,player1_marker):
                    display_board(the_board)
                    print('PLAYER 1 HAS WON!')
                    game_on = False
                else:
                    if full_board_check(the_board):  # Check for tie
                        display_board(the_board)
                        print("TIE GAME!")
                        game_on = False
                    else:
                        turn = 'Player 2'
    
            else:   
                # Show the board
                display_board(the_board)
                # Choose a place to move
                position = player_choice(the_board)
                # Place the marker on the position
                place_marker(the_board,player2_marker,position)
    
                # Check if they won
                if win_check(the_board,player2_marker):
                    display_board(the_board)
                    print('PLAYER 2 HAS WON!')
                    game_on = False
                else:
                    if full_board_check(the_board):
                        display_board(the_board)
                        print("TIE GAME!")
                        game_on = False
                    else:
                        turn = 'Player 1' 
    
        if not replay():
            break