Saat ini saya memiliki permainan sederhana seperti Tetris dan telah menemukan masalah yang tidak bisa saya selesaikan.
Tidak seperti Tetris di mana ada satu bentuk jatuh, saya memiliki beberapa bentuk yang berpotensi saling bertautan yang perlu jatuh; Saya perlu menghitung posisi akhir mereka. Pertimbangkan yang berikut ini:
Untuk menghitung posisi akhir dari bentuk hijau, saya cukup memindai ke bawah untuk setiap kotak sampai saya menekan kotak lain atau tepi papan. Selesai
Untuk beberapa bentuk sederhana saya bekerja dengan cara saya naik papan. Jadi merah ditemukan tidak perlu bergerak, oranye turun satu, hijau turun tiga. Selesai
Saya tidak tahu bagaimana memperlakukan bentuk hijau dan merah yang saling terkait. Menggunakan logika # 2 kita akan berakhir "terjebak" mengambang di udara. Jika saya memindai ke bawah untuk bentuk hijau, saya menemukan merah dan karenanya tidak bergerak, dan sebaliknya untuk merah. Solusinya mungkin memperlakukan dua bentuk sebagai satu.
Mirip dengan # 3, dalam skenario ini saya juga bisa berhasil dengan memperlakukan objek sebagai satu.
Tidak seperti # 3 dan # 4 saya tidak bisa memperlakukan bentuk sebagai satu karena bentuk oranye akan berakhir mengambang satu-persegi terlalu tinggi ...
Variasi lain dari masalah # 6.
Mungkin ada skenario lain di mana saya memiliki banyak bentuk yang terjalin dalam skenario yang lebih kompleks, tetapi saya pikir di atas mencakup bagian paling mendasar dari masalah.
Saya merasa ada solusi elegan yang belum saya temui / pikirkan dan akan sangat berterima kasih atas wawasan, ide, atau sumber daya apa pun.
LARUTAN
Solusi yang saya buat memang elegan, berdasarkan jawaban @ user35958 di bawah ini, saya telah membuat fungsi rekursif berikut (kode semu)
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 animasi yang menunjukkan setiap celah solusi
Untuk meringkas:
- Saat "menghentikan" kotak, kami juga berhenti:
- SETIAP persegi di atasnya. SELALU.
- Tetangga tetangga tempat kita terhubung (yaitu bentuk yang sama).
- Kami menghentikan seluruh baris bawah, dan fungsinya berulang melalui kotak.
- Kami ulangi sampai semua kotak dihentikan.
- Lalu kita hidup.
sumber
Jawaban:
Nah, Anda tidak perlu memperlakukan bentuk sebagai satu jika ada perbedaan antara bentuk yang bergerak dan bentuk yang diam. Bentuk (A) dapat mendeteksi bentuk (B) langsung di bawahnya dan jika bergerak, maka bentuk B kemudian dapat melihat apakah ada sesuatu yang langsung di bawahnya, dan jika ada bentuk istirahat, maka A dan B sekarang sedang beristirahat, dan jika tidak ada apa-apa, keduanya bergerak ke bawah, tetapi jika ada bentuk yang bergerak, maka bentuk baru ini akan diperlakukan oleh A dan B sebagai A yang diperlakukan B, jadi itu semacam rekursif. Ingatlah bahwa untuk setiap langkah, bentuk terendah harus memeriksa bentuk di bawahnya terlebih dahulu.
Jadi, untuk masalah # 6, bentuk hijau adalah bentuk bergerak terendah, dan ia akan melihat bahwa satu-satunya bentuk yang langsung di bawahnya adalah bentuk merah, sehingga bentuk merah akan mendeteksi tidak ada yang langsung di bawahnya, dan mereka akan bergerak ke bawah . Setelah bentuk hijau berdekatan dengan bentuk oranye, itu akan beristirahat, dan bentuk merah akan bergerak ke bawah dan kemudian mendeteksi bentuk hijau sisanya, dan itu akan beristirahat juga.
sumber
Sepertinya masalah dengan kasus # 5 dan # 6 berasal dari satu root: Anda hanya melakukan satu pass gerakan. Anda harus terus memindahkan barang ke bawah (sebut saja "lintasan gravitasi") sampai Anda tahu tidak ada yang bergerak.
Misalnya, dalam kasus 6, inilah yang akan terjadi jika Anda menggunakan beberapa lintasan:
Strategi multiple pass gravitasi ini dapat menyelesaikan # 5 juga, walaupun ini tidak akan membantu dengan kasus # 3 dan # 4 di mana Anda perlu memperlakukannya seperti sepotong.
Untuk membedakan kapan dua atau lebih bagian harus diperlakukan sebagai satu bagian, saya pikir algoritma termudah adalah untuk memeriksa apakah ada "lubang" di ruang gabungan semua bagian. Jika ada, dapat diperlakukan sebagai beberapa bagian.
sumber