2

I am trying to create a game (tic tac toe) and I have to create a board (called tab) using 3 tuples that each has 3 elements that represent a position on a line. A "X" is represented by the number 1, a "O" by -1 and an empty space by 0. I am trying to create a function that receives an argument (in this case the board is the argument) and says if it represents a valid board or not, however it always gives me the wrong answer (in this case says it's false) and I don't know why.

tab = ((1, -1, 0), (0, 0, 1), (0, -1, 1))

def eh_tabuleiro(tab):
    if len(tab) == 3:
        if len(tab[0]) == 3 and len(tab[1]) == 3 and len(tab[2]) == 3:
            if tab[0][0] or tab[0][1] or tab[0][2] or tab[1][0] or tab[1][1] or tab[1][2] or tab[2][0] or tab[2][1] or tab[2][2] != 1 or -1 or 0:
                return False
            else:
                return True           
            
        else:
            return False
    else:
        return False  

For a board to be valid it needs to be a tuple with three tuples and 3 elements inside each smaller tuple. If it has 2 elements or instead of 1/-1/0 has a "-1" or any other thing the function returns False. As you can see my board is correct and it says it is not. Can anyone help me?

2
  • You're almost there. The or expression is wrong. Do 2 for loops, one for the rows, other nested for the columns, and check if the current position is different from 1, -1 or 0. Commented Nov 18, 2020 at 15:15
  • That big if doesn't evaluate as you want it to. A more Pythonic way to express that condition is: if not all(tab[i][j] in (1, -1, 0) for i in range(3) for j in range(3)) Commented Nov 18, 2020 at 15:31

2 Answers 2

1

The problem is with the long chain of or statements. Compare the following:

if 1 or 2 == 3:  # Python reads this as `if 1 or (2 == 3):`
    print('oops')

# prints 'oops'
if (1 == 3) or (2 == 3):
    print('oops')

# does not print

Suggestion for a more readable implementation:

def is_valid(tab):
    if not isinstance(tab, tuple):
        return False

    if len(tab) != 3:
        return False

    for row in tab:
        if not isinstance(row, tuple):
            return False

        if len(row) != 3:
            return False
        
        for element in row:
             if element not in (-1, 0, 1):
                 return False

    return True
Sign up to request clarification or add additional context in comments.

Comments

1

Do not try to invent a new syntax. It does not matter that you (or I) can guess what is expected, what matter is what Python understand.

This line:

if tab[0][0] or tab[0][1] or tab[0][2] or tab[1][0] or tab[1][1] or tab[1][2] or tab[2][0] or tab[2][1] or tab[2][2] != 1 or -1 or 0:

will return True as soon as one of the elements between or is True, and the integer values 1 or -1 give True in a boolean context.

What you want is to know whether the set produced by all values is a subset of (0, 1, -1). Just test that instead:

...
if (set(tab[0]) | set(tab[1]) | set(tab[2])).issubset({1, 0, -1}):
    return True
else:
    return False

3 Comments

issubset({1, 2, 3}) ?
@Niloct: Oops I should have had a coffee before writing that! Thank you for your comment...
No problem. By the way, your answer would analyse the whole board right ? The accepted answer would stop in the first cell with problems.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.