Using 2 'For Loops' to identify a winning Line for Tic Tac Toe

Viewed 147

I am trying to use 2 'For Loops' to identify a win either vertically or horizontally in a game of tic tac toe. Currently, I'm using one loop that will iterate from 0 to 2, and almost hardcoding to check if its horizontal or vertical.

def check_win(game):
    if game[0][0] == game[1][1] == game[2][2] or\
       game[0][2] == game[1][1] == game[2][0]:
        winner = game[1][1]
        return str(winner)
    for x in range(3):
        if game[x][0] == game[x][1] == game[x][2]:
            return str(game[x][0])
        elif game[0][x] == game[1][x] == game[2][x]:
            return str(game[0][x])
        else:
            continue
    else:
        return ''

What I want to do is this:

def check_win(game):
    if game[0][0] == game[1][1] == game[2][2] or\
       game[0][2] == game[1][1] == game[2][0]:
        winner = game[1][1]
        return str(winner)
    for i in range(len(game)):
        for j in range(len(game[i])):
            if game[i][j] == game[i][j-1] == game[i][j+1]:
                return str(game[i][j])
            elif game[i][j] == game[i-1][j] == game[i+1][j]:
                return str(game[i][j])
            else:
                continue
    else:
        return ''

But I know that it will hit an index out of range error.

How can I overcome this?

3 Answers

This should help you:

def check_win(game):
    
    def check_match(gamee, flag):
        lstt = [f"{lst[0]} wins by {flag} match!" for lst in gamee if len(set(lst)) == 1]
        if len(lstt) > 0: return ''.join(lstt)

    if check_match(game,'horizontal'): return check_match(game,'horizontal')

    l = len(game[0])
    diagonals = [[game[i][i] for i in range(l)], [game[l - 1 - i][i] for i in range(l - 1, -1, -1)]]

    if check_match(diagonals,'diagonal'): return check_match(diagonals,'diagonal')
    
    game = [[game[j][i] for j in range(len(game))] for i in range(len(game[0]))]
    
    if check_match(game, 'vertical'): return check_match(game, 'vertical')

    return "No winner"

matrix = [[0, 1, 0],
          [0, 1, 1],
          [0, 0, 1]]

print(check_win(matrix))

Output:

0 wins by vertical match!

You have a list of list as input. You already have the diagonal check down. You can use all(condition elem in iterable) to check for horizontal in a row. If you transpose the list you can use the same check again to check for vertical - which will in total use 2 for loops (albeit not interleaved ones):

def check_win(field):
    # diagonal
    if field[0][0] == field[1][1] == field[2][2] or \
       field[0][2] == field[1][1] == field[2][0]:
        print("diagonal    ", end="")
        return field[1][1]
    # row
    for row in field:
        if all(e == row[0] for e in row):
            print("horizontal    ", end="")
            return row[0]
    # transpose so colums are now rows and rows are now columns
    # and check rows again
    f = list(zip(*field))
    for row in f: 
        if all(e == row[0] for e in row):
           print("vertical    ", end="")
           return row[0]

    return ''

print(check_win( [list("X12"), list("3X4"), list("56X")]))
print(check_win( [list("12X"), list("3X4"), list("X56")]))

print(check_win( [list("XXX"), list("123"), list("456")]))
print(check_win( [list("123"), list("XXX"), list("456")]))
print(check_win( [list("123"), list("345"), list("XXX")]))

print(check_win( [list("X12"), list("X34"), list("X56")]))
print(check_win( [list("1X2"), list("3X4"), list("5X6")]))
print(check_win( [list("12X"), list("34X"), list("56X")]))

print(check_win( [list("1X2"), list("34X"), list("56X")]))

Output:

diagonal    X
diagonal    X
horizontal    X
horizontal    X
horizontal    X
vertical    X
vertical    X
vertical    X
# (no output)

The simplest data structure is an one-dimensional array. If you store your board this way, the indexes that need to be the same to win are:

  • 0, 1, 2
  • 3, 4, 5
  • 6, 7, 8
  • 1, 4, 8
  • 2, 4, 6

Store these arrays in an array. To test for a win, iterate through this array and test that all elements of the board array are the same.

You could leave the board as a 2D array and use a similar approach with the winning index array storing x-y pairs instead of 1D indexes.

Related