Search code examples
pythonpython-3.xfunctionif-statementtic-tac-toe

Python: My if statement is not working but I don't get any error?


I am creating a tic-tac-toe game and the move_base function in my script is not working. I have seen this type of if statement used before and I don't know why the function is not working. There are no errors but the function doesn't update num_word or moves. I do not have a lot of python experience so I do not know what I am doing wrong. I will add more features to the game but I can't because the basic part of it is not working. I have not seen any other place that tells me how to fix this.

#tic tac toe game
#global variables
game_over = False

#game script
def game():
    #game variables

    #positions on the board
    one = '1'
    two = '2'
    three = '3'
    four = '4'
    five = '5'
    six = '6'
    seven = '7'
    eight = '8'
    nine = '9'
    positions = [one, two, three, four, five, six, seven, eight, nine]

    num_chosen = ''
    #moves in the game
    moves = 0

    #prints board
    def board():
        print(f'{one}|{two}|{three}')
        print(f'{four}|{five}|{six}')
        print(f'{seven}|{eight}|{nine}')

    #how to check who won
    def check_win_base(xo, num1, num2, num3):
        if num1 == xo and num2 == xo and num3 == xo:
            if(xo == 'x'):
                print('x player wins')
                game_over = True
            elif(xo == 'o'):
                print('o player wins')
                game_over = True
    #check_win_base applied to all numbers
    def check_win(xo):
        check_win_base(xo, one, two, three)
        check_win_base(xo, four, five, six)
        check_win_base(xo, seven, eight, nine)
        check_win_base(xo, one, four, seven)
        check_win_base(xo, two, five, eight)
        check_win_base(xo, three, six, nine)
        check_win_base(xo, one, five, nine)
        check_win_base(xo, three, five, seven)

    #checks if game is a draw
    def check_draw():
        if moves == 9:
            print('The game is a draw')
            game_over = True

    #how to pick a square
    def move_base(xo, num_word, num):    
        if num_chosen == num:
            num_word = xo
            moves += 1
    #move_base applied to all numbers
    def move(xo):
        move_base(xo, one, 1)
        move_base(xo, two, 2)
        move_base(xo, three, 3)
        move_base(xo, four, 4)
        move_base(xo, five, 5)
        move_base(xo, six, 6)
        move_base(xo, seven, 7)
        move_base(xo, eight, 8)
        move_base(xo, nine, 9)

    #all the required functions put together
    def turn(xo):
        board()
        print(f'{xo} move')
        num_chosen = int(input())
        move(xo)
        check_win(xo)
        check_draw()

    turn('x')
    turn('o')
    turn('x')
    turn('o')
    turn('x')
    turn('o')
    turn('x')
    turn('o')
    turn('x')

#checks if game is over or not
if game_over == False:
    game()
else:
    print('Game Over')

Solution

  • a few key points about variables in python

    you may read and change global variables, but cannot assign new values to them unless you specify this is a global variable, therefor this does not work

    def check_draw():
    if moves == 9:
        print('The game is a draw')
        game_over = True
    

    but this does

    def check_draw():
    global game_over
    if moves == 9:
        print('The game is a draw')
        game_over = True
    

    simple types like string,int,float are immutable, means you cannot change them, because in a result you get another object. In this example by changing num_word and moves you actually assign new value which creates local copy of those variables without changing it's global counterpart

    def move_base(xo, num_word, num):    
            if num_chosen == num:
                num_word = xo
                moves += 1
    

    solution to this mess is simple - use mutable objects, like dict or list, to retain changes

    here is example which works (more or less)

    # tic tac toe game
    #global variables
    game_over = False
    
    # game script
    
    
    def game():
        # game variables
    
        # positions on the board
        positions = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
    
        d = {
            "one": '1',
            "two": '2',
            "three": '3',
            "four": '4',
            "five": '5',
            "six": '6',
            "seven": '7',
            "eight": '8',
            "nine": '9',
            "num_chosen": "",
            "moves": 0,  # moves in the game
        }
    
        # prints board
        def board():
            print(f'{d["one"]}|{d["two"]}|{d["three"]}')
            print(f'{d["four"]}|{d["five"]}|{d["six"]}')
            print(f'{d["seven"]}|{d["eight"]}|{d["nine"]}')
    
        # how to check who won
        def check_win_base(xo, num1, num2, num3):
            global game_over
            if num1 == xo and num2 == xo and num3 == xo:
                if(xo == 'x'):
                    print('x player wins')
                    game_over = True
                elif(xo == 'o'):
                    print('o player wins')
                    game_over = True
        # check_win_base applied to all numbers
    
        def check_win(xo):
            check_win_base(xo, d["one"], d["two"], d["three"])
            check_win_base(xo, d["four"], d["five"], d["six"])
            check_win_base(xo, d["seven"], d["eight"], d["nine"])
            check_win_base(xo, d["one"], d["four"], d["seven"])
            check_win_base(xo, d["two"], d["five"], d["eight"])
            check_win_base(xo, d["three"], d["six"], d["nine"])
            check_win_base(xo, d["one"], d["five"], d["nine"])
            check_win_base(xo, d["three"], d["five"], d["seven"])
    
        # checks if game is a draw
        def check_draw():
            global game_over
            if d["moves"] == 9:
                print('The game is a draw')
                game_over = True
    
        # how to pick a square
        def move_base(xo, num_word, num):
            if d["num_chosen"] == num:
                d[num_word] = xo
                d["moves"] += 1
        # move_base applied to all numbers
    
        def move(xo):
            move_base(xo, "one", 1)
            move_base(xo, "two", 2)
            move_base(xo, "three", 3)
            move_base(xo, "four", 4)
            move_base(xo, "five", 5)
            move_base(xo, "six", 6)
            move_base(xo, "seven", 7)
            move_base(xo, "eight", 8)
            move_base(xo, "nine", 9)
    
        # all the required functions put together
        def turn(xo):
            board()
            print(f'{xo} move')
            d["num_chosen"] = int(input())
            move(xo)
            check_win(xo)
            check_draw()
    
        turn('x')
        turn('o')
        turn('x')
        turn('o')
        turn('x')
        turn('o')
        turn('x')
        turn('o')
        turn('x')
    
    
    # checks if game is over or not
    if game_over == False:
        game()
    else:
        print('Game Over')