Jump to content

if-statement triggering even when condition is false?!

Go to solution Solved by elpiop,

change if(not(check_legal(x,y,number,game_board)) in your play_game() function to:

if check_legal(x,y,number,game_board) == False:
            print("Illegal move!")

 

 

Hi.

I am working on an assignment where I need to create a simple sudoku-game in Python. I have most of the logic for the same, but I am having troubles in my chech_legal function, that basically checks if you are allowed to place a number in that spot.

Essentially, I have been bug-testing, and the following code-snippet is making me scratch my head:

    elif (x<3) and (y<6):
        print("2")
        print(number)
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    return False

I am working on the following board:

    0 1 2   3 4 5   6 7 8 
  +-------+-------+-------+
0 | 0 0 6 | 9 0 5 | 0 1 0 |
1 | 9 7 0 | 0 1 2 | 3 0 5 |
2 | 0 2 0 | 0 0 4 | 8 6 0 |
  +-------+-------+-------+
3 | 5 0 3 | 8 0 0 | 0 2 0 |
4 | 0 0 0 | 0 0 0 | 0 0 0 |
5 | 0 8 0 | 0 0 1 | 9 0 7 |
  +-------+-------+-------+
6 | 0 5 4 | 1 0 0 | 0 7 0 |
7 | 2 0 7 | 4 5 0 | 0 9 3 |
8 | 0 6 0 | 7 0 3 | 1 0 0 |
  +-------+-------+-------+

In my example, I tested with x-coord 0, y-coord 3. Which would give the 5 marked in red. 

Now, as you can see in my code-snippet, I am controlling that the outer elif-condition is true by printing the number 2. I also print the variable number, just to make sure. In this case, number = 4.

The code traverses correctly, the output from the for-loop is:
5 0 0 0 0 8 3 0 0 - YES, it traversed that square correctly. And, NONE of those should equal 4- BUT ... the function returns FALSE.

I am controlling that there are no other if or elifs in that function by printing numbers after all condition checks.

 

You can see that in my full code here:

Spoiler

def main():
    open_game_file()

# read a game_board from file
def open_game_file():
    filename = input ("What game file do you want to open (exl. .txt): ")
    # open file
    file = open(filename+'.txt','r')
    # read the file line by line into a 2d-list
    game_board = [[int(n) for n in line.split()] for line in file]
    # close file
    file.close()
    # initialize game
    play_game(game_board)

def play_game(game_board):
    # initially print game_board
    print_board(game_board)

    # while-loop that runs the game
    while (not(won_game(game_board))):
        # ask if player wants to continue
        cont = input("Do you wish to continue(y/n): ")
        if (cont == "n"):
            file = input("What do you want to name this particular game: ")
            # WRITE TO FILE
        # ask for what number to change
        y = int(input("x-coordinate of number to change: "))
        x = int(input("y-coordinate of number to change: "))
        # ask for number to replace current
        number = int(input("Number to replace current: "))
        # check if legal replacement
        if(not(check_legal(x,y,number,game_board))):
            print("Illegal move!")
            print("----------------------------------------")
            print_board(game_board)
            continue
        game_board[x][y] = number
        print_board(game_board)
        print("----------------------------------------")

def print_board(game_board):
    # print start-format
    print("    0 1 2   3 4 5   6 7 8   ")
    print("  +-------+-------+-------+")
    # split list in 3 to add lines
    for i in range(3):
        print (i, "|", "", end='')
        for j in range(9):
            if (j == 2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")
    for i in range(3,6):
        print(i, "|", "", end='')
        for j in range(9):
            if (j==2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")
    for i in range(6,9):
        print(i, "|", "", end='')
        for j in range(9):
            if (j==2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")

def check_legal(y,x,number,game_board):
    # check vertical line
    for i in range (9):
        if game_board[i][x] == number:
            print("ye")
            return False
    # check horizontal line
    for j in range (9):
        if game_board[y][j] == number:
            print("ey")
            return False
    # check first col of squares
    if (x<3) and (y<3):
        print("1")
        for i in range (3):
            for j in range(3):
                print(game_board[j][i])
                if game_board[j][i] == number:
                    return False
    elif (x<3) and (y<6):
        print("2")
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    return False
    elif (x<3) and (y<9):
        print("3")
        for i in range (3):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    # check second col of squares
    elif (x<6) and (y<3):
        print("4")
        for i in range (3,6):
            for j in range(3):
                if game_board[j][i] == number:
                    return False
    elif (x<6) and (y<6):
        print("5")
        for i in range (3,6):
            for j in range(3,6):
                if game_board[j][i] == number:
                    return False
    elif (x<6) and (y<9):
        print("6")
        for i in range (3,6):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    # check third col of squares
    elif (x<9) and (y<3):
        print("7")
        for i in range (6,9):
            for j in range(3):
                if game_board[j][i] == number:
                    return False
    elif (x<9) and (y<6):
        print("8")
        for i in range (6,9):
            for j in range(3,6):
                if game_board[j][i] == number:
                    return False
    elif (x<9) and (y<9):
        print("9")
        for i in range (6,9):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    else:
        print("true")
        return True
def won_game(game_board):
    # search for a single '0' on the board
    return not(any(0 in x for x in game_board))

main()

 

The file "gam1.txt" looks like this:

0 0 6 9 0 5 0 1 0
9 7 0 0 1 2 3 0 5
0 2 0 0 0 4 8 6 0
5 0 3 8 0 0 0 2 0
0 0 0 0 0 0 0 0 0
0 8 0 0 0 1 9 0 7
0 5 4 1 0 0 0 7 0
2 0 7 4 5 0 0 9 3
0 6 0 7 0 3 1 0 0

 

 

TLDR:
Why does:

    elif (x<3) and (y<6):
        print("2")
        print(number)
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    return False

Return FALSE when x=0, y=3, number=4 and game_board output: 5 0 0 0 0 8 3 0 0?

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

I just took a quick look at your whole code, and you might have a problem with those elif statements (rather than doing all less thens, I'd try to break them up/give them proper ranges -- i.e. make it so that you can put them in any order without everything breaking).

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

Just now, djdwosk97 said:

I just took a quick look at your whole code, and you might have a problem with those elif statements (rather than doing all less thens, I'd try to break them up/give them proper ranges).

I am planning to do that once I actually have a working prototype of the game-logic. 

I just simply do not understand why the else never runs. 

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

8 minutes ago, Claryn said:

I am planning to do that once I actually have a working prototype of the game-logic. 

I just simply do not understand why the else never runs. 

print out the value of the game_board[j] and the number when it returns false. (also, are you positive that's where it's returning false?)

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to post
Share on other sites

2 minutes ago, djdwosk97 said:

print out the value of the game_board[j] and the number when it returns false. 

Strange.

It runs through the whole square, as the output is 500008300, when x=0, y=3, num=4. However, I added a print("test") inside the if to check if it actually triggered. It didnt.

 

    elif (x<3) and (y<6):
        print("2")
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    print("test")
                    return False

Also no other ifs, elifs or else in that function triggered (proven from my prints inside all of them). It still returned false. 

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

3 minutes ago, elpiop said:

change if(not(check_legal(x,y,number,game_board)) in your play_game() function to:


if check_legal(x,y,number,game_board) == False:
            print("Illegal move!")

  

I dont know why, but it fixed it.

 

Isnt if !(condition) the same as if condition == False?

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

When you call check_legal(), it does not reach the part in the elif ladder statement to return False (as you saw and tested), so it returns 'None'. not(None) evaluates to true, thus that part of code with always run and print "illegal move"

Link to post
Share on other sites

3 minutes ago, elpiop said:

When you call check_legal(), it does not reach the part in the elif ladder statement to return False (as you saw and tested), so it returns 'None'. not(None) evaluates to true, thus that part of code with always run and print "illegal move"

What about the else at the end, which returns True? 

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

It doesn't ever reach that point. Since x<3 and y<6, this code below will evaluate to True, so it will go run all the expressions in this statement (which returns 'None'). Afterwards it will break out of the else/if ladder. The else will only be executed if all of the elif statements evaluate to False (for example, if you input x>9 and y>9, since you have no elif statements to handle that).

 elif (x<3) and (y<6):
        print("2")
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    print("test")
                    return False

Python if...else statement 

 

Here's a flow diagram I found to explain the logic. You can see that it will skip the else statement since one of the if statements was found to be True.

Link to post
Share on other sites

4 minutes ago, elpiop said:

It doesn't ever reach that point. Since x<3 and y<6, this code below will evaluate to True, so it will go run all the expressions in this statement (which returns 'None'). Afterwards it will break out of the else/if ladder. The else will only be executed if all of the elif statements evaluate to False (for example, if you input x>9 and y>9, since you have no elif statements to handle that).


 elif (x<3) and (y<6):
        print("2")
        for i in range (3):
            for j in range(3,6):
                print(game_board[j][i])
                if (game_board[j][i] == number):
                    print("test")
                    return False

Python if...else statement 

 

Here's a flow diagram I found to explain the logic. You can see that it will skip the else statement since one of the if statements was found to be True.

Aha, I got it.

 Thanks a lot.

 

 

Update:
 

# Oving 10 ITGK
# -*- coding: utf8 -*-

# Oppgave 2 Sudoku

def main():
    open_game_file()

# read a game_board from file
def open_game_file():
    filename = input ("What game file do you want to open (excl. .txt): ")
    # open file
    file = open(filename+'.txt','r')
    # read the file line by line into a 2d-list
    game_board = [[int(n) for n in line.split()] for line in file]
    # close file
    file.close()
    # initialize game
    play_game(game_board)

def play_game(game_board):
    # initially print game_board
    print_board(game_board)

    # while-loop that runs the game
    while (not(won_game(game_board))):
        # ask if player wants to continue
        cont = input("Do you wish to continue(y/n): ")
        if (cont == "n"):
            filename = input("What do you want to name this particular game (excl. .txt): ")
            file = open(filename+'.txt','w')
            # WRITE TO FILE
            for i in range(9):
                for j in range(9):
                    s = str(game_board[i][j])
                    if (j == 8):
                        b = "\n"
                        s = (s + b)
                        file.write(s)
                    else:
                        a = " "
                        s = (s + a)
                        file.write(s)
            break
        elif (cont != "y"):
            continue
        # ask for what number to change
        y = int(input("x-coordinate of number to change: "))
        x = int(input("y-coordinate of number to change: "))
        # ask for number to replace current
        number = int(input("Number to replace current: "))
        # check if legal replacement
        if((check_legal(x,y,number,game_board))==False):
            print("Illegal move!")
            print("----------------------------------------")
            print_board(game_board)
            continue
        # make the number change
        game_board[x][y] = number
        # print updated board
        print_board(game_board)
        print("----------------------------------------")
    # check win
    if (won_game(game_board)):
        print("You won the game!")

def print_board(game_board):
    # print start-format
    print("    0 1 2   3 4 5   6 7 8   ")
    print("  +-------+-------+-------+")
    # split list in 3 to add lines
    for i in range(3):
        print (i, "|", "", end='')
        for j in range(9):
            if (j == 2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")
    for i in range(3,6):
        print(i, "|", "", end='')
        for j in range(9):
            if (j==2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")
    for i in range(6,9):
        print(i, "|", "", end='')
        for j in range(9):
            if (j==2) or (j==5):
                print(game_board[i][j], "|", "", end='')
            elif j==8:
                print(game_board[i][j], "|")
            else:
                print(game_board[i][j], "", end='')
    print("  +-------+-------+-------+")

def check_legal(y,x,number,game_board):
    # check vertical line
    for i in range (9):
        if game_board[i][x] == number:
            return False
    # check horizontal line
    for j in range (9):
        if game_board[y][j] == number:
            return False
    # check first col of squares
    if (x<3) and (y<3):
        for i in range (3):
            for j in range(3):
                if game_board[j][i] == number:
                    return False
    elif (x<3) and (y<6):
        for i in range (3):
            for j in range(3,6):
                if (game_board[j][i] == number):
                    return False
    elif (x<3) and (y<9):
        for i in range (3):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    # check second col of squares
    elif (x<6) and (y<3):
        for i in range (3,6):
            for j in range(3):
                if game_board[j][i] == number:
                    return False
    elif (x<6) and (y<6):
        for i in range (3,6):
            for j in range(3,6):
                if game_board[j][i] == number:
                    return False
    elif (x<6) and (y<9):
        for i in range (3,6):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    # check third col of squares
    elif (x<9) and (y<3):
        for i in range (6,9):
            for j in range(3):
                if game_board[j][i] == number:
                    return False
    elif (x<9) and (y<6):
        for i in range (6,9):
            for j in range(3,6):
                if game_board[j][i] == number:
                    return False
    elif (x<9) and (y<9):
        for i in range (6,9):
            for j in range(6,9):
                if game_board[j][i] == number:
                    return False
    else:
        return True
def won_game(game_board):
    # search for a single '0' on the board
    return not(any(0 in x for x in game_board))

main()

Here is the whole shazzle. Reading and writing to files working, along with all game-logic, in the following format:

 

0 0 6 9 0 5 0 1 0
9 7 0 0 1 2 3 0 5
0 2 0 0 0 4 8 6 0
5 0 3 8 0 0 0 2 0
0 0 0 0 0 0 0 0 0
0 8 0 0 0 1 9 0 7
0 5 4 1 0 0 0 7 0
2 0 7 4 5 0 0 9 3
0 6 0 7 0 3 1 0 0

 

Running Arch with i3-gaps on a Thinkpad X1 Extreme
Data Science Postgrad

 

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×