patternpythonMinor
Check "five in a row" for a 15x15 chess board
Viewed 0 times
five15x15chessforcheckrowboard
Problem
Problem:
For a given board, judge who had complete a continuously line (could
be horizontal, vertical or diagonal) of 5 pieces. Input is a 15×15
chess board, could be white (1), black (2) or empty (0). Return if
white win, if black win, if both win or if none of them win.
My specific questions are:
```
import random
def check_five(matrix):
white_win = False
black_win = False
for i in range(0, len(matrix)):
num_white_so_far = 0
num_black_so_far = 0
for j in range(0, len(matrix[0])):
if matrix[i][j] == 1: # 1 for white
num_white_so_far += 1
num_black_so_far = 0
if num_white_so_far == 5:
white_win = True
elif matrix[i][j] == 2: # 2 for black
num_black_so_far += 1
num_white_so_far = 0
if num_black_so_far == 5:
black_win = True
else:
num_black_so_far = 0
num_white_so_far = 0
for j in range(0, len(matrix[0])):
num_white_so_far = 0
num_black_so_far = 0
for i in range(0, len(matrix)):
if matrix[i][j] == 1: # 1 for white
num_white_so_far += 1
num_black_so_far = 0
if num_white_so_far == 5:
white_win = True
elif matrix[i][j] == 2: # 2 for black
num_black_so_far += 1
num_white_so_far = 0
if num_black_so_far == 5:
black_win = True
else:
num_black_so_far = 0
num_white_so_far = 0
for i i
For a given board, judge who had complete a continuously line (could
be horizontal, vertical or diagonal) of 5 pieces. Input is a 15×15
chess board, could be white (1), black (2) or empty (0). Return if
white win, if black win, if both win or if none of them win.
My specific questions are:
- I enumerate each direction one by one, and the code looks very long. Are there any elegant ways to handle directions (I mean direction of horizontal, vertical or diagonal)?
- I incrementally count # of black, # of white, to reduce redundant counting. I'm wondering if there are any better ideas to reduce counting.
```
import random
def check_five(matrix):
white_win = False
black_win = False
for i in range(0, len(matrix)):
num_white_so_far = 0
num_black_so_far = 0
for j in range(0, len(matrix[0])):
if matrix[i][j] == 1: # 1 for white
num_white_so_far += 1
num_black_so_far = 0
if num_white_so_far == 5:
white_win = True
elif matrix[i][j] == 2: # 2 for black
num_black_so_far += 1
num_white_so_far = 0
if num_black_so_far == 5:
black_win = True
else:
num_black_so_far = 0
num_white_so_far = 0
for j in range(0, len(matrix[0])):
num_white_so_far = 0
num_black_so_far = 0
for i in range(0, len(matrix)):
if matrix[i][j] == 1: # 1 for white
num_white_so_far += 1
num_black_so_far = 0
if num_white_so_far == 5:
white_win = True
elif matrix[i][j] == 2: # 2 for black
num_black_so_far += 1
num_white_so_far = 0
if num_black_so_far == 5:
black_win = True
else:
num_black_so_far = 0
num_white_so_far = 0
for i i
Solution
A few suggestions:
This way you could do something like:
Of course you still need to add the code to put the diagonals in an array to check, but this is the general idea. Keep in mind that here I'm assuming a variable size matrix, but still square.
EDIT: As @Graipher noted, you need to use
- Can both players win? If not, how do you decide which one to check first? If they can, if both of them have already won in the first check, no need to go on, just return
True,True.
- You are using a lot of hard-coded values (
1,2,5) that are repeated through the code. I think it would be better to call them something likewhite_cell,black_cell,min_winning_cells.
- The values can be only
0,1and2, so random.choice could be better, also because...
- ... You could use
random.choice(['0', '1', '2']). Notice that these are strings, so it's sort of cheating maybe.
This way you could do something like:
white_winning_cells = '1' * 5
black_winning_cells = '2' * 5
def check_rows(rows):
white_win = False
black_win = False
for row in rows:
# Avoid overwriting
white_win |= white_winning_cells in ''.join(row)
black_win |= black_winning_cells in ''.join(row)
if (white_win and black_win):
return (white_win, black_win)
return (white_win, black_win)
def check_five(matrix):
row_length = 15
white_win = False
black_win = False
(white_win, black_win) = check_rows(matrix)
if (white_win and black_win):
return (white_win, black_win)
# We need to avoid overwriting also here
(white_win_temp, black_win_temp) = check_rows(zip(*matrix))
white_win |= white_win_temp
black_win |= black_win_temp
return (white_win, black_win)Of course you still need to add the code to put the diagonals in an array to check, but this is the general idea. Keep in mind that here I'm assuming a variable size matrix, but still square.
EDIT: As @Graipher noted, you need to use
|= so you don't overwrite values. This has to be done in both the function and the caller. Also, for diagonals you can use the same code you have now to generate the arrays and pass them to the check_rows. You can also consider generating everything at once (rows, columns, diagonals), put them all in the same variable and call check_rows only once. But as I said, this is just a general idea.Code Snippets
white_winning_cells = '1' * 5
black_winning_cells = '2' * 5
def check_rows(rows):
white_win = False
black_win = False
for row in rows:
# Avoid overwriting
white_win |= white_winning_cells in ''.join(row)
black_win |= black_winning_cells in ''.join(row)
if (white_win and black_win):
return (white_win, black_win)
return (white_win, black_win)
def check_five(matrix):
row_length = 15
white_win = False
black_win = False
(white_win, black_win) = check_rows(matrix)
if (white_win and black_win):
return (white_win, black_win)
# We need to avoid overwriting also here
(white_win_temp, black_win_temp) = check_rows(zip(*matrix))
white_win |= white_win_temp
black_win |= black_win_temp
return (white_win, black_win)Context
StackExchange Code Review Q#153460, answer score: 4
Revisions (0)
No revisions yet.