Oyuncuları aynı anda aynı kareye mi taşımak istiyorsunuz?


15

2 x 2 karelik bir ızgara düşünün. Bir oyuncu aşağıdaki durumlarda bir kareye geçebilir:

  • başka hiçbir oyuncu bir sonraki turda kareye geçmek istemez
  • başka hiçbir oyuncu bu turu hala beklemiyor ve meydanı işgal ediyor

Örnek Diyagram

Sorunumu tanımlamak için yukarıdaki resmi ekledim.

Oyuncular aynı anda hareket ederler.

2 (veya daha fazla) oyuncu aynı kareye hareket etmeye çalışırsa, ikisi de hareket etmez.


1
oyuncu birbirlerine bir adımda fayans taşıyabilir? örneğin sarı ve mavi anahtar aynı adımda yerleştirilebilir (mavi bir döşemeyi sola, sarı bir döşemeyi sağa gider)?
Ali1S232

Şimdilik Gajet evet. Ama bir noktada 2 komşu oyuncunun yerleri doğrudan değiştirmesini
istemiyorum

sonra cevabım bu sorunu çözer.
Ali1S232

2
SON DERECE ilgili: Diplomasi için hareket kurallarına göz atın. en.wikipedia.org/wiki/Diplomacy_(game)#Movement_phase
TehShrike

Yanıtlar:


11
  1. Bu turda hamle göndermelerine bağlı olarak tüm oyuncuları sabit veya hareketli olarak işaretleyin.
  2. Hamle listesini gözden geçirin. İki hareket aynı yeri gösteriyorsa, bunları listeden kaldırın ve oyuncuları sabit tutun.
  3. Sabit bir oyuncuya veya başka bir engele işaret eden tüm hareketleri kaldırarak listede dolaşın. Bunu, listeden geçerken değişmeyene kadar tekrar tekrar yapın.
  4. Tüm oyuncuları taşı.

Bunun işe yarayacağını düşünüyorum. Kesinlikle yayınladığınız dava için çalışıyor ve test ettiğim birkaç diğer önemsiz vaka.


Evet, bu işe yaramalı. Gerçekte oyuncu listesi üzerinde tekrar tekrar döngü yapmak istemediğinizi unutmayın; pratikte, çarpışmaları geri takip ederek çözmek çok daha verimli olacaktır.
Ilmari Karonen

16

Çarpışma önleme yerine çarpışma çözümü.

Sadece nesneleri hareket ettirin, sonra herhangi bir çarpışma olup olmadığını kontrol edin. Başka bir blokla çarpışma olursa, önceki kareye veya oyun türüne bağlı olarak farklı bir kareye geri dönün.


1
Evet ama birinin geri hareket etmesi gerekiyorsa, diğerleri de geri hareket etmek zorunda kalacak ...
t123

2
Haklısın, ama yine de gerçek oyun türüne bağlı, daha fazla bilgi gerekli olacak ve durum türüne göre değişecek. Bu mevcut en genel cevapla ilgiliydi.
ultifinitus

5
tüm çarpışmaları tek adımda çözmek zorunda değilsiniz. tüm nesneyi hareket ettirin, herhangi bir çarpışma olup olmadığını kontrol edin, bu çarpışma ile ilgili ters hareketler yapın, kalan çarpışma kalmayıncaya kadar bu işlemi tekrarlayın.
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

Bu, her oyuncunun nereden taşındıklarını hatırlamasını gerektirir, böylece geri dönebilir ve ayrıca bu dönüşü hareket ettirip değiştirmediklerini hatırlar. Bu ikinci kontrol, her parçanın yalnızca bir kez geri dönmesi gerektiği ve algoritmanın düzgün şekilde sonlandığını garanti etmesi gerektiği anlamına gelir. Ayrıca yalnızca taşınan oyuncuların iade edilmesini sağlar - orijinal yolcu, kaldırılmaları düşünülmediği için kalmaya devam eder.


3

Başka bir çözüm, gösterdiğinizden 2 kat daha büyük bir harita kullanmaktır. oyuncuları her hareket ettirmek istediğinizde onları iki kez hareket ettirirsiniz, böylece oyuncular her zaman hem X hem de Y için eşit değere sahip karolara inerler. iki kez düşünmeden).


Burada aklınızda bir şey olduğunu düşünüyorum, ancak cevabınızda bu gerçekleşmiyor. 2x harita kullanmak çarpışma problemini nasıl çözer?
Zan Lynx

Tamam. Sanırım cevabı görüyorum. Ters yönde hareket eden iki parça aynı kareye iner ve çarpışır. Saat yönünde hareket eden parçalar yarım adım ilerler ve her zaman başka bir parçanın hareket etmesi için açık bir alan bırakır.
Zan Lynx

@ZanLynx: sorunu tam olarak bu şekilde çözer, tek sorun iki parçanın (yeşil ve mavi diyelim) çarpışacağı ve başka bir parçanın (sarı) yeşilin son konumunu dolduracağı olacaktır. bunlara benzer durumlarda (mümkünse) çarpışmaları ultifinitus önerdiği gibi çözmeniz gerekir.
Ali1S232

çarpışma tespiti için bildiğim en kolay uygulama mayın ve ultifinitus karışımı. Benimki parçaların birbirini geçip geçmediğini kontrol etmek iyidir ve unltifinitus diğer çarpışma türlerini çözmek için iyidir.
Ali1S232

0

İstenen tüm hareketleri bir dizi veya harita kullanarak kaydedin.

Bir çakışma varsa, söz konusu taşıma isteğini geri alın. Bu, nesneyi başka bir nesnenin işgal etmeye çalıştığı kareye döndürürse, istekte bulunan nesnenin isteğini geri alın.

Sahte kod:

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'un cevabı üzerine inşa , burada açık bir algoritma var:

Izin vermek squaresoyuncu konumları tarafından endeksli ve olası her konum için, başka bir konumun dizin veya özel değer içeren bir dizi NULL. (Bunu seyrek bir dizi olarak saklamak isteyebilirsiniz.) Bu dizideki girişlerin olası değerleri aşağıdaki gibi yorumlanabilir:

  • Eğer squares[S]öyleyse NULL, kare Shareket etmekte serbesttir.
  • Eğer squares[S] == S, ya oyuncunun oynamaması ya da oynamaması Sya da iki (ya da daha fazla) oyuncu Saynı anda oynamayı denediyse ve ikisi de reddedilirse.
  • Aksi takdirde, squares[S]bir oyuncunun kareye taşımak istediği karenin dizinini içerir S.

Her dönüşte, her girdileri başlatmak squaresiçin NULLve aşağıdaki algoritmayı çalıştırın:

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

Bundan sonra, oyuncular listesinde tekrar dolaşın ve bunu yapabilenleri taşıyın:

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

Her hareket sadece bir kez planlanabildiğinden ve en fazla bir kez iptal edilebildiğinden, bu algoritma en kötü durumda bile n oyuncu için O ( n ) zamanında çalışacaktır .

(Ne yazık ki, bu algoritma oyuncuların yer değiştirmesini veya yolları çapraz olarak geçmesini engellemeyecektir. Gajet'in iki adımlı hilesini buna uyarlamak mümkün olabilir , ancak bunu yapmanın tamamen naif yolu işe yaramaz ve çok yorgunum şimdi daha iyi bir yol bulmak için.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.