patternpythonMinor
Repetitive For Loops in 2048 Game
Viewed 0 times
loopsrepetitivegamefor2048
Problem
I have the following function defined in a program that implements the 2048 game. I tried condensing the repeating part of the code into one loop containing +1 offset variables for the indices, which are either set to 0 or 1 depending on the direction passed into the function, but the outer and inner loop variables swap depending on the direction. Could anyone give me some pointers as to how to condense this code and make it more clean, pythonic and terse?
def merge(direction):
#if adjacent cells are equal, they are merged into one with twice the value and then moved.
if direction == "up":
for col in range(nColumns):
for row in range(nRows-1):
if grid[row][col] == grid[row+1][col]:
grid[row][col] = grid[row+1][col]*2
grid[row+1][col] = 0
move(direction)
if direction == "down":
for col in range(nColumns):
for row in range(nRows-1):
if grid[row][col] == grid[row+1][col]:
grid[row+1][col] = grid[row][col]*2
grid[row][col] = 0
move(direction)
if direction == "left":
for row in range(nRows):
for col in range(nColumns-1):
if grid[row][col] == grid[row][col+1]:
grid[row][col] = grid[row][col]*2
grid[row][col+1] = 0
move(direction)
if direction == "right":
for row in range(nRows):
for col in range(nColumns-1):
if grid[row][col] == grid[row][col+1]:
grid[row][col+1] = grid[row][col]*2
grid[row][col] = 0
move(direction)Solution
Iterating more smartly can simplify your loops.
To start with, run this standalone example and see that the
Then, you can reuse the loop just by changing which ranges you pass in.
To start with, run this standalone example and see that the
izip(…) expression produces useful pairs of coordinates:from itertools import product, izip
nRows, nColumns = 3, 5
for dest, src in izip(product(range(nRows - 1), range(nColumns)),
product(range(1, nRows), range(nColumns))):
print(dest, src)Then, you can reuse the loop just by changing which ranges you pass in.
from itertools import product, izip
def merge(direction):
def merge(dest_iterator, src_iterator):
for (dr, dc), (sr, sc) in izip(dest_iterator, src_iterator):
if grid[dr][dc] == grid[sr][sc]:
grid[dr][dc] == 2 * grid[sr][sc]
grid[sr][sc] = 0
move(direction)
if direction == "up":
merge(product(range(nRows - 1), range(nColumns)),
product(range(1, nRows), range(nColumns)))
elif direction == "down":
merge(product(range(1, nRows), range(nColumns)),
product(range(nRows - 1), range(nColumns)))
elif direction == "left":
merge(product(range(nRows), range(nColumns - 1)),
product(range(nRows), range(1, nColumns)))
elif direction == "down":
merge(product(range(nRows), range(1, nColumns)),
product(range(nRows), range(nColumns - 1)))Code Snippets
from itertools import product, izip
nRows, nColumns = 3, 5
for dest, src in izip(product(range(nRows - 1), range(nColumns)),
product(range(1, nRows), range(nColumns))):
print(dest, src)from itertools import product, izip
def merge(direction):
def merge(dest_iterator, src_iterator):
for (dr, dc), (sr, sc) in izip(dest_iterator, src_iterator):
if grid[dr][dc] == grid[sr][sc]:
grid[dr][dc] == 2 * grid[sr][sc]
grid[sr][sc] = 0
move(direction)
if direction == "up":
merge(product(range(nRows - 1), range(nColumns)),
product(range(1, nRows), range(nColumns)))
elif direction == "down":
merge(product(range(1, nRows), range(nColumns)),
product(range(nRows - 1), range(nColumns)))
elif direction == "left":
merge(product(range(nRows), range(nColumns - 1)),
product(range(nRows), range(1, nColumns)))
elif direction == "down":
merge(product(range(nRows), range(1, nColumns)),
product(range(nRows), range(nColumns - 1)))Context
StackExchange Code Review Q#45613, answer score: 6
Revisions (0)
No revisions yet.