在列表列表中移动形状

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(主要是 0s 的数组),使用 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 映射到相对于当前角索引的移动的逻辑。