Search code examples
pythonpython-2.7tic-tac-toe

Is using nested for loops good practice?


I am working on a tic-tac-toe game, everything is going smoothly but I was wondering if there was a better way to carry out the following code:

def straight_check(play_board, item):
    inc_up = 1
    inc_down = 1
    for num in range(3):
        for second in range(3):
            if play_board[second][num] == 'x':
                if inc_up == 3:
                    return True
                inc_up += 1
            else:
                continue
            if play_board[num][second] == 'x':
                if inc_down == 3:
                    return True
                inc_down += 1
            else:
                continue

    return False

This function takes in the board for the game (a 3x3 nested list) along with the users char (x or o). This function checks if the users char occurs 3 times in a row on the board (horizontally or vertically). Is there another way I could do this without using a nested for loop along with variables? Also, is this kind of programming along with the size of the programming good practice?


Solution

  • Actually, there are some issues. You should reset the counters inside the outer loop (or you'll keep incrementing counts from previous failed chcks) and also remove the else: continue parts or you will skip column checks if there is no item in the corresponding row:

    def straight_check(play_board, item):
        for x in range(3):
            # reset the counters in inner loop
            cnt_hori, cnt_vert = 0, 0  
            for y in range(3):
                if play_board[x][y] == item:
                    cnt_hori += 1
                    if cnt_hori == 3:
                        return True
                if play_board[y][x] == item:
                    cnt_vert += 1
                    if cnt_vert == 3:
                        return True
        return False
    

    Nothing inherently wrong with the nested loops in general (since you know in advance that this is only a 3x3 matrix). Note, however, that there are the built-in functions any and all as well as the zip(*...) transpositioning pattern that you can use to some effect in order to shorten your code and (maybe) make it more readable:

    def straight_check(play_board, item):
        if any(all(x == item for x in row) for row in play_board):
            return True
        if any(all(x == item for x in col) for col in zip(*play_board)):
            return True
        return False
    

    You can think of this in terms of natural language: Does it hold for "any" row that "all" items in it are 'x', etc.?