Search code examples
pythontic-tac-toe

I have a problem with the win detection in a tic-tac-toe game in python 3


I'm a Python beginner and tried to write a simple Tic-Tac-Toe game (no GUI, just text-based). I defined a function for a move and after each move I call a functon for win / tie detection. But somehow the win and tie detection doesn't work, i.e. the game works fine, but when a player has 3 symbols in a row, the game just goes on and no win-message is shown. I already changed a few things with the code (e.g. the win checking function only returns 1, -1 or 0 now instead of directly returning the win message) and I read the code a few times but I don't find where the issue is :( Please help Here's the complete code:

board = {
    1: "1", 2: "2", 3: "3",
    4: "4", 5: "5", 6: "6",
    7: "7", 8: "8", 9: "9"
}
taken_spaces = []
players = ("X", "O")
current_player = players[0]
board_lines_win_check = {
    "row1": [board[1], board[2], board[3]],
    "row2": [board[4], board[5], board[6]],
    "row3": [board[7], board[8], board[9]],
    "col1": [board[1], board[4], board[7]],
    "col2": [board[2], board[5], board[8]],
    "col3": [board[3], board[6], board[9]],
    "diagonal_lr": [board[1], board[5], board[9]],
    "diagonal_rl": [board[3], board[5], board[7]]
}


def print_board():
    print(f'''
    {board[1]} | {board[2]} | {board[3]}
  ----|---|----
    {board[4]} | {board[5]} | {board[6]}
  ----|---|----
    {board[7]} | {board[8]} | {board[9]}''')


def player_input():
    print_board()
    print('')
    print(f"Player {current_player}'s turn!")
    while True:
        try:
            while True:
                player_move = int(input(f'Please enter the number of the place you want to set your mark: '))
                if (player_move >= 1) and (player_move <= 9) and player_move not in taken_spaces:
                    break
                else:
                    print('Please enter a number between 1 and 9 that has not yet been taken!')
            break
        except ValueError:
            print('Please enter a valid number')
    taken_spaces.append(player_move)
    return player_move


def move():
    player_move = player_input()
    board[player_move] = current_player
    return board


def win_tie_check():
    for line in board_lines_win_check:
        if line[0] == "X" and line[1] == "X" and line[2] == "X":
            return 1
        elif line[0] == "O" and line[1] == "O" and line[2] == "O":
            return -1
    else:
        for line in board_lines_win_check:
            for value in line:
                if value != "X" and value != "O":
                    return ""
            else:
                return 0


for i in range(9):
    move()
    if current_player == players[0]:
        current_player = players[1]
    else:
        current_player = players[0]
    if win_tie_check() == 1:
        print('Player X wins! Congratulations!')
        break
    elif win_tie_check() == -1:
        print('Player O wins! Congratulations')
        break
    elif win_tie_check() == 0:
        print("It's a tie! Good game!")
        break
print_board()

I suspect the problem is in the "win_tie_check()" function


Solution

  • board_lines_win_check is never updated when you're playing the game; so it's created with the base tic-tac-toe board and never updated. So when you loop through it to check for a win, it will never find one. You can check the updated board just by moving it into your win check so it creates a new dictionary of row/column/diagonals to check:

    def win_tie_check():
        to_check = [(1, 2, 3), (4, 5, 6), (7, 8, 9),
                    (1, 4, 7), (2, 5, 8), (3, 6, 9),
                    (1, 5, 9), (3, 5, 7)]
        for (a, b, c) in to_check:
            if board[a] == board[b] == board[c]:
                return 1 if board[a] == 'X' else -1
            else:
                return 0