Saya mencoba untuk menulis pemecah dalam C # .NET untuk permainan yang dikenal sebagai Flowerz. Untuk referensi Anda, Anda dapat memainkannya di MSN, di sini: http://zone.msn.com/gameplayer/gameplayer.aspx?game=flowerz . Saya menulisnya untuk bersenang-senang, bukan untuk semua jenis tugas atau pekerjaan apa pun yang terkait. Karena itu, satu-satunya batasan adalah komputer saya (intel i7 core, dengan 8GB RAM). Itu tidak perlu dijalankan di tempat lain, sejauh yang saya ketahui.
Singkatnya, aturannya seperti ini:
- Ada antrian penuh dengan bunga berwarna. Panjangnya sewenang-wenang
- Antrian tidak dapat dipengaruhi
- Antrian dibuat di awal level
- Bunga memiliki satu atau dua warna.
- Jika ada dua warna, maka ada warna luar, dan warna dalam. Dalam kasus dua warna, warna luar digunakan untuk pencocokan.
- Jika ada kecocokan, maka warna luar menghilang dan bunga sekarang menjadi bunga warna tunggal dengan warna yang sama dengan bunga dalam
- Tujuan permainan ini adalah untuk membuat pertandingan tiga (atau lebih) dengan warna yang sama
- Ketika bunga dengan warna tunggal adalah bagian dari korek api, bunga itu dihilangkan dari lapangan bermain, menciptakan ruang kosong
- Anda dapat mencocokkan bunga warna tunggal dengan warna luar bunga dua warna. Dalam hal ini, warna bunga tunggal menghilang, warna luar bunga dua warna menghilang dan warna bagian dalam tetap ada
- Anda memenangkan ronde ketika antrian kosong dan setidaknya ada satu ruang kosong yang tersisa
- Pencocokan Cascading dimungkinkan. Kaskade adalah ketika tiga (atau lebih) bunga luar menghilang, dan ketika warna bagian dalam mereka membentuk rantai 3 (atau lebih banyak bunga) lainnya.
- Lapangan bermain selalu 7x7
- Beberapa ruang di lapangan ditutupi oleh batu
- Anda tidak dapat menempatkan bunga di atas batu
- Antrian juga dapat berisi sekop yang dapat Anda gunakan untuk memindahkan bunga yang ditempatkan ke ruang kosong
- Anda harus menggunakan sekop, tetapi Anda tidak benar-benar harus memindahkan bunga: sangat legal untuk meletakkannya kembali dari tempat asalnya.
- Antrian juga dapat berisi kupu-kupu berwarna. Saat Anda menggunakan kupu-kupu ini pada bunga, maka bunga itu mendapatkan warna kupu-kupu
- Menerapkan kupu-kupu pada bunga dengan dua warna, menghasilkan bunga hanya mendapatkan satu warna, yaitu kupu-kupu
- Anda dapat membuang kupu-kupu di ruang kosong atau bunga yang sudah memiliki warna ini
- Membersihkan lapangan tidak memenangkan pertandingan
Tujuan dari solver itu sederhana: temukan cara untuk mengosongkan antrian, dengan sebanyak mungkin ruang sisa di lapangan bermain. Pada dasarnya, AI memainkan game untuk saya. Output dari solver adalah daftar dengan gerakan yang ditemukannya. Saya tidak tertarik dengan skor, tetapi bertahan selama mungkin, maka saya tertarik pada gerakan yang meninggalkan ruang terbuka sebanyak mungkin.
Tak perlu dikatakan, ruang pencarian tumbuh dengan cepat semakin besar antrian yang didapat, sehingga kekuatan kasar keluar dari pertanyaan. Antrian dimulai pada 15, dan tumbuh dengan 5 setiap dua atau tiga level, jika saya ingat benar. Dan, tentu saja, menempatkan bunga pertama pada (0,0) dan yang kedua pada (0,1) berbeda dari menempatkan bunga pertama pada (1,0) dan bunga kedua pada (0,0), terutama ketika lapangan sudah diisi dengan bunga dari babak sebelumnya. Keputusan sederhana seperti itu dapat membuat perbedaan dalam membuatnya atau tidak.
Pertanyaan yang saya miliki adalah sebagai berikut:
- Masalah apa ini? (pikirkan penjual keliling, ransel, atau masalah kombinatorial lainnya). Mengetahui ini bisa membuat Google-fu saya sedikit lebih baik.
- Algoritme apa yang bisa memberi saya hasil yang baik, cepat?
Mengenai yang terakhir: Pada awalnya, saya mencoba untuk menulis algoritma heuristik saya sendiri (pada dasarnya: bagaimana saya menyelesaikannya, jika saya tahu antrian?), Tetapi itu menghasilkan banyak kasus tepi dan pencocokan skor yang mungkin saya lewatkan.
Saya sedang berpikir untuk menggunakan algoritma genetika (karena saya setidaknya tahu bagaimana menggunakannya ...), tapi saya mengalami beberapa masalah dalam memutuskan representasi biner dari papan. Lalu ada masalah crossover, tapi itu bisa diselesaikan dengan operator crossover yang dipesan atau jenis operasi serupa.
Dugaan saya adalah bahwa pemecah harus selalu mengetahui konfigurasi papan dan antrian itu mencoba mengosongkan.
Saya tahu beberapa algoritma heuristik lain seperti jaringan saraf dan sistem logika fuzzy, tetapi saya tidak memiliki pengalaman untuk mengetahui mana yang paling cocok untuk diterapkan, atau jika ada yang lain yang lebih cocok untuk tugas yang dihadapi.
Jawaban:
Pada pandangan pertama , ini bagi saya merupakan masalah pencarian agen tunggal . Yaitu: Anda memiliki satu agen ("pemain" AI). Ada status permainan yang mewakili kondisi papan permainan dan antrian, dan Anda memiliki fungsi penerus yang dapat menghasilkan status baru dari kondisi tertentu.
Ada juga kriteria tujuan yang memberi tahu Anda ketika negara bagian adalah negara "terpecahkan". Dan biaya jalur - biaya memajukan ke keadaan tertentu (selalu "1 bergerak" dalam kasus ini).
Salah satu puzzle prototipikal dari jenis ini adalah 15 Puzzle . Dan cara khas untuk mengatasinya adalah dengan pencarian informasi - misalnya, pencarian heuristik klasik A * dan variannya.
Namun ada masalah dengan pendekatan ini pada pandangan pertama. Algoritma seperti A * dirancang untuk memberi Anda jalur terpendek ke tujuan (misalnya: jumlah gerakan terkecil). Dalam kasus Anda, jumlah bergerak selalu tetap - tidak ada jalur terpendek - sehingga pencarian heuristik hanya akan memberikan sebuah jalan untuk sebuah pertandingan selesai.
Yang Anda inginkan adalah urutan gerakan yang memberi Anda kondisi permainan yang paling baik diselesaikan.
Jadi yang harus Anda lakukan adalah membalikkan masalahnya sedikit. Alih-alih papan permainan menjadi "negara", urutan gerakan menjadi "negara". (Yaitu: Tempatkan item dalam antrian di posisi "D2, A5, C7, B3, A3, ...")
Ini berarti kami tidak terlalu peduli bagaimana status tersebut dihasilkan. Dewan itu sendiri bersifat insidentil, hanya diperlukan untuk mengevaluasi kualitas suatu negara.
Ini mengubah masalah menjadi masalah optimisasi , yang dapat diselesaikan dengan algoritma pencarian lokal (yang pada dasarnya berarti membuat status di sekitar status yang diberikan, dan memilih status terbaik, tanpa peduli tentang jalur antara status.)
Teka-teki prototipe dari jenis ini adalah Puzzle Delapan Ratu .
Di kelas masalah ini, Anda mencari ruang keadaan untuk menemukan solusi yang baik, di mana "baik" dievaluasi oleh fungsi objektif (juga disebut fungsi evaluasi atau, untuk algoritma genetika, fungsi kebugaran ).
Untuk masalah Anda, fungsi objektif mungkin mengembalikan nilai antara 0 dan N, untuk jumlah item dalam antrian yang digunakan sebelum mencapai keadaan gagal (di mana N adalah panjang antrian). Dan, jika tidak, nilai N + M, di mana M adalah jumlah ruang kosong yang tersisa di papan setelah antrian kosong. Dengan demikian - semakin tinggi nilainya, solusi "lebih baik secara objektif".
(Perlu dicatat, pada titik ini, bahwa Anda harus mengoptimalkan omong kosong dari kode yang menjalankan permainan - yang mengubah keadaan menjadi papan jadi yang dapat digunakan untuk fungsi tujuan.)
Adapun contoh-contoh algoritma pencarian lokal : Pola dasar adalah pencarian mendaki bukit yang mengambil keadaan tertentu, memutasinya, dan bergerak menuju keadaan berikutnya yang memberikan hasil yang lebih baik.
Jelas ini bisa macet di maksimum lokal (dan sejenisnya). Dalam bentuk ini disebut pencarian lokal serakah . Ada banyak variasi untuk mengatasi hal ini dan masalah lainnya ( Wikipedia telah Anda bahas ). Beberapa di antaranya (misalnya: pencarian balok lokal ) melacak beberapa negara sekaligus.
Satu variasi khusus tentang ini adalah algoritma genetika ( Wikipedia ). Langkah-langkah dasar untuk algoritma genetika adalah:
Sebuah solusi algoritma genetika merasa seperti itu mungkin sesuai untuk masalah Anda - dengan beberapa penyesuaian. Kesulitan terbesar yang saya lihat adalah bahwa, dengan representasi string di atas, Anda akan menemukan bahwa mengganti bagian ekor negara dengan bagian depan yang sangat berbeda cenderung menghasilkan keadaan "mati" (karena gerakan yang saling bertentangan antara kedua bagian, akibatnya adalah dalam skor kebugaran rendah).
Mungkin mungkin untuk mengatasi masalah ini. Satu ide yang muncul di benak adalah membuatnya lebih mungkin bagi negara-negara dengan bagian depan yang serupa untuk menjadi pasangan pengembangbiakan. Ini bisa sesederhana menyortir populasi negara berkembang, sebelum memasangkannya. Mungkin juga membantu untuk secara bertahap memindahkan posisi yang mungkin dari crossover, dari awal hingga akhir string, karena jumlah generasi meningkat.
Dimungkinkan juga untuk menghadirkan representasi gerakan dalam kondisi yang lebih tahan (bahkan mungkin sepenuhnya kebal) untuk menghadapi kondisi kegagalan "kuadrat penuh". Mungkin mewakili gerakan sebagai koordinat relatif dari langkah sebelumnya. Atau setelah bergerak pilih ruang kosong terdekat ke posisi yang diberikan.
Seperti dengan semua masalah AI non-sepele seperti ini, itu akan memerlukan beberapa bermain-main yang signifikan.
Dan, seperti yang saya sebutkan sebelumnya, tantangan utama lainnya hanyalah mengoptimalkan fungsi objektif Anda. Dengan mempercepat ini, Anda dapat mencari ruang dalam jumlah besar, dan mencari solusi untuk permainan dengan antrian yang lebih panjang.
Untuk jawaban ini, terutama untuk mendapatkan semua terminologi yang benar, saya harus menggali buku teks AI universitas saya, "Inteligensi Buatan: Pendekatan Modern" oleh Russell dan Norvig. Tidak yakin apakah itu "baik" (saya tidak memiliki teks AI lain untuk membandingkannya), tapi itu tidak buruk. Setidaknya itu cukup besar;)
sumber
Kategorisasi
Jawabannya tidak mudah. Teori gim memiliki beberapa klasifikasi untuk gim, tetapi tampaknya tidak ada kecocokan 1: 1 untuk gim tersebut dengan teori khusus. Ini adalah bentuk khusus dari masalah kombinatorial.
Ini bukan penjual keliling, yang akan memutuskan untuk memesan di mana Anda mengunjungi "node" dengan biaya untuk mencapai node berikutnya dari yang terakhir. Anda tidak dapat memesan ulang antrian, Anda juga tidak harus menggunakan semua bidang pada peta.
Knapsack tidak cocok karena beberapa bidang menjadi kosong saat memasukkan beberapa item ke dalam "knapsack". Jadi itu mungkin beberapa bentuk perpanjangan dari itu, tetapi kemungkinan besar algoritma tidak akan berlaku karena ini.
Wikipedia memberikan beberapa petunjuk tentang kategorisasi di sini: http://en.wikipedia.org/wiki/Game_theory#Types_of_games
Saya akan mengategorikannya sebagai "masalah kontrol optimal diskrit-waktu" ( http://en.wikipedia.org/wiki/Optimal_control ), tetapi saya tidak berpikir ini akan membantu Anda.
Algoritma
Jika Anda benar-benar mengetahui antrean lengkap, Anda dapat menerapkan algoritma penelusuran pohon. Seperti yang Anda katakan, kompleksitas masalah tumbuh sangat cepat dengan panjang antrian. Saya sarankan untuk menggunakan algoritme seperti "Pencarian kedalaman-pertama (DFS)", yang tidak memerlukan banyak memori. Karena skor tidak masalah bagi Anda, Anda bisa berhenti setelah menemukan solusi pertama. Untuk memutuskan cabang mana yang akan dicari terlebih dahulu, Anda harus menerapkan heuristik untuk pemesanan. Itu berarti Anda harus menulis fungsi evaluasi (misalnya: jumlah bidang kosong; semakin canggih ini, semakin baik), yang memberikan skor untuk membandingkan langkah selanjutnya yang paling menjanjikan.
Maka Anda hanya perlu bagian-bagian berikut:
Berikut ini adalah implementasi referensi yang tidak lengkap untuk pencarian mendalam-pertama:
Kode ini tidak diverifikasi untuk berfungsi, juga tidak dapat dikompilasi atau diselesaikan. Tapi itu harus memberi Anda ide bagaimana melakukannya. Pekerjaan yang paling penting adalah fungsi evaluasi. Semakin canggih, semakin salah "mencoba" algoritma akan mencoba (dan harus membatalkan) nanti. Ini sangat mengurangi kompleksitas.
Jika ini terlalu lambat, Anda juga dapat mencoba menerapkan beberapa metode permainan dua orang sebagai HashTables. Untuk itu Anda harus menghitung kunci hash (iteratif) untuk setiap status game yang Anda evaluasi dan tandai status yang tidak mengarah ke solusi. Misalnya setiap kali sebelum metode Pencarian () mengembalikan "null" entri HashTable harus dibuat dan ketika memasukkan Pencarian () Anda akan memeriksa apakah Negara ini telah mencapai sejauh ini tanpa hasil positif dan jika demikian mengembalikan "null" tanpa investigasi lebih lanjut. Untuk ini, Anda akan memerlukan tabel hash besar dan harus menerima "tabrakan hash" yang dapat menyebabkan Anda mungkin tidak menemukan solusi yang ada, tetapi yang sangat tidak mungkin, jika fungsi hash Anda cukup baik dan meja Anda cukup besar (ini risiko risiko yang dapat dihitung).
Saya pikir tidak ada algoritma lain untuk menyelesaikan masalah ini (seperti yang dijelaskan oleh Anda) lebih efisien, dengan asumsi fungsi evaluasi Anda optimal ...
sumber