user6042714
user6042714

Reputation:

How to switch between players in tic tac toe in Python

The rest of my code does what I want it to do for now. I can't for the life of me figure out why I can't switch between players. The code I have makes sense to me. This is a two-part question: How can I fix this using the same sort of approach I've taken AND ALSO how would you have done it?

board_tiles = [0, 1, 2, 3, 4, 5, 6, 7, 8]
tiles_available = [0, 1, 2, 3, 4, 5, 6, 7, 8]

# create a function that draw the board
def draw_board():
    #call clear_screen()

    print(f'{board_tiles[0]} | {board_tiles[1]} | {board_tiles[2]}')
    print('------------------')
    print(f'{board_tiles[3]} | {board_tiles[4]} | {board_tiles[5]}')
    print('------------------')
    print(f'{board_tiles[6]} | {board_tiles[7]} | {board_tiles[8]}')

# create a function that prompts the user to choose a character
def player_input():
    mark = input('Would you like to be "X" or "O"? ').lower()
    if mark == 'x':
        player1 = 'x'
        player2 = 'o'
    else:
        player1 = 'o'
        player2 = 'x'
    print(f'Player1, you are {player1}.  That means Player2 is {player2}.  LETS PLAY!')

    return player1, player2

# create a function that defines a win
def winning_combo(player1, player2):
    players = [player1, player2]
    turn = 0
    player = players[turn]
    turn = (turn + 1) % len(players)
    while tiles_available:
        move = int(input('Where would you like to move? '))
        if move in tiles_available:
            tiles_available.remove(move)
            board_tiles.insert(board_tiles[move], player)
            board_tiles.remove(move)
        else:
            print('That move has already been taken.')

        return move, turn, player

# create a function to determine when a player wins
def win_combo():
    if board_tiles[0] == board_tiles[1] == board_tiles[2] or \
        board_tiles[3] == board_tiles[4] == board_tiles[5] or \
        board_tiles[6] == board_tiles[7] == board_tiles[8] or \
        board_tiles[0] == board_tiles[3] == board_tiles[6] or \
        board_tiles[1] == board_tiles[4] == board_tiles[7] or \
        board_tiles[2] == board_tiles[5] == board_tiles[8] or \
        board_tiles[0] == board_tiles[4] == board_tiles[8] or \
        board_tiles[2] == board_tiles[4] == board_tiles[6]:
        quit()
    else:
        True
# create a game function
def game():
    playing = True
    player1, player2 = player_input()
    while playing:
        draw_board()
        winning_combo(player1, player2)
        win_combo()

game()

Upvotes: 0

Views: 7733

Answers (2)

Bernardo Chamarelli
Bernardo Chamarelli

Reputation: 11

board_tiles = [1, 2, 3, 4, 5, 6, 7, 8, 9]
tiles_available = [1, 2, 3, 4, 5, 6, 7, 8, 9]

# create a function that draw the board
def draw_board():
    #call clear_screen()
    print(f"""
    {board_tiles[6]} | {board_tiles[7]} | {board_tiles[8]}
   ---+---+---
    {board_tiles[3]} | {board_tiles[4]} | {board_tiles[5]}
   ---+---+---
    {board_tiles[0]} | {board_tiles[1]} | {board_tiles[2]}
""")

# create a function that defines a win
def winning_combo(player1, player2):
    players = [player1, player2]
    global turn
    player = players[turn]
    turn = (turn + 1) % len(players)
    moove = ''
    while tiles_available:
        if turn != 1:
            moove = player2
        else:
            moove = player1
        # player 1 = 1 player 2 = 0
        move = int(input(f'Player {moove}, Where would you like to move? '))
        real_move = move - 1
        if move in tiles_available:
            tiles_available.remove(move)
            board_tiles.insert(board_tiles[real_move], player)
            board_tiles.remove(move)
        else:
            print('That move has already been taken.')

        return move, turn, player

# create a function to determine when a player wins
def win_combo():
    play_1 = 'X'
    play_2 = 'O'
    if board_tiles[0] == board_tiles[1] == board_tiles[2] == play_1 or \
        board_tiles[3] == board_tiles[4] == board_tiles[5] == play_1 or \
        board_tiles[6] == board_tiles[7] == board_tiles[8] == play_1 or \
        board_tiles[0] == board_tiles[3] == board_tiles[6] == play_1 or \
        board_tiles[1] == board_tiles[4] == board_tiles[7] == play_1 or \
        board_tiles[2] == board_tiles[5] == board_tiles[8] == play_1 or \
        board_tiles[0] == board_tiles[4] == board_tiles[8] == play_1 or \
        board_tiles[2] == board_tiles[4] == board_tiles[6] == play_1 :
        print(draw_board())
        print(f"{play_1} YOU ARE THE WINNER!")
    elif board_tiles[0] == board_tiles[1] == board_tiles[2] == play_2 or \
          board_tiles[3] == board_tiles[4] == board_tiles[5] == play_2 or \
          board_tiles[6] == board_tiles[7] == board_tiles[8] == play_2 or \
          board_tiles[0] == board_tiles[3] == board_tiles[6] == play_2 or \
          board_tiles[1] == board_tiles[4] == board_tiles[7] == play_2 or \
          board_tiles[2] == board_tiles[5] == board_tiles[8] == play_2 or \
          board_tiles[0] == board_tiles[4] == board_tiles[8] == play_2 or \
          board_tiles[2] == board_tiles[4] == board_tiles[6] == play_2:
        print(draw_board())
        print(f"{play_2} YOU ARE THE WINNER!")
    else:
        True

# create a game function
def game():
    global turn
    turn = 0
    playing = 0
    player1, player2 = 'X', 'O'
    while playing < 10:
        draw_board()
        winning_combo(player1, player2)
        win_combo()
        if playing == 9:
            print("It's a TIE!!!")
            playing = 10
        playing += 1

game()

Upvotes: 1

abarnert
abarnert

Reputation: 365697

There are actually multiple problems here, but let's get to the root of it:

The winning_combo function resets turn = 0 at the start of each call. Sure, you update it to 1 with that turn = (turn + 1) % len(players), but you're never going to use the value again; you just return from the function, and then call it again, and then set turn = 0 again.

The simplest fix here would be to use a global variable for turn, so it can be persistent across calls:

def winning_combo(player1, player2):
    global turn
    players = [player1, player2]
    player = players[turn]
    turn = (turn + 1) % len(players)
    while tiles_available:
        # the rest of the code is the same

def game():
    global turn
    turn = 0
    playing = True
    # the rest of the code is the same

You may have heard that global variables are bad. Can you avoid one here? Sure. While you can't use a local variable in winning_combo, because that function keeps exiting and starting over again, you can use a local variable in game, and pass it in as a parameter to winning_combo:

def winning_combo(player1, player2, turn):
    players = [player1, player2]
    player = players[turn]
    while tiles_available:
        move = int(input('Where would you like to move? '))
        # the rest of the code is the same

def game():
    turn = 0
    playing = True
    player1, player2 = player_input()
    while playing:
        draw_board()
        winning_combo(player1, player2, turn)
        turn = (turn + 1) % 2
        win_combo()

There are many other ways you could improve your design and simplify your code, and bugs to fix (e.g., what happens when the game is a tie?), but this should get you past your current bug, and hopefully give you a little insight into how local variables work.

Upvotes: 1

Related Questions