GNU Prolog, 493 bytes
z(_,[_,_]).
z(F,[A,B,C|T]):-call(F,A,B,C),z(F,[B,C|T]).
i([],[],[],[]).
i([H|A],[I|B],[J|C],[H-I-J|T]):-i(A,B,C,T).
c(A/_-B/_-C/_,D/_-_/T-E/_,F/_-G/_-H/_):-T#=A+B+C+D+E+F+G+H.
r(A,B,C):-i(A,B,C,L),z(c,L).
q(63,V):-var(V).
q(42,1/_).
q(X,0/Y):-Y#=X-48.
l([],[0/_]).
l([H|T],[E|U]):-q(H,E),l(T,U).
p([],[[0/_,0/_]],0).
p([],[[0/_|T]],N):-M#=N-1,p([],[T],M).
p([H|T],[[0/_|E]|U],N):-p(T,U,N),l(H,E).
m([H|A],B):-length(H,N),p([],[R],N),p([H|A],M,N),z(r,[R|M]),p(B,M,N).
s(A):-setof(B,m(A,B),[_]).
Predikat tambahan yang mungkin berguna untuk pengujian (bukan bagian dari pengiriman):
d([]).
d([H|T]):-format("~s~n",[H]),d(T).
Prolog jelas merupakan bahasa yang tepat untuk menyelesaikan tugas ini dari sudut pandang praktis. Program ini cukup banyak hanya menyatakan aturan Minesweeper dan memungkinkan pemecah kendala GNU Prolog memecahkan masalah dari sana.
z
dan i
adalah fungsi utilitas ( z
melakukan semacam operasi lipatan tetapi pada himpunan tiga elemen yang berdekatan, bukan 2; i
mentranspos 3 daftar elemen n ke dalam daftar n 3-tupel). Kami secara internal menyimpan sel sebagai , di mana x adalah 1 untuk tambang dan 0 untuk bukan tambang, dan y adalah jumlah tambang yang berdekatan; mengungkapkan kendala ini di papan tulis. berlaku untuk setiap baris papan; dan jadi memeriksa untuk melihat apakah papan yang valid.x/y
c
r
c
z(r,M)
M
Sayangnya, format input yang diperlukan untuk membuat pekerjaan ini secara langsung tidak masuk akal, jadi saya juga harus menyertakan parser (yang mungkin menyumbang lebih banyak kode daripada mesin aturan aktual, dan sebagian besar waktu yang dihabiskan untuk debugging; mesin aturan Minesweeper cukup banyak bekerja pertama kali, tetapi parser itu penuh dengan thinkos). q
mengkonversi sel tunggal antara kode karakter dan format kami . mengonversi satu baris papan (meninggalkan satu sel yang diketahui bukan tambang, tetapi dengan sejumlah ranjau yang berdekatan, di setiap tepi garis sebagai perbatasan);x/y
l
p
mengkonversi seluruh papan (termasuk batas bawah, tetapi tidak termasuk yang paling atas). Semua fungsi ini dapat dijalankan baik maju atau mundur, sehingga dapat menguraikan dan mencetak papan. (Ada beberapa yang mengganggu dengan argumen ketiga p
, yang menentukan lebar papan; ini karena Prolog tidak memiliki jenis matriks, dan jika saya tidak membatasi papan menjadi persegi panjang, program akan masuk ke loop tak terbatas mencoba semakin perbatasan yang lebih luas di sekitar papan.)
m
adalah fungsi pemecahan Minesweeper utama. Ini mem-parsing string input, menghasilkan papan dengan perbatasan yang benar (melalui menggunakan kasus rekursif p
untuk mengkonversi sebagian besar papan, kemudian memanggil kasing langsung untuk menghasilkan perbatasan atas, yang memiliki struktur yang sama dengan perbatasan bawah). Maka itu panggilanz(r,[R|M])
untuk menjalankan mesin aturan Minesweeper, yang (dengan pola panggilan ini) menjadi generator yang hanya menghasilkan papan yang valid. Pada titik ini, dewan masih dinyatakan sebagai serangkaian kendala, yang berpotensi canggung bagi kita; kita mungkin dapat memiliki satu set kendala yang dapat mewakili lebih dari satu papan. Selain itu, kami belum menentukan di mana saja bahwa setiap kotak berisi paling banyak satu tambang. Dengan demikian, kita perlu secara eksplisit "menciutkan bentuk gelombang" dari setiap kotak, yang mengharuskannya untuk menjadi tambang (tunggal) atau bukan tambang, dan cara termudah untuk melakukannya adalah dengan menjalankannya melalui parser mundur ( var(V)
pada kasing q(63,V)
dirancang untuk mencegah ?
kasing mundur, dan dengan demikian merentang papan memaksa agar diketahui sepenuhnya). Akhirnya, kami mengembalikan papan yang diurai darim
; m
dengan demikian menjadi generator yang mengambil papan yang sebagian tidak dikenal dan menghasilkan semua papan yang diketahui konsisten dengannya.
Itu benar-benar cukup untuk menyelesaikan Minesweeper, tetapi pertanyaannya secara eksplisit meminta untuk memeriksa apakah ada satu solusi, daripada menemukan semua solusi. Karena itu, saya menulis predikat tambahan s
yang hanya mengubah generator m
menjadi satu set, dan kemudian menyatakan bahwa set tersebut memiliki tepat satu elemen. Ini berarti bahwa s
akan mengembalikan kebenaran ( yes
) jika memang ada satu solusi, atau falsey ( no
) jika ada lebih dari satu atau kurang dari satu.
d
bukan bagian dari solusi, dan tidak termasuk dalam bytecount; itu adalah fungsi untuk mencetak daftar string seolah-olah itu adalah matriks, yang memungkinkan untuk memeriksa papan yang dihasilkan oleh m
(secara default, GNU Prolog mencetak string sebagai daftar kode ASCII, karena itu memperlakukan keduanya secara sinonim; format ini cukup sulit dibaca). Ini berguna selama pengujian, atau jika Anda ingin menggunakan m
sebagai pemecah Minesweeper praktis (karena menggunakan pemecah kendala, ini sangat efisien).
2?
tidak memiliki solusi, yang berarti tidak dapat berasal dari permainan Minesweeper yang sebenarnya. Oleh karena itu tidak dianggap sebagai "papan Minesweeper" ... ya?)