下降块和复杂形状


10

我目前有一个简单的类似Tetris的游戏,遇到了我无法解决的问题。

与俄罗斯方块中有一个单独的下降形状不同,我有多个可能需要互锁的形状需要下降;我需要计算他们的最终职位。考虑以下:

掉块问题的例子

  1. 要计算绿色形状的最终位置,我只需向下扫描每个正方形,直到碰到另一个正方形或板的边缘。完成

  2. 对于多种简单形状,我会按照自己的方式进行开发。因此,发现红色不需要移动,橙色下降1,绿色下降3。完成

  3. 我不知道如何对待互锁的绿色和红色形状。使用#2的逻辑,我们最终会“卡住”漂浮在空中。如果我向下扫描以获取绿色形状,则会遇到红色,因此不会移动,反之亦然。解决方案可能是将两种形状视为一种。

  4. 与#3类似,在这种情况下,我也可以通过将对象视为一个对象而成功。

  5. 与#3和#4不同,我无法将形状视为一个形状,因为橙色形状最终会浮动一个正方形太高...

  6. 问题6的另一种变化。

可能还有其他情况,使我有许多形状在越来越复杂的情况下交织在一起,但是我认为以上内容涵盖了问题的最基本部分。

我觉得我还没有遇到/想过一个优雅的解决方案,并且非常感谢您提供任何见解,想法或资源。

根据下面的@ user35958的答案,我想出的解决方案确实很优雅,我创建了以下递归函数(伪代码)

function stop(square1, square2){
    // Skip if we're already stopped
    if(square1.stopped){
        return;
    }
    // Are we comparing squares?
    if(!square2){
        // We are NOT comparing squares, simply stop.
        square1.stopped = true;
    } else {
        // Stop IF
        // square1 is directly above square2
        // square1 is connected to square2 (part of the same complex shape)
        if(square1.x == square2.x && square1.y == (square2.y+1) || isConnected(square1, square2)){
            square1.stopped = true;
        }
    }
    // If we're now stopped, we must recurse to our neighbours
    stop(square1, squareAbove);
    stop(square1, squareBelow);
    stop(square1, squareRight);
    stop(square1, squareDown);
}

动画GIF,显示解决方案的每一次通过

总结一下:

  • 当“停止”一个正方形时,我们也会停止:
    • 它上方的任何正方形。总是。
    • 我们连接到的相邻正方形(即相同的形状)。
  • 我们停止整个底部行,然后该函数通过正方形重复出现。
  • 我们重复直到所有正方形都停止。
  • 然后我们制作动画。

动画GIF,显示逻辑序列的每个遍历


我想如果您解决5,那么6也将解决。实际上,我相信解决5可能会解决所有这些情况。
UnderscoreZero 2013年

+1感谢您的分享。惊人的解决方案。喜欢动画:)
ashes999

干杯ashes999,我想我需要一个带有箭头的新动画,该动画显示停止逻辑如何从最下面一行“向上”流动并扩散到整个阶段……
oodavid

Answers:


4

好吧,如果正在移动的形状和静止的形状之间存在区别,则不需要完全将形​​状视为一个。形状(A)可以检测到其正下方的形状(B),如果它正在移动,则B形状可以查看其正下方是否有任何东西,如果有静止形状,则A和B现在处于静止状态,并且如果什么也没有,它们都会向下移动,但是如果有一个移动的形状,那么这个新形状将被A和B视为A处理过的B,因此它是递归的。请记住,对于每个步骤,最低的形状都需要首先检查其下方的形状。

因此,对于问题6,绿色形状是移动最低的形状,它会看到唯一在其正下方的形状是红色形状,因此红色形状将在其正下方检测不到任何东西,并且它们会向下移动。一旦绿色形状与橙色形状相邻,它将静止,红色形状将向下移动,然后检测静止的绿色形状,它也将静止。


我是否认为我们必须假设所有形状都处于静止状态才能证明?
oodavid 2013年

我刚刚花了一些时间思考这个问题,我必须说这听起来像是一种非常好的技术。我明天/周末尝试一下,看看效果如何。
oodavid

3

案例5和案例6的问题似乎源于一个根源:您只执行了一次移动检查。您应该继续向下移动东西(我们称其为“重力通行证”),直到您什么也没有移动。

例如,在情况6中,如果使用多次通过,则会发生以下情况:

  • 橙色下移
  • 绿色下移
  • 橙色下移
  • 绿色下移
  • 橙色下移
  • 什么都没下来(完成!)

这种多重重力通过的策略也可以解决5号问题,尽管对于3号和4号案例似乎无济于事,这似乎无济于事。

为了区分何时应将两个以上的零件视为一个零件,我认为最简单的算法是检查所有零件的组合空间中是否有“孔”。如果有,可以将其视为多件。


1
对于#3和#4,也可能会有变化,例如2个或3个形状被较大的“ C”形完全包围,弄清楚是否凝结了碎片可能会引发其他问题。我会去看看它会带来什么!干杯@ ashes999
oodavid

@oodavid对我来说您的要求/设计似乎不必要地复杂。从简单的事情开始,逐步解决这些问题。
ashes999

不,上述问题是一种完全简化/抽象的方式,用于描述一个更为复杂的问题。我这样做是为了追逐刺激!
oodavid 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.