简体   繁体   中英

How to check for win in custom sized tic-tac-toe diagonals

I'm making a simple tic tac toe game, where user can specify the size of the grid (amount of columns and rows).
I need to create a function, that could check for a win in all the diagonals in the grid.

For the grid, I'm using a 2-dimensional list, that looks like this (3x3 example):

grid = [['x', '-', 'o'], 
        ['o', 'x', '-'], 
        ['-', '-', 'x']]
grid[row][col]

This should be a winning situation

I have already created a check for the vertical and horizontal win, but I can't quite figure out, how to check for the diagonals.

Here is how I check for row win in my code:

min_win_streak is the minimum winning streak (for example in classical 3x3 tic-tac-toe, it would be 3)

def check_rows(grid, min_win_streak):
    winner = '-'
    for row in grid:
        win_streak = 0
        for element in row:
            if element != '-':
                if element == winner:
                    win_streak += 1
                    winner = element
                    if win_streak >= min_win_streak:
                        return True, winner
                else:
                    win_streak = 1
                    winner = element
            else:
                win_streak = 0
                winner = '-'
    return False, None



I need the check_diags() function, the returns should be:

  • win for x , the function should return True, 'x'
  • win for o , the function should return True, 'x'
  • no win , the function should return False, None

You can check for diagonals in a 2x2 using the following nested for loops:

for i in range(len(grid)-2):
    for j in range(len(grid)-2):
        if grid[i][j] == grid[i+1][j+1] == grid[i+2][j+2] and grid[i][j] != '-':
            print('Winner')
        elif grid[i][j+2] == grid[i+1][j+1] == grid[i+2][j] and grid[i][j+2] != '-':
            print('Winner')

Insert this into a function with the desired returns in place of the print statements if you desire. This should be extendable to 3x3, 4x4, etc. with fairly easy alterations.

Thanks for posting your code. I replaced your win_streak check loop with the all function. The code below does more work than you'd want to use for a huge grid, but it's easy (easier) to understand and adapt, and it's fast enough to use for a game of go-moku (5 in a row on a 19x19 board).

I left in one tracing print statement to illustrate the diagonals it's checking. You should be able to adapt this to the NE-SW diagonals ( check_slash_diag ).

grid = [['x', '-', 'o', 'o'],
        ['o', 'x', 'o', '-'],
        ['-', 'o', 'x', 'x'],
        ['-', 'x', 'o', '-']]

def check_backslash_diag(grid, min_win_streak):

    grid_size = len(grid)
    grid_extra = grid_size - min_win_streak   # This is the "extra" space in a long line

    # This pair of loops will iterate through the upper-left square of side 
    #   grid_extra+1, starting points of any diagonals long enough to contain a win.
    for start_row in range(grid_extra+1):
        for start_col in range(grid_extra+1):
            # Extract a diagonal "row" of length min_win_streak
            diag = [grid[start_row+i][start_col+i] for i in range(min_win_streak)]
            print(start_row, start_col, diag)  # DEBUG: Display checked diagonals
            if all(diag[i] == diag[0] for i in range(min_win_streak)):
                print(diag[0], "wins on NW-SE diagonal at", start_row, start_col)

check_backslash_diag(grid, 3)

Output:

0 0 ['x', 'x', 'x']
x wins on NW-SE diagonal at 0 0
0 1 ['-', 'o', 'x']
1 0 ['o', 'o', 'o']
o wins on NW-SE diagonal at 1 0
1 1 ['x', 'x', '-']

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