Saya membuat game yang mirip dengan Tetris, dengan dua perbedaan utama: layar sudah mulai dipenuhi ubin (seperti dalam Puzzle Quest untuk Nintendo DS dan PC) dan setiap ubin individu memiliki huruf di dalamnya. Tujuan pemain adalah menghilangkan ubin dengan membentuk kata-kata yang valid dengannya. Kata-kata dibentuk dengan menempatkan huruf-huruf di samping satu sama lain, ke segala arah, kecuali secara diagonal.
Pemain dapat memindahkan seluruh baris ubin ke kiri atau ke kanan atau seluruh kolom ubin ke atas atau ke bawah, untuk sebanyak mungkin ruang yang diinginkan (jika pergerakan baris / kolom melampaui batas papan, maka huruf yang melewati batas akan "siklus", muncul di ujung baris / kolom). Setelah aksi pemain, permainan harus memeriksa seluruh papan untuk mencari kata yang valid dan menghapus huruf yang membentuk kata-kata itu dari papan. Huruf-huruf di atas yang telah dihapus akan jatuh di tempat surat-surat yang dihapus dan surat-surat baru akan jatuh dari bagian atas layar sampai papan diisi kembali.
Saya sudah menulis algoritma linier yang, diberi urutan karakter, menentukan apakah itu kata bahasa Inggris yang valid. Masalah yang saya alami adalah: bagaimana saya bisa memeriksa kata-kata yang valid di papan tulis? Apakah kekuatan kasar satu-satunya cara? Menguji semua kemungkinan kombinasi dari papan untuk melihat apakah mereka valid sangat lambat, bahkan untuk papan kecil (5x5). Bantuan apa pun akan sangat dihargai, terima kasih!
sumber
Jawaban:
Kekerasan bukan satu-satunya cara.
Memecahkan papan permainan Anda mirip dengan memecahkan papan Boggle , kecuali lebih sederhana. Anda ingin memeriksa setiap ubin di papan, mencari untuk melihat apakah ada kata yang dapat dibuat di sepanjang arah yang sesuai.
Anda masih ingin mempersempit ruang pencarian Anda lebih jauh sehingga Anda tidak perlu repot mencari arah jika Anda tahu Anda tidak dapat membuat kata. Misalnya, jika Anda menemukan dua
q
s berturut-turut, Anda harus membatalkan. Untuk itu, Anda ingin beberapa jenis struktur data yang memungkinkan Anda untuk mengetahui apakah serangkaian karakter yang diberikan adalah awalan dari kata yang valid. Untuk ini, Anda bisa menggunakan trie , atau pohon awalan; struktur data yang berguna saat memecahkan masalah seperti ini.Pohon awalan adalah struktur berbasis simpul hierarkis, di mana setiap simpul mewakili beberapa awalan anak-anaknya, dan simpul daun (umumnya) mewakili nilai akhir. Misalnya, jika kamus Anda berisi kata-kata yang valid berisi "cat," "car," dan "cell," sebuah trie akan terlihat seperti:
Jadi, mulailah dengan mengisi pohon awalan dengan setiap kata yang valid di gim Anda.
Proses aktual untuk menemukan kata-kata yang valid di papan tulis pada waktu tertentu akan melibatkan memulai pencarian rekursif dari setiap ubin di papan tulis. Karena setiap pencarian melalui ruang papan dimulai pada beberapa ubin yang diberikan adalah independen, ini dapat diparalelkan jika diperlukan. Saat Anda mencari, Anda "mengikuti" pohon awalan berdasarkan nilai huruf ke arah yang Anda cari.
Anda akhirnya akan mencapai titik di mana tidak ada huruf di sekitarnya adalah anak-anak dari simpul pohon awalan Anda saat ini. Ketika Anda mencapai titik itu, jika memang benar bahwa simpul saat ini adalah daun, Anda telah menemukan kata yang valid. Jika tidak, Anda belum menemukan kata yang valid dan Anda dapat membatalkan pencarian.
Contoh kode dan diskusi tentang teknik ini (dan lainnya, seperti solusi pemrograman dinamis yang bahkan bisa lebih cepat dengan "membalikkan" ruang pencarian setelah mode) dapat ditemukan di blog orang ini di sini ; ia membahas pemecahan Boggle, tetapi mengadaptasi solusi untuk gim Anda kurang lebih adalah masalah mengubah arah yang memungkinkan Anda mencari.
sumber
Anda mungkin sudah mencoba ini, sudah menerapkan ini, mungkin lebih baik disertai dengan jawaban lain, dll. Tapi saya belum melihat mereka disebutkan (belum), jadi ini dia:
Anda dapat membuang banyak cek dengan melacak apa yang berubah dan apa yang tidak. Sebagai contoh:
atau, dalam kode psudo
Dan pertanyaan sepele:
Apakah Anda memiliki optimisasi kecepatan kompiler yang ditetapkan? (jika Anda menggunakan satu)
Dapatkah algoritma pencarian kata Anda dioptimalkan sama sekali? Dengan cara apapun?
sumber
IF(rowMoved){ checkColumns(); checkMovedRow(); } IF(columnMoved){ checkRows() checkMovedColumn();}
Jika pengguna hanya dapat memindahkan satu per satu, maka pada akhir gerakan itu, tidak ada huruf paralel yang bergerak dan karenanya tidak perlu memeriksa ulang itu.Ingat bahwa setiap karakter adalah nilai. Jadi gunakan itu untuk keuntungan Anda. Ada beberapa fungsi hash yang dapat dihitung dengan cepat saat iterasi pada substring. Sebagai contoh, katakanlah kita memberi setiap huruf kode 5 bit (lakukan saja
c - 'a' + 1
dalam C):Daripada Anda bisa dengan cepat menabrak semua substring dengan ukuran tertentu:
Kita dapat memeriksa substring hingga 12 huruf dengan cara ini pada arsitektur paling umum saat ini.
Jika kode hash ada di kamus Anda, Anda dapat menarik kata dari sana dengan cepat karena kode hash seperti ini unik. Saat Anda mencapai maksimal 12 huruf, Anda mungkin ingin menambahkan struktur data lain untuk kata-kata yang dimulai dengan 12 huruf itu. Jika Anda menemukan kata yang dimulai dengan 12 huruf spesifik daripada hanya membuat daftar atau tabel hash kecil untuk akhiran setiap kata yang dimulai dengan awalan itu.
Menyimpan kamus dari semua kode kata yang ada tidak boleh lebih dari beberapa megabyte memori.
sumber
Apakah Anda hanya terbatas pada bentuk Tetris klasik ketika membentuk kata-kata, atau akankah formasi apa pun melakukannya? Bisakah kata-kata dibengkokkan tanpa batas atau hanya sekali? Bisakah sebuah kata sepanjang yang diinginkan? Cara ini cukup rumit jika Anda bisa melakukan banyak tikungan sesuka hati, efektif membuat kata-kata terpanjang sepanjang 25 karakter. Saya menganggap Anda memiliki daftar kata yang diterima. Atas asumsi itu saya sarankan Anda mencoba sesuatu seperti ini:
Ini akan membuat peta pada setiap ubin dengan informasi bagaimana ubin ini terhubung dengan kata-kata di sekitarnya dalam kisi. Ketika kolom atau baris dipindahkan periksa semua ubin yang telah, atau berdekatan dengan gerakan dan hitung ulang informasinya. Ketika Anda menemukan kata, dan tidak ada ubin lagi dapat ditambahkan ke kata itu; Singkirkan. Saya tidak yakin apakah ini akan lebih cepat, itu benar-benar bermuara pada berapa banyak kata yang setengah dibuat. Manfaat untuk ini adalah bahwa pengguna kemungkinan besar mencoba membuat kata dari kata setengah lengkap di papan tulis. Dengan menyimpan semua kata ini tersimpan, mudah untuk memeriksa apakah suatu kata telah selesai.
sumber