Search code examples
pythontic-tac-toe

How can correct the draw function in Tic-Tac-Toe game?


    for i in range(1, 10):

        valid_move = False
        while not valid_move:
            move = (input("Player1 your turn with X. Please choose a cell: "))
            if not move.isdigit():
                print("Please insert a cell number from 1-9.")

            else:
                valid_move = make_move(player1,move)
                if valid_move:
                    printBoard(theBoard)
                    break

        if (theBoard['7'] == theBoard['8'] == theBoard['9'] == player1) or \
                (theBoard['4'] == theBoard['5'] == theBoard['6'] == player1) or \
                (theBoard['1'] == theBoard['2'] == theBoard['3'] == player1) or \
                (theBoard['7'] == theBoard['4'] == theBoard['1'] == player1) or \
                (theBoard['8'] == theBoard['5'] == theBoard['2'] == player1) or \
                (theBoard['9'] == theBoard['6'] == theBoard['3'] == player1) or \
                (theBoard['7'] == theBoard['5'] == theBoard['3'] == player1) or \
                (theBoard['9'] == theBoard['5'] == theBoard['1'] == player1):
            print("Player1 wins!")
            theBoard = {key: ' ' for key in theBoard}  # Reset the board
            break


        valid_move = False
        while not valid_move:
            move = (input("Player2 your turn with O. Please choose a cell: "))
            if not move.isdigit():
                print("Please insert a cell number.")

            else:
                valid_move = make_move(player2, move)
                if valid_move:
                    printBoard(theBoard)
                    break

        if (theBoard['7'] == theBoard['8'] == theBoard['9'] == player2) or \
                (theBoard['4'] == theBoard['5'] == theBoard['6'] == player2) or \
                (theBoard['1'] == theBoard['2'] == theBoard['3'] == player2) or \
                (theBoard['7'] == theBoard['4'] == theBoard['1'] == player2) or \
                (theBoard['8'] == theBoard['5'] == theBoard['2'] == player2) or \
                (theBoard['9'] == theBoard['6'] == theBoard['3'] == player2) or \
                (theBoard['7'] == theBoard['5'] == theBoard['3'] == player2) or \
                (theBoard['9'] == theBoard['5'] == theBoard['1'] == player2):
            print("Player2 wins!")
            theBoard = {key: ' ' for key in theBoard}  # Reset the board
            break


        `if i == 9:
            print("It's a draw!")
            theBoard = {key: ' ' for key in theBoard}
            break  # Reset the board`

elif start_question.lower() == "no":
    print("The game is over.")
    game = False

else:
    print("Please respond 'Yes' or 'No'.")

I was trying to use the function in order to stop the tic-tac-toe game after the 9th round, which implifies the draw of the game. However, the function is not triggered and doesn't react if all 9 rounds have gone.

I tried to implement the function, which would stop a game when the 9 rounds are gone.


Solution

  • The condition i == 9 is not true at the moment of a draw. The draw occurs earlier, since in every iteration of your loop two moves are made. If a draw is reached, it will always be the first player that plays the last move (their fifth move), so the draw-check should be made before the second player takes their turn.

    So the solution is to move this block:

    if i == 9:
        print("It's a draw!")
        theBoard = {key: ' ' for key in theBoard}
        break
    

    ... and place it just before valid_move = False (half-way the loop's body), and change the condition:

    if i == 5:
        print("It's a draw!")
        theBoard = {key: ' ' for key in theBoard}
        break
    

    You can then also change the for loop's range, although it is not absolutely necessary as the loop will always end with a break.

    Unlrelated, but there are many things that can be improved in your code. Some high-level hints:

    • Don't mix game logic and printing in the same function: instead keep your functions dedicated to either printing (like printBoard: good example), or business logic (like make_move, which I hope, doesn't print). The main loop should then only call functions of either type.
    • Don't repeat similar code (like checking for a win, getting input from the user, ...etc), but instead make more functions (one could be is_win) that take argument(s) to cover for the slight differences (like: which player), and introduce the concept of toggling the player, so that you can reuse the same code for a different player.