Spostare i giocatori nello stesso riquadro contemporaneamente?


15

Considera una griglia 2 x 2 di quadrati. Un giocatore può spostarsi su una casella se:

  • nessun altro giocatore vuole muoversi nella casella il prossimo turno
  • nessun altro giocatore ha aspettato e sta ancora occupando la casella in questo turno

Esempio di diagramma

Ho incluso l'immagine sopra per descrivere il mio problema.

I giocatori si muovono contemporaneamente.

Se 2 (o più) giocatori provano a muoversi nella stessa casella, nessuno dei due si muove.


1
il giocatore può spostarsi tra loro in un solo passaggio? per esempio, il giallo e il blu possono cambiare posizione esattamente nello stesso passaggio (il blu fa una tessera a sinistra e il giallo va una tessera a destra)?
Ali1S232,

Gajet sì per ora. Ma a un certo punto non vorrei che 2 giocatori vicini potessero scambiare i posti direttamente
t123

quindi la mia risposta risolve questo problema.
Ali1S232,

2
ESTREMAMENTE rilevante: controlla le regole di movimento per la diplomazia. it.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike

Risposte:


11
  1. Contrassegna tutti i giocatori come fermi o in movimento, a seconda che abbiano inviato una mossa in questo turno.
  2. Passa attraverso l'elenco delle mosse. Se due mosse puntano nella stessa posizione, rimuovile dall'elenco e metti i giocatori fermi.
  3. Scorri la lista rimuovendo tutte le mosse che indicano un giocatore fermo o un altro ostacolo. Fallo ripetutamente fino a quando l'elenco non cambia quando lo attraversi.
  4. Sposta tutti i giocatori.

Penso che dovrebbe funzionare. Funziona sicuramente per il caso che hai pubblicato, e un paio di altri casi banali su cui l'ho provato.


Sì, dovrebbe funzionare. Si noti che in realtà non si desidera scorrere ripetutamente l'elenco dei giocatori; in pratica, sarà molto più efficiente risolvere le collisioni con il backtracking.
Ilmari Karonen,

16

Risoluzione delle collisioni, anziché prevenzione delle collisioni.

Basta spostare gli oggetti, quindi verificare se ci sono state delle collisioni. Se c'è stata una collisione con un altro blocco, torna alla casella precedente o, a seconda del tipo di gioco, una casella diversa.


1
Sì, ma se uno deve tornare indietro, anche gli altri dovranno tornare indietro ...
t123

2
Hai ragione, ma dipende ancora dal tipo di gioco effettivo, sarebbero necessarie ulteriori informazioni e la situazione cambierebbe in base al tipo. Questa era la risposta più generica disponibile.
ultifinito

5
non è necessario risolvere tutte le collisioni in un solo passaggio. sposta tutti gli oggetti, controlla se ci sono delle collisioni inverse relative a quella collisione, ripeti questo processo fino a quando non ci sono più collisioni.
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

Ciò richiede che ogni giocatore si ricordi da dove si sono appena mossi, in modo che possano essere restituiti, e anche ricordare se si sono mossi in questo turno. Questo secondo controllo indica che ogni pezzo dovrà essere restituito una sola volta e dovrebbe garantire che l'algoritmo venga terminato correttamente. Assicura inoltre che vengano restituiti solo i giocatori che si sono mossi: l'occupante originale rimane perché non vengono considerati per la rimozione.


3

Un'altra soluzione è utilizzare una mappa 2 volte più grande di quella che stai mostrando. ogni volta che vuoi spostare i giocatori, li sposti due volte in modo che i giocatori finiscano sempre su tessere con valore pari sia per X che per Y. di nuovo ci saranno alcuni rari casi che richiedono più attenzione ma la maggior parte dei casi possibili vengono risolti (come quello che tu descritto) senza pensarci due volte.


Penso che tu abbia qualcosa in mente qui, ma non sta arrivando nella tua risposta. In che modo l'utilizzo di una mappa 2x risolve il problema delle collisioni?
Zan Lynx,

Va bene. Penso di vedere la risposta. Due pezzi che si muovono in direzioni opposte atterrano sulla stessa piazza e si scontrano. I pezzi che si muovono in senso orario si spostano di mezzo passo, lasciando sempre uno spazio aperto in cui spostarsi un altro pezzo.
Zan Lynx,

@ZanLynx: è esattamente così che risolve il problema, l'unico problema sarà quando due pezzi (diciamo verde e blu) si scontreranno e un altro pezzo (giallo) riempirà l'ultima posizione del verde. in casi simili a questi (se possibile) è necessario risolvere le collisioni come suggerito da ultifinito.
Ali1S232

l'implementazione più semplice che conosco per il rilevamento delle collisioni è un mio mix e ultifinito. il mio è buono per verificare se i pezzi si incrociano e unltifinitus è buono per risolvere altri tipi di collisione.
Ali1S232,

0

Registra tutte le mosse richieste usando un array o una mappa.

In caso di conflitto, ripristinare la richiesta di spostamento in questione. Se restituisce l'oggetto a un quadrato che un altro oggetto sta tentando di occupare, ripristina la richiesta dell'oggetto richiedente.

Pseudo codice:

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

Sulla base della risposta di SimonW , ecco un algoritmo esplicito:

Sia squaresuna matrice indicizzata dalle posizioni dei giocatori e contenente, per ogni possibile posizione, l'indice di un'altra posizione o il valore speciale NULL. (È possibile che si desideri memorizzare questo come un array sparse.) I possibili valori delle voci in questo array possono essere interpretati come segue:

  • Se squares[S]è NULL, il quadratoS è libera di spostarsi.
  • Se squares[S] == S, il giocatore a Snon può o non si sposta, o due (o più) giocatori hanno tentato di spostarsiS contemporaneamente e vengono entrambi negati.
  • Altrimenti, squares[S]conterrà l'indice del quadrato da cui un giocatore vuole passare al quadrato S.

Ad ogni turno, inizializzare tutte le voci di squaresto NULLe quindi eseguire il seguente algoritmo:

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

Successivamente, ripeti l'elenco dei giocatori e sposta quelli che sono in grado di farlo:

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

Poiché ogni mossa può essere pianificata una sola volta e annullata al massimo una volta, questo algoritmo verrà eseguito in tempo O ( n ) per n giocatori anche nel caso peggiore.

(Ahimè, questo algoritmo non impedirà ai giocatori di cambiare posto o attraversare percorsi in diagonale. Potrebbe essere possibile adattare il trucco in due fasi di Gajet , ma il modo completamente ingenuo per farlo non funzionerà e sono troppo stanco per capire un modo migliore proprio ora.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.