在某些情况下,在两个不同的事件中更改一个字典会导致 KeyError(因为键事件的时间 + 由于 dt 引起的事件)

Changing one dictionary at two different events leads to KeyError in some cases (because of timing of key event + event due to dt)

底部最后一个问题的副本: “我不知道如何解决这个错误。一个动作依赖于时间,另一个依赖于玩家输入。有人有想法吗?python 中有什么东西可以处理可变数据来处理一个对象获取的情况在不同的时间从不同的地方改变?

我在 Pygame 中编写了自己的俄罗斯方块。目前我的目标是从这里重建游戏模式“生存”:https://jstris.jezevec10.com/?play=4 玩家需要尽可能长时间地生存,而每 1 秒就会在底部添加一条只有 1 个空闲位置的新行,并将游戏区域移向顶部。

我的问题是,有一个 key.event 玩家丢下一个棋子并用该动作清除一行,另一方面有一个时间事件,每隔一秒随机添加一条线到场地。这两个事件都会更改字典中的值。总的来说,这段代码可以工作,但有非常小的 window 时间取决于代码抛出错误的操作。

我的游戏的简短说明: 有一个网格(列表列表 10x20),其中每个元素都是 RGB 颜色(0,0,0),每次都以黑色开始,并且将填充当前下落棋子的信息(颜色)或棋子所在的底部字段被锁定。网格将在每一帧绘制。已经放置的棋子存储在字典中。网格每次绘制前都会请求锁片的dict

在这张图片中,您看到的是原始游戏。那时 6 行已经添加到字段中。 每条线都将在字段底部生成,颜色为灰色,带有一个自由随机点。每次生成一行时,信息都会添加到我的“锁定”字典中( key = (x,y) : value = (153,153,153) )并且一个函数将每个键中的 y 值更改为 1 到顶部。 同时,如果玩家清除一行(在这张图片中,它将是从底部数起的第 6 行),则有一个函数可以删除“锁定”字典中清除的行并更改所有大于该值的 y 值从 1 行到底部。

下面是两个函数:

def clear_rows(grid, locked): # (0,0) is at the top left, x increases right, y increases down

    
    i = len(grid) - 1  # last row
    rows_cleared = 0
    while i > -1:
        row = grid[i]

        if BLACK not in row: #which means the row is full and can be cleared
            i_new = i + rows_cleared
            for j in range(len(row)):
                del locked[(j, i_new)]
            rows_cleared += 1

            for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
                x_coord, y_coord = key
                if y_coord < i_new:
                    new_key = (x_coord, y_coord + 1)
                    locked[new_key] = locked.pop(key)
            i -= 1
        else:
            i -= 1

    return rows_cleared

def survival_add_line(locked):
    for key in sorted(list(locked)):
        x, y = key
        new_key = (x, y - 1)
        locked[new_key] = locked.pop(key)

    gap = random.randint(0,9)
    for i in range(10):
        if not i == gap:
            locked[(i, 19)] = SURVIVAL_GRAY

这是我的主循环中的代码:

if level_time / 1000 >= 1:
            survival_add_line(locked)
            level_time = 0
if change_piece:
    for pos in tetrimino_position:
        locked[(pos[0], pos[1])] = current_piece.color      
    current_piece = next_pieces[0]
    next_pieces.pop(0)
    next_pieces.append(new_tetromino())
    change_piece = False
    cleared_lines += clear_rows(grid, locked)

我注意到这个错误只会发生在字段的最底部。如果我理解正确的话,当玩家在 survival_add_line() 已经被调用但在 change_piece 之前的那个确切时刻掉下一块时,就会发生这种情况。 Survival_add_line() 将每一行移动到顶部,然后 clear_row 函数想要删除最后一行(现在是倒数第二行)并且它找不到最后一行中的键删除 --> KeyError.

我不知道如何解决这个错误。一个动作取决于时间,另一个取决于玩家输入。 有人有想法吗? python 中是否有一些处理可变数据的东西可以处理一个对象在不同时间从不同地方发生变化的情况?

不用用 if 调用这两个语句,if/elif 块就可以完成工作! (change_piece 现在可以延迟 1 帧,但这对玩家来说并不明显)

代表提问者发表