Düşen Bloklar ve karmaşık şekiller


10

Şu anda Tetris benzeri basit bir oyunum var ve çözemediğim bir sorunla karşılaştım.

Tek bir düşen şeklin olduğu Tetris'in aksine, düşmesi gereken çoklu, potansiyel olarak birbirine kenetlenen şekillerim var; Onların son konumlarını hesaplamam gerekiyor. Aşağıdakileri göz önünde bulundur:

düşen blok problemi örnekleri

  1. Yeşil şeklin son konumunu hesaplamak için, başka bir kareye veya tahtanın kenarına çarpana kadar her kare için aşağı doğru tararım. Bitti

  2. Birden çok, basit şekiller için tahta yukarı doğru çalışırım. Böylece kırmızının hareket etmesine gerek olmadığı bulunur, turuncu birer birer aşağı, yeşil üçte bir aşağı gider. Bitti

  3. Kilitli yeşil ve kırmızı şekillerin nasıl tedavi edileceğini bilmiyorum. # 2 mantığını kullanarak sonunda havada yüzen "sıkışmış" olurdu. Eğer yeşil şekli aşağıya tararsam, kırmızı ile karşılaşırım ve bu nedenle hareket etmezim ve tersi kırmızı için. Çözüm, iki şekli tek olarak ele almak olabilir.

  4. # 3'e benzer şekilde, bu senaryoda nesneleri bir olarak ele alarak da başarabilirim.

  5. # 3 ve # 4'ün aksine, turuncu şekil bir kare çok yüksek yüzer gibi olacağı için şekli bir olarak ele alamadım ...

  6. Sorun # 6'nın başka bir varyasyonu.

Giderek daha karmaşık senaryolarda iç içe geçen birçok şekle sahip olduğum başka senaryolar da olabilir, ancak bence yukarıdakiler sorunun en temel kısımlarını kapsıyor.

Henüz karşılaşmadığım / düşünmediğim ve herhangi bir görüş, fikir veya kaynakta minnettar olacağım zarif bir çözüm var gibi hissediyorum.

ÇÖZÜM

Geldiğim çözüm, @ user35958'in aşağıdaki cevabına dayanarak gerçekten zarif, aşağıdaki özyinelemeli işlevi (sahte kod) oluşturdum

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);
}

Çözümün her geçişini gösteren animasyonlu GIF

Özetle:

  • Bir kareyi "durdururken", biz de duruyoruz:
    • Üzerinde HERHANGİ BİR kare. HER ZAMAN.
    • Bağlandığımız komşu kare (yani aynı şekil).
  • Tüm alt satırı durdururuz ve fonksiyon kareler boyunca tekrarlanır.
  • Tüm kareler durana kadar tekrarlıyoruz.
  • Sonra canlandırıyoruz.

Mantıksal dizinin her geçişini gösteren animasyonlu GIF


Eğer 5'i çözdüysen 6'nın da çözüleceğini tahmin ediyorum. Aslında, 5'i çözmenin muhtemelen tüm bu durumları çözeceğine inanıyorum.
UnderscoreZero

+1 paylaştığınız için teşekkürler. İnanılmaz bir çözüm. Animasyonu seviyorum :)
ashes999

Şerefe Ash9999, sanırım stop mantığının alt sıradan nasıl "aktığını" ve tüm sahne boyunca nasıl çoğaldığını gösteren oklarla yeni bir animasyona ihtiyacım var ...
oodavid

Yanıtlar:


4

Hareket eden şekiller ile hareketsiz şekiller arasında bir ayrım varsa şekillere tam olarak davranmanız gerekmez. Bir şekil (A) doğrudan altındaki bir şekli (B) algılayabilir ve hareket ederse, B şekli daha sonra doğrudan altında bir şey olup olmadığını görebilir ve dinlenme şekli varsa, A ve B şimdi dinlenir ve hiçbir şey yoksa, ikisi de aşağı doğru hareket eder, ancak hareketli bir şekil varsa, bu yeni şekil A ve B tarafından A muamele edilmiş B olarak değerlendirilir, bu yüzden bir tür özyinelemeli. Her adım için, en düşük şekillerin önce altındaki şekilleri kontrol etmesi gerektiğini unutmayın.

Yani, sorun # 6 için, yeşil şekil en düşük hareketli şekildir ve doğrudan altındaki tek şeklin kırmızı şekil olduğunu görecektir, bu nedenle kırmızı şekil doğrudan altında hiçbir şey algılamaz ve aşağı doğru hareket ederler . Yeşil şekil turuncu şekle bitişik olduğunda, dinlenir ve kırmızı şekil aşağı doğru hareket eder ve daha sonra dinlenme yeşil şeklini algılar ve dinlenir.


Aksini ispatlayana kadar tüm şekillerin dinlenmediğini varsaymamız gerektiğini düşünüyor muyum?
oodavid

Bunu düşünmek için biraz zaman harcadım ve bunun çok iyi bir teknik gibi geldiğini söylemeliyim. Yarın / haftasonu deneyeceğim ve nasıl geçtiğini göreceğim.
oodavid

3

# 5 ve # 6 vakalarındaki sorun tek bir kökten kaynaklanıyor gibi görünüyor: sadece bir geçiş hareketi kontrolü gerçekleştiriyorsunuz. Hiçbir şey hareket edene kadar bir şeyleri aşağı hareket ettirmelisiniz (buna "yerçekimi geçişi" diyelim).

Örneğin, 6 durumunda, birden fazla geçiş kullandıysanız bu olurdu:

  • Turuncu aşağı doğru hareket eder
  • Yeşil aşağı doğru hareket eder
  • Turuncu aşağı doğru hareket eder
  • Yeşil aşağı doğru hareket eder
  • Turuncu aşağı doğru hareket eder
  • Hiçbir şey aşağıya inmez (bitti!)

Bu çoklu yerçekimi geçişleri stratejisi # 5'i de çözebilir, ancak 3 ve # 4 vakalarına tek parça gibi davranmanız gereken yerlerde yardımcı olmaz.

İki veya daha fazla parçanın ne zaman tek bir parça olarak ele alınması gerektiğini ayırt etmek için, en kolay algoritmanın tüm parçaların birleşik alanında herhangi bir "delik" olup olmadığını kontrol etmek olduğunu düşünüyorum. Varsa, birden fazla parça olarak ele alınabilir.


1
# 3 ve # 4 ile, 2 veya 3 şeklin daha büyük bir "C" şekliyle tamamen çevrelendiği varyasyonlar da olabilir; Bunu bir deneyeceğim ve ne olduğunu göreceğim! Cheers @ ashes999
oodavid

@ ihtiyaçlarınız / tasarım ihtiyaçlarınız benim için gereksiz yere karmaşık görünüyor. Daha basit bir şeyle başlayın ve bu sorunları çözerken yolunuza devam edin.
ashes999

Nahhhh, yukarıdaki sorun çok daha karmaşık bir sorunu tanımlamak için tamamen basitleştirilmiş / soyutlanmış bir yoldur. Bunu kovalamaca heyecanı için yapıyorum!
oodavid
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.