I’m in the making of a 4-in-a-Row game with a grid system. Was thinking of shortening it down with a for loop, but it ended up making the player randomly win. Any tips is appreciated.
if grid[4][row] == '.':
grid[4][row] = 'X'
else:
if grid[3][row] == '.':
grid[3][row] = 'X'
else:
if grid[2][row] == '.':
grid[2][row] = 'X'
else:
if grid[1][row] == '.':
grid[1][row] = 'X'
else:
if grid[0][row] == '.':
grid[0][row] = 'X'
>Solution :
Right off the bat, you can use elif:
if grid[4][row] == '.':
grid[4][row] = 'X'
elif grid[3][row] == '.':
grid[3][row] = 'X'
elif grid[2][row] == '.':
grid[2][row] = 'X'
elif grid[1][row] == '.':
grid[1][row] = 'X'
elif grid[0][row] == '.':
grid[0][row] = 'X'
You can then replace this with a simple loop which will exit early if it finds a .:
for n in range(4, -1, -1):
if grid[n][row] == '.':
grid[n][row] = 'X'
break
If grid is a list, you can use a reversed slice instead of iterating over specific indices.
for c in grid[4::-1]:
if c[row] == '.':
c[row] = 'X'
break
If you want to get fancier, use any with an assignment expression:
if any((c:=grid[n])[row] == '.' for n in range(4, -1, -1)):
c[row] = 'X'
# Or for a list,
# if any((c:=x)[row] == '.' for x in grid[4::-1]):
# c[row] = 'X'
As soon as any sees a value of n (or x) that makes the expression true, it returns True, and the name c remains bound to the element of grid that made the expression true.