简体   繁体   中英

Nested loops in nested lists

I am trying to build a simple Tic-Tac-Toe game in python, to check for a win I am using a nested loop to search for a match in a nested lists. For some reason my code will only search the first nested list and not the rest of them as I expected it to.

board = [ 'O', 'X', ' ', 'O', ' ', 'X', 'O', 'X', 'X' ]
wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]

def checkWin(player):
    win = False
    for test in wins:
        print (test)
        count = 0
        for squares in test:
            if board[squares] == player:
                count = count + 1
            if count == 3:
                win = True
        return win

if __name__ == '__main__':
    print ("\nChecking board for X win ...\n")
    if checkWin("X"): 
        print ("Game over, X wins!")

    print ("\nChecking board for O win ...\n")
    if checkWin("O"):
        print ("Game over, O wins")

Based on the board provided a win for O is expected instead, this is the output I get:

Checking board for X win ...

[0, 1, 2]

Checking board for O win ...

[0, 1, 2]

Does anyone know why this happens?

You return from the first nested list test, regardless of wether those three squares matched. Instead, only return if win is true:

def checkWin(player):
    win = False
    for test in wins:
        count = 0
        for squares in test:
            if board[squares] == player:
                count = count + 1
            if count == 3:
                win = True
        if win:
            return True
    return False

If win is false, the above continues to the next nested list for the next test.

Better still, just return when count is set to 3 , since you know you have found a match at that stage:

def checkWin(player):
    for test in wins:
        count = 0
        for squares in test:
            if board[squares] == player:
                count = count + 1
            if count == 3:
                return True
    return False

Instead of counting, you could use the all() function :

def checkWin(player):
    for test in wins:
        if all(board[square] == player for square in test):
            return True
    return False

all() returns False early, as soon as one of the tests in the generator expression fails.

And the ultimate version adds any() to complete the test in one line:

def checkWin(player):
    return any(all(board[square] == player for square in test)
               for test in wins)

Demo:

>>> board = [ 'O', 'X', ' ', 'O', ' ', 'X', 'O', 'X', 'X' ]
>>> wins = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]]
>>> def checkWin(player):
...     return any(all(board[square] == player for square in test)
...                for test in wins)
... 
>>> checkWin('X')
False
>>> checkWin('O')
True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM