Падіння блоків і складних форм


10

В даний час я маю просту гру, схожу на тетріс, і зіткнувся з проблемою, яку я не можу вирішити.

На відміну від тетрісу, де є одна падаюча форма, у мене є кілька, потенційно замикаються форми, які потрібно падати; Мені потрібно обчислити їх кінцеві позиції. Розглянемо наступне:

приклади проблеми падаючих блоків

  1. Щоб обчислити остаточне положення зеленої форми, я просто сканую вниз на кожен квадрат, поки не потрапляю на інший квадрат або край дошки. Зроблено

  2. Для декількох простих фігур я працюю вгору по дошці. Таким чином, виявляється, що червоний не потребує руху, оранжевий знижується на один, зелений - на три. Зроблено

  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 вирішив би і 6. Насправді, я вважаю, що рішення 5, мабуть, вирішить усі ці ситуації.
UnderscoreZero

+1 дякую за обмін. Дивовижне рішення. Любіть анімацію :)
ashes999

Здрастуйте, ashes999, я думаю, мені потрібна нова анімація зі стрілками, яка показує, як логіка зупинки "тече" з нижнього ряду і
поширюється

Відповіді:


4

Ну, вам точно не потрібно ставитися до фігур як до однієї, якщо є різниця між рухомими формами і формами, які перебувають у спокої. Форма (A) могла б виявити форму (B) безпосередньо під нею, і якщо вона рухається, то форма B потім може побачити, чи є щось безпосередньо під нею, і якщо є форма спокою, то A і B тепер відпочивають, і якщо нічого немає, вони обидва рухаються вниз, але якщо є рухома форма, то ця нова форма буде розглядатися A і B як A, що обробляється B, тож вона є свого роду рекурсивною. Майте на увазі, що для кожного кроку найнижчі фігури потрібно спочатку перевірити форми під ними.

Отже, для проблеми № 6 зелена форма є найнижчою рухомою формою, і вона побачить, що єдина форма, що знаходиться безпосередньо під нею, - це червона форма, тож тоді червона форма нічого не виявить безпосередньо під нею, і вони рухатимуться вниз . Як тільки зелена форма примикає до помаранчевої форми, вона буде відпочивати, а червона форма рухається вниз, а потім виявляє зелену форму, що відпочиває, і вона теж відпочиватиме.


Я маю рацію, думаючи, що нам доведеться вважати, що всі форми не знаходяться в спокої, поки не доведемо інше?
oodavid

Я просто витратив деякий час на роздуми над цим, і мушу сказати, що це звучить як дуже гарна техніка. Я спробую це завтра / вихідні і побачу, як це забирається.
oodavid

3

Схоже, що проблема із справами №5 та №6 випливає з одного кореня: ви виконуєте лише один пропуск перевірок руху. Вам слід продовжувати рухати речі вниз (давайте назвати це "тяжкості пропуску"), поки ви не знаєте, що нічого не рухалося.

Наприклад, у випадку 6 це те, що станеться, якщо ви використали кілька пропусків:

  • Помаранчевий рухається вниз
  • Зелений рухається вниз
  • Помаранчевий рухається вниз
  • Зелений рухається вниз
  • Помаранчевий рухається вниз
  • Нічого не рухається вниз (зроблено!)

Ця стратегія з декількома гравітаційними пропусками також може вирішити номер 5, хоча це не допоможе у випадках №3 та №4, де, здається, потрібно ставитися до них як до однієї частини.

Щоб розрізнити, коли два чи більше творів слід розглядати як єдину частину, я думаю, що найпростіший алгоритм - це перевірити, чи є в об'єднаному просторі всіх частин якісь «дірки». Якщо вони є, це можна розглядати як декілька штук.


1
З №3 та №4 також можуть бути варіанти, коли, скажімо, 2 або 3 форми повністю укладені більшою формою "С", з'ясування того, чи є шматки коагульовані, може викликати подальші проблеми. Я піду, щоб побачити, що з цього виходить! Cheers @ ashes999
oodavid

@ovidvid ваші вимоги / дизайн мені здається надмірно складним. Почніть з чогось більш простого і працюйте над тим, як вирішувати ці проблеми.
ashes999

Ого, проблема вище - це ретельно спрощений / абстрагований спосіб описати набагато складнішу проблему. Я роблю це для трепету погоні!
oodavid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.