Переміщення гравців на один і той же квадрат одночасно?


15

Розглянемо сітку квадратів 2 x 2. Гравець може переміститися на квадрат, якщо:

  • жоден інший гравець не хоче рухатися на майдан наступного ходу
  • жоден інший гравець не чекав і досі обіймає цю площу

Прикладна діаграма

Я включив зображення вище, щоб описати свою проблему.

Гравці рухаються одночасно.

Якщо 2 (або більше) гравців намагаються переміститися в один і той же квадрат, не рухаються.


1
чи може гравець перейти один до одного плитки за один крок? наприклад, чи можуть жовтий і синій перемикатися місцями в точно такому ж кроці (синій переходить на одну плитку ліворуч, а жовтий йде на одну плитку праворуч)?
Ali1S232

Гаджет так. Але в якийсь момент я не хотів би, щоб два сусідні гравці могли безпосередньо міняти місцями
t123

то моя відповідь вирішує це питання.
Ali1S232

2
Надзвичайно актуально: ознайомтеся з правилами руху дипломатії. en.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike

Відповіді:


11
  1. Позначте всіх гравців як стаціонарних, так і рухомих, залежно від того, чи подали ходу цей поворот.
  2. Перегляньте список ходів. Якщо два ходи вказують на одне місце, видаліть їх зі списку та встановіть гравців нерухомими.
  3. Проведіть список, видаляючи всі рухи, які вказують на стаціонарний програвач або іншу перешкоду. Робіть це кілька разів, поки список не зміниться, коли ви переходите через нього.
  4. Переміщення всіх гравців.

Я думаю, що це має працювати. Це, безумовно, працює для справи, яку ви опублікували, і ще декількох дрібницьких випадків, на яких я перевіряв.


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

16

Розв’язання зіткнення замість запобігання зіткненням.

Просто перемістіть об’єкти, а потім перевірте, чи відбулися зіткнення. Якщо сталося зіткнення з іншим блоком, поверніться до попереднього квадрата, або залежно від типу гри, на інший квадрат.


1
Так, але якщо хтось повинен повернутися назад, то й іншим доведеться також рухатися назад ...
t123

2
Ви маєте рацію, але знову-таки це залежить від фактичного типу гри, потрібно буде більше інформації та ситуація зміниться залежно від типу. Мова йшла про найзагальнішу відповідь.
ultifinitus

5
вам не доведеться вирішувати всі зіткнення за один крок. перемістіть увесь об’єкт, перевірте, чи є зіткнення зворотні ходи, пов'язані в цьому зіткненні, повторюйте цей процес, поки не залишиться зіткнення.
Ali1S232

4
Move all players according to their request.
while there are still some squares multiply occupied:
    For each square that is now multiply occupied:
        For each player in that square that moved there this turn:
            Return them to their previous square
            Mark them as having not moved this turn

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


3

Ще одне рішення - використовувати карту в 2 рази більше, ніж показана вами. кожного разу, коли ви хочете переміщувати гравців, ви переміщуєте їх двічі, тому гравці завжди приземляються на плитки з рівним значенням як для X, так і для Y. Знову трапляються деякі рідкісні випадки, на які потрібно буде більше уваги, але більшість можливих випадків вирішуються (як, наприклад, ви описано), не замислюючись двічі.


Я думаю, що ви щось тут маєте на увазі, але це не проходить через вашу відповідь. Як використання 2x-карти вирішує проблему зіткнення?
Зан Лінкс

Добре. Я думаю, що бачу відповідь. Дві частини, що рухаються протилежними напрямками, приземляються на одну площу і стикаються. Шматки, що рухаються за годинниковою стрілкою, рухаються на півкроку, завжди залишаючи відкритий простір для іншого шматка.
Зан Лінкс

@ZanLynx: саме так воно вирішує проблему, єдиною проблемою буде те, коли дві частини (скажімо, зелений і синій) зіткнуться, а інший шматок (жовтий) збирається заповнити останню позицію зеленого. у випадках, подібних до цих (якщо вони можливі), вам потрібно вирішити зіткнення, як це запропоновано ultifinitus.
Ali1S232

Найпростіша реалізація, яку я знаю для виявлення зіткнень, - це суміш міни та ульфітиніту. моє добре перевірити, чи шматки перетинаються один з одним, і неліфітініт добре вирішувати інші види зіткнення.
Ali1S232

0

Реєструйте всі запитувані ходи за допомогою масиву чи карти.

Якщо виникає конфлікт, поверніть відповідний запит на переміщення. Якщо це повертає об'єкт у квадрат, який намагається зайняти інший об'єкт, поверніть запит об'єкта, що запитує.

Псевдокод:

int[][] game; // game board

var doMoves() {
    int[][] dest = [][]; // destinations; cleared each run

    for (obj in gameObjects)
        if (obj.moveRequest) {
            var o = dest[obj.moveX][obj.moveY];
            if (o) {
                // collision!
                o.doNotMove = true;
                obj.doNotMove = true;
            } else {
                dest[obj.moveX][obj.moveY] = obj;
            }
        }
    }

    // check move validity
    for (obj in gameObjects) {
        if (obj.doNotMove) continue;

        var o = game[obj.moveX][obj.moveY];
        if (o and o.doNotMove)
            revertRequest(obj, dest);
    }

    // process moves
    //etc
}

// recursive function to back up chained moves
var revertRequest(obj, dest) {
    if (!obj.doNotMove) {
        obj.doNotMove = true;
        var next = dest[obj.x][obj.y];
        if (next)
            revertRequest(next, dest);
    }
}

0

Спираючись на відповідь SimonW , ось чіткий алгоритм:

Дозвольте squaresбути масивом, індексованим місцями програвача, і містить для кожного можливого місця розташування або індекс іншого місця розташування, або спеціальне значення NULL. (Ви можете зберегти це як розріджений масив.) Можливі значення записів у цьому масиві можуть бути інтерпретовані так:

  • Якщо squares[S]є NULL, то площа Sможе вільно переміщатися в.
  • Якщо squares[S] == S, або гравець уS може або не зможе рухатися, або два (або більше) гравців намагалися перейти Sодночасно, і їм обом було відмовлено.
  • В іншому випадку squares[S]буде містити індекс площі, з якої гравець хоче перейти на квадратS .

На кожному кроці ініціалізуйте всі записи squaresдо, NULLа потім запустіть наступний алгоритм:

for each player:
   current := the player's current location;
   target := the location the player wants to move to (may equal current);
   if squares[target] is NULL:
      squares[target] := current;  // target is free, mark planned move
   else
      // mark the target square as contested, and if necessary, follow
      // the pointers to cancel any moves affected by this:
      while not (target is NULL or squares[target] == target):
         temp := squares[target];
         squares[target] := target;
         target := temp;
      end while
      // mark this player as stationary, and also cancel any moves that
      // would require some else to move to this square
      while not (current is NULL or squares[current] == current):
         temp := squares[current];
         squares[current] := current;
         current := temp;
      end while
   end if
end for

Після цього знову проведіть список гравців і перемістіть тих, хто може це зробити:

for each player:
   current := the player's current location;
   if not squares[current] == current:
       move player;
   end if
end for

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

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

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