Search code examples
pythontkinterbuttontic-tac-toe

Why is the game ending a draw when player wins in python Tic Tac Toe


I've been creating a tic-tac-toe game, the game works fine. The player can win, lose and tie. The problem is when all 9 tiles have been used and there's a win or loss, the draw messagebox appears after the win or loss messagebox. I am using a click count to handle the draw, when the click count reaches 9 i want it to be a tie which does works. However, if there is a win or loss on the 9 turn i want it to only say win or loss without the tie message following.

def btn_click(row, col):
    global hasClicked, clickCount

    if buttonGrid[row][col]["text"] == "" and hasClicked == True:
        
        buttonGrid[row][col]["text"] = "X"
        clickCount += 1
            
        #now check for win
        if who_wins("X"):
            messagebox.showinfo("O-X-O", "You win, Congratulations!")
            messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
            disable_buttons()
            
        else:
            computer_turn()
            if who_wins("O"):
                messagebox.showinfo("O-X-O", "You lose, Unlucky!")
                messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
                
        if clickCount == 9:
            messagebox.showinfo("O-X-O", "It was a Draw!")
            messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")

Gif of what's happening


Solution

  • This is expected. After the if...else block, execution will still continue to execute the next if statement.

    Make sure this code is in a function that you can exit, and use return:

            if who_wins("X"):
                messagebox.showinfo("O-X-O", "You win, Congratulations!")
                messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
                disable_buttons()
                return  # <--
            else:
                computer_turn()
                if who_wins("O"):
                    messagebox.showinfo("O-X-O", "You lose, Unlucky!")
                    messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
                    return # <-- 
                    
            if clickCount == 9:
                messagebox.showinfo("O-X-O", "It was a Draw!")
                messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
                return # <--
    

    Or if this code appears in a loop, you can opt to use break. It all depends on the larger context around this code.

    NB: It is not clear why you would only call disable_buttons() when "X" wins. Shouldn't this happen when "O" wins as well?

    You could also introduce a boolean for registering whether the game has ended, like so:

            gamover = who_wins("X")
            if gameover:
                messagebox.showinfo("O-X-O", "You win, Congratulations!")
            else:
                computer_turn()
                gameover = who_wins("O"):
                if gameover:
                    messagebox.showinfo("O-X-O", "You lose, Unlucky!")
            if not gameover and clickCount == 9:
                messagebox.showinfo("O-X-O", "It was a Draw!")
                gameover = True
            if gameover: 
                messagebox.showinfo("O-X-O", "Go to Menu to play again or quit!")
                disable_buttons()