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', '-']