В даний час я маю просту гру, схожу на тетріс, і зіткнувся з проблемою, яку я не можу вирішити.
На відміну від тетрісу, де є одна падаюча форма, у мене є кілька, потенційно замикаються форми, які потрібно падати; Мені потрібно обчислити їх кінцеві позиції. Розглянемо наступне:
Щоб обчислити остаточне положення зеленої форми, я просто сканую вниз на кожен квадрат, поки не потрапляю на інший квадрат або край дошки. Зроблено
Для декількох простих фігур я працюю вгору по дошці. Таким чином, виявляється, що червоний не потребує руху, оранжевий знижується на один, зелений - на три. Зроблено
Я не знаю, як поводитися із замкненими зеленими та червоними формами. Використовуючи логіку №2, ми б в кінцевому підсумку "застрягли" в плаваючому повітрі. Якщо я сканую вниз на зелену форму, я стикаюся з червоним і, таким чином, не рухаюся, і навпаки для червоного. Рішенням може бути розгляд двох форм як однієї.
Подібно до №3, у цьому сценарії я також міг досягти успіху, розглядаючи об'єкти як один.
На відміну від №3 та №4, я не міг трактувати фігуру як єдину, оскільки помаранчева форма в кінцевому підсумку плавала на один квадрат занадто високою ...
Ще одна варіація проблеми №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, що показує кожен пропуск рішення
Підсумовувати:
- "Зупиняючи" квадрат, ми також зупиняємось:
- БУДЬ-яку площу над ним. ВСЕГДА.
- Сусідній квадрат, до якого ми пов'язані (тобто тієї ж форми).
- Зупиняємо весь нижній ряд, і функція повторюється через квадрати.
- Повторюємо, поки не зупиняться всі квадрати.
- Потім ми оживляємо.