I am working on a tic-tac-toe game, everything is going smoothly but I was wondering if there was a better way to carry out the following code:
def straight_check(play_board, item):
inc_up = 1
inc_down = 1
for num in range(3):
for second in range(3):
if play_board[second][num] == 'x':
if inc_up == 3:
return True
inc_up += 1
else:
continue
if play_board[num][second] == 'x':
if inc_down == 3:
return True
inc_down += 1
else:
continue
return False
This function takes in the board for the game (a 3x3 nested list) along with the users char (x or o). This function checks if the users char occurs 3 times in a row on the board (horizontally or vertically). Is there another way I could do this without using a nested for loop along with variables? Also, is this kind of programming along with the size of the programming good practice?
Actually, there are some issues. You should reset the counters inside the outer loop (or you'll keep incrementing counts from previous failed chcks) and also remove the else: continue
parts or you will skip column checks if there is no item
in the corresponding row:
def straight_check(play_board, item):
for x in range(3):
# reset the counters in inner loop
cnt_hori, cnt_vert = 0, 0
for y in range(3):
if play_board[x][y] == item:
cnt_hori += 1
if cnt_hori == 3:
return True
if play_board[y][x] == item:
cnt_vert += 1
if cnt_vert == 3:
return True
return False
Nothing inherently wrong with the nested loops in general (since you know in advance that this is only a 3x3 matrix). Note, however, that there are the built-in functions any
and all
as well as the zip(*...)
transpositioning pattern that you can use to some effect in order to shorten your code and (maybe) make it more readable:
def straight_check(play_board, item):
if any(all(x == item for x in row) for row in play_board):
return True
if any(all(x == item for x in col) for col in zip(*play_board)):
return True
return False
You can think of this in terms of natural language: Does it hold for "any" row that "all" items in it are 'x', etc.?