How do we make a function that allows us to check if the list of string are consecutive?

Viewed 32

Given a board of n x n size that is greater than 4 and no larger than 100. How can we check if a list[str] has connecting elements from left to right, up to down, and diagonally (top left to bottom right / top right to bottom left)?

for example if we have a list:

Matrix = [ 'XXXOO',
           'X.OXX',
           'XOXOO',
           'O.XOO',
           'XXXOO']

we should be able to see that player O has a matching four

this is the code that I have at the moment:

Matrix = [ 
        'XXXOO',
        'X.OXX',
        'XOXOO',
        'O.XOO',
        'XXXOO']

def WhoWon(Matrix:list[str]) -> str:
    rows = len(Matrix)
    columns = len(Matrix[0])

    if 4 <= len(Matrix) <= 100:
        for Row in range(rows-3):
            for Col in range(columns-3):
                if Matrix[Row][Col] == Matrix[Row][Col + 1] == Matrix[Row][Col + 2] == Matrix[Row][Col + 3]: # left and right
                    return Matrix[Row][Col]
                elif Matrix[Row][Col] == Matrix[Row + 1][Col] == Matrix[Row + 2][Col] == Matrix[Row + 3][Col]: # up and down
                    return Matrix[Row][Col]
                elif Matrix[Row][Col] == Matrix[Row + 1][Col - 1] == Matrix[Row + 2][Col - 2] == Matrix[Row + 3][Col - 3]:
                    return Matrix[Row][Col]
                elif Matrix[Row][Col] == Matrix[Row + 1][Col + 1] == Matrix[Row + 2][Col + 2] == Matrix[Row + 3][Col + 3]:
                    return Matrix[Row][Col]

print(WhoWon(Matrix))```
1 Answers

You can just think of it as a regular Matrix system, so basically for every cell you want to know if it's a part of a row along a vector, so in order for a row to exist, there must exist a cell denoted with indices (i,j) such that either cells (i±k,j), cells (i±k,j±k) or cells (i,j±k) are the same symbol as the cell itself, when k runs from 0 to S-1, if S denotes how many symbols in a row are needed to win.

This is relatively easy to check using indices in this mathematical way:


player1symbol = 'O'
player2symbol = '.'
neutralsymbol = 'X'
Matrix = [ 
        'XXXOO',
        'X.OXX',
        'XOXOO',
        'O.XOO',
        'XXXOO']

def CheckWinner(Matrix, symbol):
    winner = False
    # How many in row to win
    towin = 4
    
    def isSymbol(elem):
        return elem == symbol
    
    def CheckRows(i,j):
        rowE = rowSE = rowS = rowSW = True
        for k in range(1,towin):
            if rowE and j+k<len(Matrix[i]):
                rowE = isSymbol(Matrix[i][j+k])
            if rowSE and j+k<len(Matrix[i]) and i+k<len(Matrix):
                rowSE = isSymbol(Matrix[i+k][j+k])
            if rowS and i+k<len(Matrix):
                rowS = isSymbol(Matrix[i+k][j])
            if rowSW and j-k>=0 and i+k<len(Matrix):
                rowSW = isSymbol(Matrix[i+k][j-k])
        
        if rowE or rowSE or rowS or rowSW:
            return True
        else:
            return False
    
    
    for i in range(len(Matrix)):
        for j in range(len(Matrix[i])):
            if isSymbol(Matrix[i][j]):
                isrow = CheckRows(i,j)
                if isrow:
                    return isrow
    
    return False

print("Player1 has winning row: "+repr(CheckWinner(Matrix,player1symbol)))
print("Player2 has winning row: "+repr(CheckWinner(Matrix,player2symbol)))
print("Neutral has winning row: "+repr(CheckWinner(Matrix,neutralsymbol)))

Note that in order to save a bit of time we only check whether each cell starts a winning row, since when going left to right, up to down we will be guaranteed to hit the starting cell of a row first. Also we only check 4 of the 8 possible cardinal directions, since the other 4 aren't needed (already covered by the 4 we check).

I'm sure you could clean up the code more, but this one is just a proof-of-concept.

Related