在列表列表中移动形状
Move a shape inside a list of lists
我有以下表示矩阵的列表列表:
space = [
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
]
数字 1s 代表倒置的 L(如伽玛,“Γ”)。我怎样才能让这个“物体”像块一样左右移动?我用“asdw”键移动它。
重要提示:我无法使用numpy
,这让工作变得更加困难。
这是我进行正确方向运动的失败方法(顺便说一句,它不能正确地进行运动),但我认为这不是最好的方法,也不认为我可以将其升级为其他运动:
def show_space(space):
for line in space:
print(line)
x = input("Movement: ")
if x == 'd':
for i in range(4):
for j in range(4):
if space[i][j] == 1:
try:
if space[i][j+1] == 0:
space[i][j] = 0
space[i][j+1] = 1
if space[i][j+1] == 1 and space[i][j+2] == 0:
space[i][j] = 0
space[i][j+2] = 1
except IndexError:
pass
show_space(space)
还有其他方法可以尝试吗?或者更正我正在使用的那个?提前致谢
编辑:
伽玛不仅应该能够从右上左下移动,还应该能够移动 90 度,镜像自身,以及形式可以采用的所有可能形状。所以如果我必须硬编码所有可能的 gamma 或 L 组合,我将不得不硬编码 48 种可能性。我不知道硬编码是否是诚实的最佳方式。
我并不是说对位置进行硬编码是不可接受的,这绝对是一个解决方案,但我只是觉得这不是正确的方法。当然我可能是错的。
你怎么看?
如果您需要留在标准库的范围内,您可以使用 collection.deque
, which has a rotate
方法,它可以完全满足您的需要,如果您不能使用双端队列,则必须在列表中实现。
这就是我可以用双端队列提供的。
注意。这环绕着可能不是预期的边缘,
from collections import deque
space = deque([
deque([0, 1, 1, 0]),
deque([0, 0, 1, 0]),
deque([0, 0, 1, 0]),
deque([0, 0, 0, 0]),
])
def move(mvt):
if mvt == "s":
space.rotate(1)
elif mvt == "w":
space.rotate(-1)
elif mvt == "d":
[x.rotate(1) for x in space]
elif mvt == "a":
[x.rotate(-1) for x in space]
else:
raise NotImplementedError
move("d") # etc
你的答案在你的问题中 - 而不是跟踪所有 space(主要是 0
s 的数组),使用 object
(python dict
) 来指定形状,以及从哪里开始绘制它,例如:
{
'abs_pos': (0,1),
'rel_points': [(0,0), (0,1), (1,0), (2,0)]
}
然后移动它仅相当于更新 upper-left 角 abs_pos
.
的位置(例如)
当需要打印所有 space 的地图时,从 abs_pos
开始,然后在 rel_points
中的每个点添加一个点。
以下是我建议的做法:
计算矩阵中每个gamma shape的所有索引,保存在字典中,以每个角索引元组作为字典键,然后每当角移动时,找出应该为1的索引,并赋值到零矩阵的副本。
positions = {(0, 0): ((0, 1), (1, 0), (2, 0)),
(0, 1): ((0, 2), (1, 1), (2, 1)),
(0, 2): ((0, 3), (1, 2), (2, 2)),
(1, 0): ((1, 1), (2, 0), (3, 0)),
(1, 1): ((1, 2), (2, 1), (3, 1)),
(1, 2): ((1, 3), (2, 2), (3, 2))}
def move_gamma(corner):
board = [[0 for _ in range(4)] for _ in range(4)]
try:
for (i, j) in (corner, *positions[corner]):
board[i][j] = 1
return board
except KeyError:
print("You can't move there!")
return board
def flip_h(board):
return [[*reversed(row)] for row in board]
def flip_v(board):
return [*reversed(board)]
def transpose(board):
return [[*t] for t in zip(*board)]
演示:
In [3]: board = move_gamma((1, 1))
In [4]: print(*board, sep="\n")
[0, 0, 0, 0]
[0, 1, 1, 0]
[0, 1, 0, 0]
[0, 1, 0, 0]
In [5]: board = move_gamma((1, 2))
In [6]: print(*board, sep="\n")
[0, 0, 0, 0]
[0, 0, 1, 1]
[0, 0, 1, 0]
[0, 0, 1, 0]
In [7]: print(*transpose(board), sep="\n")
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 1, 1, 1]
[0, 1, 0, 0]
请注意,您仍然需要实现将 WASD 映射到相对于当前角索引的移动的逻辑。
我有以下表示矩阵的列表列表:
space = [
[0, 1, 1, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 0],
]
数字 1s 代表倒置的 L(如伽玛,“Γ”)。我怎样才能让这个“物体”像块一样左右移动?我用“asdw”键移动它。
重要提示:我无法使用numpy
,这让工作变得更加困难。
这是我进行正确方向运动的失败方法(顺便说一句,它不能正确地进行运动),但我认为这不是最好的方法,也不认为我可以将其升级为其他运动:
def show_space(space):
for line in space:
print(line)
x = input("Movement: ")
if x == 'd':
for i in range(4):
for j in range(4):
if space[i][j] == 1:
try:
if space[i][j+1] == 0:
space[i][j] = 0
space[i][j+1] = 1
if space[i][j+1] == 1 and space[i][j+2] == 0:
space[i][j] = 0
space[i][j+2] = 1
except IndexError:
pass
show_space(space)
还有其他方法可以尝试吗?或者更正我正在使用的那个?提前致谢
编辑:
伽玛不仅应该能够从右上左下移动,还应该能够移动 90 度,镜像自身,以及形式可以采用的所有可能形状。所以如果我必须硬编码所有可能的 gamma 或 L 组合,我将不得不硬编码 48 种可能性。我不知道硬编码是否是诚实的最佳方式。
我并不是说对位置进行硬编码是不可接受的,这绝对是一个解决方案,但我只是觉得这不是正确的方法。当然我可能是错的。
你怎么看?
如果您需要留在标准库的范围内,您可以使用 collection.deque
, which has a rotate
方法,它可以完全满足您的需要,如果您不能使用双端队列,则必须在列表中实现。
这就是我可以用双端队列提供的。
注意。这环绕着可能不是预期的边缘,
from collections import deque
space = deque([
deque([0, 1, 1, 0]),
deque([0, 0, 1, 0]),
deque([0, 0, 1, 0]),
deque([0, 0, 0, 0]),
])
def move(mvt):
if mvt == "s":
space.rotate(1)
elif mvt == "w":
space.rotate(-1)
elif mvt == "d":
[x.rotate(1) for x in space]
elif mvt == "a":
[x.rotate(-1) for x in space]
else:
raise NotImplementedError
move("d") # etc
你的答案在你的问题中 - 而不是跟踪所有 space(主要是 0
s 的数组),使用 object
(python dict
) 来指定形状,以及从哪里开始绘制它,例如:
{
'abs_pos': (0,1),
'rel_points': [(0,0), (0,1), (1,0), (2,0)]
}
然后移动它仅相当于更新 upper-left 角 abs_pos
.
当需要打印所有 space 的地图时,从 abs_pos
开始,然后在 rel_points
中的每个点添加一个点。
以下是我建议的做法:
计算矩阵中每个gamma shape的所有索引,保存在字典中,以每个角索引元组作为字典键,然后每当角移动时,找出应该为1的索引,并赋值到零矩阵的副本。
positions = {(0, 0): ((0, 1), (1, 0), (2, 0)),
(0, 1): ((0, 2), (1, 1), (2, 1)),
(0, 2): ((0, 3), (1, 2), (2, 2)),
(1, 0): ((1, 1), (2, 0), (3, 0)),
(1, 1): ((1, 2), (2, 1), (3, 1)),
(1, 2): ((1, 3), (2, 2), (3, 2))}
def move_gamma(corner):
board = [[0 for _ in range(4)] for _ in range(4)]
try:
for (i, j) in (corner, *positions[corner]):
board[i][j] = 1
return board
except KeyError:
print("You can't move there!")
return board
def flip_h(board):
return [[*reversed(row)] for row in board]
def flip_v(board):
return [*reversed(board)]
def transpose(board):
return [[*t] for t in zip(*board)]
演示:
In [3]: board = move_gamma((1, 1))
In [4]: print(*board, sep="\n")
[0, 0, 0, 0]
[0, 1, 1, 0]
[0, 1, 0, 0]
[0, 1, 0, 0]
In [5]: board = move_gamma((1, 2))
In [6]: print(*board, sep="\n")
[0, 0, 0, 0]
[0, 0, 1, 1]
[0, 0, 1, 0]
[0, 0, 1, 0]
In [7]: print(*transpose(board), sep="\n")
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 1, 1, 1]
[0, 1, 0, 0]
请注意,您仍然需要实现将 WASD 映射到相对于当前角索引的移动的逻辑。