Algoritma untuk Menentukan Tic Tac Toe Game Over
I've ditulis permainan tic-tac-toe di pulau Jawa, dan saya saat ini metode penentuan akhir dari permainan account untuk mengikuti skenario yang mungkin untuk permainan menjadi lebih:
- Papan penuh, dan tidak ada pemenang yang belum menyatakan: Permainan imbang.
- Salib telah menang.
- Lingkaran telah memenangkan.
Sayangnya, untuk melakukannya, ia membaca melalui sebuah set standar dari skenario ini dari sebuah tabel. Ini isn't selalu buruk mengingat bahwa hanya ada 9 ruang pada papan, dan dengan demikian meja agak kecil, tapi apakah ada yang lebih baik algoritmik cara untuk menentukan jika permainan berakhir? Penentuan apakah seseorang telah menang atau tidak adalah daging dari masalah, karena memeriksa jika 9 ruang yang penuh sepele.
Tabel metode yang mungkin bisa menjadi solusi, tapi jika tidak, apa? Juga, bagaimana jika dewan tidak ukuran n=9
? Bagaimana jika itu adalah jauh lebih besar papan, mengatakan n=16
, n=25
, dan sebagainya, yang menyebabkan jumlah berturut-turut ditempatkan item untuk menang untuk x=4
, x=5
, dll? Algoritma umum untuk digunakan untuk semua n = { 9, 16, 25, 36 ... }
?
Anda tahu pemenang bergerak hanya bisa terjadi setelah X atau O telah membuat mereka yang paling baru-baru ini bergerak, sehingga anda hanya dapat mencari baris/kolom dengan opsional diag yang terdapat di dalam yang bergerak untuk membatasi pencarian anda ruang ketika mencoba untuk menentukan pemenang papan. Juga karena ada jumlah tetap bergerak dalam menggambar tic-tac-toe game setelah langkah terakhir dilakukan jika itu't pemenang bergerak's secara default imbang permainan.
edit: kode ini adalah untuk n dengan n papan dengan n berturut-turut untuk menang (3x3 papan requries 3 berturut-turut, dll)
edit: ditambahkan kode untuk memeriksa anti diag, aku tak't mengetahui non loop cara untuk menentukan apakah titik itu pada anti diag jadi thats mengapa langkah itu hilang
anda dapat menggunakan magic square http://mathworld.wolfram.com/MagicSquare.html jika setiap baris, kolom, atau diag menambahkan hingga 15 maka seorang pemain telah memenangkan.
Hal ini mirip dengan Osama ALASSIRY's answer, tetapi perdagangan yang konstan-ruang dan linear-waktu linear-ruang dan konstan-waktu. Artinya, ada's tidak ada perulangan setelah inisialisasi.
Menginisialisasi sepasang
(0,0)
untuk setiap baris, setiap kolom, dan dua diagonal (diagonal & anti-diagonal). Pasangan ini mewakili akumulasi(sum,sum)
dari potongan-potongan di baris yang sesuai, kolom, atau diagonal, di manaKetika seorang pemain menempatkan sepotong, update baris yang sesuai pasangan, kolom pasangan, dan diagonal pasang (jika pada diagonal). Jika ada yang baru diperbarui baris, kolom, atau diagonal sepasang sama dengan baik
(n,0)
atau(0,n)
maka A atau B yang menang, masing-masing.Asymptotic analisis:
Untuk penggunaan memori, anda menggunakan
4*(n+1)
bilangan bulat.Latihan: anda Dapat melihat bagaimana untuk menguji hasil imbang di O(1) waktu per-pindah? Jika demikian, anda dapat mengakhiri permainan awal yang menarik.
Bagaimana tentang hal ini pseudocode:
Setelah pemain meletakkan bagian pada posisi (x,y):
I'a menggunakan sebuah array dari char [n,n], dengan O,X, dan ruang kosong.
Heres solusi saya bahwa saya menulis untuk sebuah proyek, saya'm bekerja di dalam javascript. Jika anda don't pikiran memori biaya dari beberapa array itu's mungkin yang tercepat dan paling sederhana solusi anda'll menemukan. Ini mengasumsikan anda tahu posisi terakhir bergerak.
Saya hanya menulis ini untuk saya pemrograman C kelas.
Saya posting ini karena tidak ada contoh-contoh lain di sini akan bekerja dengan berbagai ukuran persegi panjang grid, dan jumlah N-in-a-baris berturut-tanda untuk menang.
Anda'll menemukan algoritma saya, seperti itu, di
checkWinner()
fungsi. Itu doesn't menggunakan angka ajaib atau sesuatu yang mewah untuk cek pemenang, itu hanya menggunakan empat untuk loop - kode baik berkomentar agar saya'll membiarkannya berbicara untuk dirinya sendiri saya kira.Jika papan n &kali; n kemudian ada n baris, n kolom, dan 2 diagonal. Periksa masing-masing untuk semua-X's atau all-O's untuk menemukan pemenang.
Jika hanya dibutuhkan x < n kotak berturut-turut untuk menang, maka itu's sedikit lebih rumit. Solusi yang paling jelas adalah untuk memeriksa setiap x &kali; x square untuk pemenang. Berikut ini's beberapa kode yang menunjukkan bahwa.
(I didn't sebenarnya tes ini *batuk*, tapi itu did mengkompilasi pada percobaan pertama, yay aku!)
Saya don't tahu Jawa yang baik, tapi aku tahu C, jadi saya mencoba adk's magic square idea (bersama dengan Hardwareguy's pencarian restriction).
Mengkompilasi dan tes dengan baik.
Itu menyenangkan, terima kasih!Sebenarnya, berpikir tentang hal itu, anda don't perlu sihir persegi, hanya dihitung untuk setiap baris/kolom/diagonal. Ini adalah sedikit lebih mudah daripada generalisasi persegi ajaib untuk
n
&kali;n
matrik, karena anda hanya perlu hitungan ken
.Saya ditanya pertanyaan yang sama di salah satu wawancara saya. Pikiran saya: Menginisialisasi matriks dengan 0. Tetap 3 array 1)sum_row (size n) 2) sum_column (size n) 3) diagonal (size 2)
Untuk masing-masing bergerak dengan (X) pengurangan kotak value dengan 1 dan untuk setiap langkah (0) increment dengan 1. Pada setiap titik jika baris/kolom/diagonal yang telah dimodifikasi di saat ini bergerak memiliki jumlah yang baik -3 atau +3 berarti seseorang telah memenangkan permainan. Untuk menarik kita dapat menggunakan pendekatan di atas untuk menjaga moveCount variabel.
Apakah anda pikir saya kehilangan sesuatu ?
Edit: yang Sama dapat digunakan untuk nxn matrix. Jumlah yang harus menjadi +3 atau -3.
non-loop cara untuk menentukan apakah titik itu pada anti diag:
Saya terlambat partai, tapi saya ingin menunjukkan salah satu manfaat yang saya temukan untuk menggunakan magic square, yaitu bahwa hal itu dapat digunakan untuk mendapatkan referensi ke alun-alun yang akan menyebabkan menang atau rugi pada giliran berikutnya, bukan hanya digunakan untuk menghitung ketika permainan berakhir.
Mengambil ini magic square:
Pertama, mendirikan sebuah
nilai
array yang bertambah setiap kali bergerak dibuat. Lihat jawaban untuk rincian. Sekarang jika kita bermain secara ilegal X dua kali berturut-turut di [0,0] dan [0,1], makanilai
array terlihat seperti ini:Dan dewan terlihat seperti ini:
Kemudian, yang harus kita lakukan dalam rangka untuk mendapatkan referensi ke alun-alun untuk menang/blok adalah:
Dalam kenyataannya, pelaksanaan memerlukan beberapa trik tambahan, seperti penanganan bernomor kunci (JavaScript), tapi saya menemukan itu cukup sederhana dan menikmati rekreasi matematika.
Saya membuat beberapa optimasi di row, col, diagonal pemeriksaan. Terutama diputuskan dalam pertama nested loop jika kita perlu memeriksa kolom tertentu atau diagonal. Jadi, kita menghindari memeriksa kolom atau diagonal menghemat waktu. Hal ini membuat dampak besar ketika ukuran papan yang lebih banyak dan jumlah yang signifikan dari sel-sel yang tidak diisi.
Berikut ini adalah kode java untuk itu.
Saya suka algoritma ini karena menggunakan 1x9 vs 3x3 representasi dari papan.
Berikut ini adalah solusi saya menggunakan 2 dimensi array:
Pilihan lain: membuat tabel dengan kode. Hingga simetri, hanya ada tiga cara untuk menang: ujung baris, baris tengah, atau diagonal. Mengambil orang-orang tiga dan berputar mereka di sekitar setiap cara yang mungkin:
Simetri-simetri ini dapat memiliki lebih banyak kegunaan dalam permainan-bermain kode: jika anda mendapatkan ke papan anda've sudah melihat diputar versi, anda hanya dapat mengambil nilai yang di-cache atau cache terbaik berpindah dari yang satu (dan unrotate kembali). Hal ini biasanya jauh lebih cepat daripada mengevaluasi permainan subtree.
(Membalik kiri dan kanan dapat membantu dengan cara yang sama; itu't dibutuhkan di sini karena mengatur rotasi dari pola kemenangan adalah cermin-simetris.)
Berikut ini adalah solusi saya datang dengan, ini menyimpan simbol-simbol sebagai karakter dan menggunakan char's int nilai untuk mengetahui apakah X atau O telah memenangkan (lihat Wasit's kode)
Juga di sini adalah unit saya tes untuk memvalidasi itu benar-benar bekerja
Solusi lengkap: https://github.com/nashjain/tictactoe/tree/master/java
Bagaimana pendekatan berikut untuk 9 slot? Menyatakan 9 integer variabel untuk 3x3 matrix (a1,a2....a9) dimana a1,a2,a3 mewakili baris-1 dan a1,a4,a7 akan membentuk kolom-1 (anda mendapatkan ide). Gunakan '1' untuk menunjukkan Pemain-1 dan '2' untuk menunjukkan Pemain-2.
Ada 8 kemungkinan menang kombinasi: Win-1: a1+a2+a3 (jawaban bisa 3 atau 6 berdasarkan pada pemain mana yang tidak) Menang-2: a4+a5+a6 Win-3: a7+a8+a9 Win-4: a1+a4+a7 .... Win-7: a1+a5+a9 Win-8: a3+a5+a7
Sekarang kita tahu bahwa jika pemain satu salib a1 maka kita perlu mengevaluasi kembali jumlah dari 3 variabel: Win-1, Win-4 dan Win-7. Mana 'Win-?' variabel mencapai 3 atau 6 pertama memenangkan permainan. Jika Menang-1 variabel mencapai 6 pertama maka Pemain 2 menang.
Saya mengerti bahwa solusi ini tidak scalable dengan mudah.
Ini adalah cara yang sangat sederhana untuk memeriksa.
Jika anda memiliki asrama bidang 5*5 untuk examle, saya menggunakan metode pemeriksaan:
Konstanta waktu O(8), rata-rata 4 pendek DAN's. Pemain = nomor pendek. Perlu pemeriksaan tambahan untuk memastikan langkah ini berlaku.