落下ブロックと複雑な形状


10

私は現在、テトリスのような単純なゲームを持っていて、解決できない問題に遭遇しました。

テトリスとは異なりがある場合、単一の落下形状は、I落下する必要のある複数の、潜在的に連動形状を有しています。最終的な位置を計算する必要があります。以下を検討してください。

落下ブロック問題の例

  1. 緑の形状の最終的な位置を計算するには、別の正方形またはボードの端に当たるまで、すべての正方形をスキャンします。できた

  2. 複数の単純な形状の場合は、ボードを上に向かって作業します。したがって、赤は移動する必要がないことがわかり、オレンジは1つ下がり、緑は3つ下がります。できた

  3. 連動する緑と赤の形の扱い方がわかりません。#2のロジックを使用すると、空中で「スタック」してしまいます。緑の形状を下にスキャンすると、赤に遭遇して移動しません。赤の場合も同様です。解決策は、2つの形状を1つとして扱うことです。

  4. #3と同様に、このシナリオでは、オブジェクトを1つとして扱うことで成功させることもできます。

  5. #3や#4とは異なり、オレンジのシェイプは1スクエアの高さに浮き上がるため、シェイプを1つとして扱うことができませんでした...

  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年

共有していただきありがとうございます。素晴らしいソリューション。アニメーションが大好きです:)
ashes999

乾杯ashes999、私はストップロジックが下の行から「流れ」、ステージ全体に増殖する方法を示す矢印の付いた新しいアニメーションが必要だと思います...
oodavid

回答:


4

まあ、動いている図形と静止している図形に違いがある場合は、図形を1つの図形として扱う必要はありません。形状(A)はその直下の形状(B)を検出でき、移動している場合、B形状はその直下に何かがあるかどうかを確認でき、静止している形状がある場合は、AとBが静止している何もない場合、両方とも下に移動しますが、移動する形状がある場合、この新しい形状はAとB​​によってA処理済みBとして扱われるため、一種の再帰的です。各ステップで、最も低い形状は最初にその下の形状を確認する必要があることに注意してください。

したがって、問題#6の場合、緑色の形状は最も移動する形状であり、その真下にある唯一の形状は赤い形状であることがわかります。そのため、赤い形状はその直下で何も検出せず、下に移動します。 。緑の図形がオレンジの図形に隣接すると、静止し、赤の図形が下に移動して、静止している緑の図形を検出し、静止します。


そうでないことが証明されるまで、すべての形状が静止していないと想定する必要があると私は考えていますか?
oodavid 2013年

私はこれについて熟考しましたが、とても良いテクニックのように聞こえます。私はそれを明日/週末に試してみて、それがどのように機能するかを確認します。
oodavid 2013年

3

ケース#5と#6の問題は単一のルートに起因するようです。移動チェックの1つのパスのみを実行しています。何も移動していないことがわかるまで、物を下に移動し続けます(これを「重力パス」と呼びます)。

たとえば、ケース6では、複数のパスを使用した場合、次のようになります。

  • オレンジが下に移動
  • グリーンが下に移動
  • オレンジが下に移動
  • グリーンが下に移動
  • オレンジが下に移動
  • 何も下に移動しない(完了!)

複数の重力パスのこの戦略は、#5も解決する可能性がありますが、それらを1つのピースとして扱う必要があると思われるケース#3と#4には役立ちません。

2つ以上のピースを1つのピースとして扱う必要がある場合を区別するには、最も簡単なアルゴリズムは、すべてのピースの結合空間に「穴」があるかどうかを確認することです。ある場合は複数ピースとして扱うことができます。


1
#3と#4では、2つまたは3つの形状がより大きな「C」形状で完全に囲まれているというバリエーションもある可能性があります。私はそれをやってみて、それから何が起こるか見てみましょう!乾杯@ ashes999
oodavid

@oodavidあなたの要件/デザインは私にとって不必要に複雑に見えます。これらの問題を解決しながら、より単純なものから始めて、上に向かって作業を進めます。
ashes999 2013年

ちなみに、上記の問題は、はるかに複雑な問題を説明するための完全に簡略化/抽象化された方法です。私は追跡のスリルのためにこれをやっています!
oodavid 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.