Hari ini saya tiba-tiba mendapat ide untuk membuat permainan puzzle yang cerdas untuk pacar saya.
Fungsi-fungsi ini perlu diwujudkan, yang pertama adalah menyesuaikan gambar, dan yang kedua adalah menyesuaikan grid. Tentu saja, yang saya pikirkan di awal adalah 3*3 4*4 5*5, dan saya tidak menggunakannya. kotak seperti 3*5.
Yang ketiga adalah mewujudkan fungsi puzzle otomatis. Saya yakin semua orang tahu bahwa wanita tidak pandai bermain game, jadi fungsi puzzle otomatis ini diperlukan.
Saya tidak akan menulis tentang suspensi dan peringkat lainnya!
Sekarang pertanyaan kuncinya muncul. Tampaknya persyaratan untuk mewujudkan fungsi puzzle otomatis agak tinggi! Apakah komputer bisa seperti manusia dan hanya bisa:
Mari kita ke intinya dulu
Teka-teki gambar sebenarnya hanyalah masalah pengaturan:
Ada pengertian permutasi : Pada susunan 1, 2,...,n, jika posisi depan dan belakang suatu pasangan bilangan berurutan terbalik, yaitu bilangan depan lebih besar dari bilangan belakang, maka mereka disebut urutan terbalik. Jumlah total urutan terbalik dalam suatu permutasi disebut nomor urutan terbalik dari permutasi tersebut. Susunan yang bilangan kebalikannya merupakan bilangan genap disebut susunan genap; susunan yang bilangan kebalikannya ganjil disebut susunan ganjil. Misalnya, pada 2431, 21, 43, 41, dan 31 berada dalam urutan terbalik, dan urutan terbaliknya adalah 4, yang merupakan susunan genap.
Berikut definisi lainnya: Dengan menukar dua bilangan dalam suatu permutasi, paritas permutasi tersebut berubah.
Definisi di atas semuanya diambil dari "Aljabar Lanjutan".
Susunan puzzle haruslah susunan yang rata. Ini dapat ditemukan di referensi saya.
Jadi beginilah cara teka-teki saya diimplementasikan!
Akan menulis nanti
Referensi: http://en.wikipedia.org/wiki/Fifteen_puzzle
Teka-teki otomatis:
Pertama-tama, harus ada aturan tertentu untuk teka-teki otomatis. Menurut pengalaman teka-teki saya, untuk menyelesaikan teka-teki, area yang berbeda menggunakan aturan teka-teki yang berbeda, jadi:
Peta grid saya dibagi menjadi 4 area (jika peta grid memiliki n*n grid)
Area pertama: rentang koordinat x 0 hingga n-2, rentang koordinat y 0 hingga n-3
Area kedua: koordinat x n-1, rentang koordinat y 0 hingga n-3
Daerah ketiga: rentang koordinat x 0 sampai n-3, rentang koordinat y n-2 dan n-1
Area keempat: rentang koordinat x n-2 hingga n-1, rentang koordinat y n-2 dan n-1 yaitu empat sel terakhir
Setiap area dapat diselesaikan sesuai aturan area masing-masing.
Puzzle.java
import java.io.FileNotFoundException;import java.io.PrintStream;import java.io.UnsupportedEncodingException;import java.util.Random; Puzzle { private long step = 0; [][] puzzle; private int resetBlock = 0;// //Posisi blok kosong private int whiteBlockX; whiteBlockY; //Koordinat blok yang sedang dipindahkan adalah blok reset private int resetBlockX; private int resetBlockY; n = n; init(); } pribadi kekosongan init() { teka-teki = int baru[n][n]; y++) { untuk (int x = 0; x < n; x++) { puzzle[y][x] = x + y * n; } whiteBlockX = n-1; whiteBlockY = int kali = 100; // Jumlah pengacakan harus genap. Random random = new Random(); while (times > 0) { int x0 = random.nextInt(n); random.nextInt(n); int x1 = random.nextInt(n); int y1 = random.nextInt(n); if (x0 != x1 && y0!=y1) {// Dijamin pengurutan merata if((x0 = =n-1&&y0==n-1)||(x1==n-1&&y1==n-1)){//Yang terakhir tidak digantilanjutkan } kali--; int t = teka-teki[x0][y0]; teka-teki[x0][y0] = teka-teki[x1][y1]; teka-teki[x1][y1] = t; p = {{22,9 ,1 ,5 ,0 ,25 },{// 33,23,20,26,18,21},{// 6 ,16,17,10,34,31},{// 19,28,32,7 ,3 ,2},{// 11,4 ,12,14,27,24},{// 15,29 ,30,8 ,13,35}};// puzzle = p; } public void sort(){ untuk (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {//Yang terakhir kosong, } else { reset(x, y ) ; } } } } } //Reset blok ke posisi target private void reset(int targetX, int targetY) { //Temukan posisi blok reset saat ini initResetBlock(targetX, targetY); Urutan resetnya dari kiri ke kanan, atas ke bawah* Cara pergerakannya adalah naik dulu, lalu ke kiri* Blok reset saat ini, posisi yang ingin direset dapat dibagi menjadi empat situasi* 1. Tidak di baris paling kanan atau dua baris terbawah * 2. Baris paling kanan x=n-1, tetapi bukan dua baris terbawah; * 3. Dua baris terbawah y=n-2, tetapi bukan baris paling kanan * 4. Genap baris paling kanan juga merupakan dua baris terbawah OK*/ if(targetX < n-1 && targetY < n-2){ if(resetBlockX==targetX&&resetBlockY==targetY){//Posisi sudah benar tanpa berpindah kembali;//Keluar dari rekursi} resetBlockToTarget(targetX, targetY } lain jika( targetX==n-1 && targetY < n-2){//Kasus kedua if(resetBlockX==targetX&&resetBlockY==targetY){//Posisinya benar tanpa berpindah kembali;//Keluar dari rekursi} reset2(targetX, targetY); n- 2 && targetY == n-2){// isPrint=true; reset3(targetX); resetBlockToTarget(n-2, n-2); if(whiteBlockX<n-1){ whiteBlockRight(); } if(whiteBlockY<n-1){ whiteBlockDown(); -1){ kembali; } } setel ulang(targetX, targetY);//rekursi} kekosongan pribadi initResetBlock(int targetX,int targetY){ resetBlock = targetX + targetY * n; untuk (int y = 0; y < n; y++) { untuk (int x = 0; x < n; x++) { if (puzzle[y][x] == resetBlock) {// x, y adalah posisi blok reset resetBlockX = x; resetBlockY = y; break; if(targetX>=2){// } initResetBlock(targetX, n-1); resetBlockToTarget(targetX+1, n-2); : while (!(whiteBlockX==targetX && whiteBlockY==n-1)) { if(whiteBlockY<n-1){ whiteBlockDown(); lanjutkan l; } if(whiteBlockX>targetX){ whiteBlockLeft(); lanjutkan l; } break; } whiteBlockUp(); puzzle[n-1][targetX]!=(resetBlock+n)){//Tidak ada reset yang berhasil// isPrint=benar; swapWhiteBlockAndCurrentBlock(); reset3(targetX); swapWhiteBlockAndCurrentBlock(); reset3_0(); kembali; } kembali } pribadi void reset2_3(){ if(whiteBlockX==resetBlockX && whiteBlockY==resetBlockY+1){ return;//Jika kondisi terpenuhi, keluar dari rekursi} //Blok putih mungkin berada di kiri, kiri bawah, atau bawah sisi blok reset if(whiteBlockY= =resetBlockY){//left whiteBlockDown(); }else if(whiteBlockX < resetBlockX){//kiri bawah whiteBlockRight(); }else { whiteBlockUp(); } reset2_3();//recursion} private void reset2_2(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//2 Kembali ke bawah;//Keluar dari rekursi} //Kemungkinan posisi blok reset, posisi target ke kiri, tepat di bawah, kiri bawah if(resetBlockX==targetX){//Pindah langsung ke bawah dan ke atas resetBlockUp(targetX, targetY); Pindah ke kanan lalu ke atas resetBlockRight(targetX, targetY } reset2_2(targetX, targetY);//recursion} private void reset2(int targetX, int targetY){ if (resetBlockX == target Bagian bawah bukan blok reset, pindahkan blok putih ke posisi target* 2. Pindahkan blok reset tepat di bawah posisi target* 3. Pindahkan blok putih ke bawah blok reset* 4. Reset sesuai ke langkah-langkah yang ditentukan*/ //Langkah pertama if(whiteBlockX==targetX&& whiteBlockY==targetY){ if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){//Blok reset berada di bawah swapWhiteBlockAndCurrentBlock(); return; } } //Langkah kedua adalah memindahkan blok reset tepat di bawah posisi target reset2_2(targetX, targetY+1); //Langkah ketiga memindahkan blok putih di bawah blok reset reset2_3(); //Langkah keempat mereset swapWhiteBlockAndCurrentBlock() sesuai dengan langkah yang ditentukan; whiteBlockLeft(); ); whiteBlockUp(); whiteBlockRight(); whiteBlockDown(); whiteBlockLeft(); whiteBlockUp(); whiteBlockUp(); whiteBlockRight(); swapWhiteBlockAndCurrentBlock(); } private void resetBlockToTarget(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//Posisi yang benar tanpa memindahkan kembali ;//Keluar dari rekursi} if(resetBlockY==targetY){//positif kiri resetBlockLeft(targetX, targetY); }else{//kiri bawah, bawah, kanan bawah if(resetBlockX>=targetX){//kanan bawah||turun ke atas if ( resetBlockX==n-1){//Blok reset ada di paling kanan, gerakkan ke kiri terlebih dahulu; untuk memudahkan gerakan ke atas, blok putih berlawanan arah jarum jam resetBlockLeft(targetX, targetY); }else{ resetBlockUp(targetX, targetY); } }else{//Kiri bawah; shift kanan resetBlockRight(targetX, targetY); , ke dalam targetY){ if (resetBlockX == target ; }// System.out.println("resetBlockRight"); if(whiteBlockY<resetBlockY){//Di atas if(whiteBlockY<resetBlockY-1){//Beberapa baris di atas whiteBlockDown(); tepat di atas whiteBlockRight(); }else{//kanan atas whiteBlockDown(); if(whiteBlockY==resetBlockY){//Baris yang sama if(whiteBlockX<resetBlockX){//Sisi kiri if(whiteBlockY==n-1){//Pada akhirnya, Anda hanya bisa naik whiteBlockUp(); }else { whiteBlockDown (); } }lainnya{//kanan jika(whiteBlockX==resetBlockX+1){ swapWhiteBlockAndCurrentBlock(); return;//Keluar dari rekursi}else{ whiteBlockLeft(); }else{//Bawah if(whiteBlockX <= resetBlockX){//Kiri bawah, bawah whiteBlockRight(); } } resetBlockRight(targetX, targetY);//recursion} kekosongan pribadi resetBlockLeft(int targetX, int targetY){ if (resetBlockX == target / System.out.println("resetBlockLeft"); if(whiteBlockY<resetBlockY){//Di atas if(whiteBlockY<resetBlockY-1){//Beberapa baris di atas whiteBlockDown(); = =n-1){//Di paling kanan, balok putih tidak bisa dipindahkan ke kanan, tapi hanya bisa dipindahkan ke kiri whiteBlockLeft(); if(resetBlockY==n-1){//Blok reset berada di ujung paling bawah, blok putih tidak dapat bergerak searah jarum jam whiteBlockLeft(); }else{ whiteBlockRight(); /Kanan atas if(resetBlockY==n-1){//Blok reset berada di ujung paling bawah, blok putih tidak dapat bergerak searah jarum jam whiteBlockLeft(); whiteBlockDown(); } }else{//kiri atas whiteBlockDown(); 1){//Satu spasi di sebelah kiri swapWhiteBlockAndCurrentBlock();//Keluar dari pengembalian rekursi; }else{ whiteBlockRight(); } }else{//Kanan if(whiteBlockY==n-1){//Ada di bagian bawah dan tidak dapat dipindahkan ke bawah. Hanya dapat dipindahkan ke atas whiteBlockUp(); }else{ whiteBlockDown(); { whiteBlockUp( ); }else{ whiteBlockRight(); }else{//Bawah, kanan bawah whiteBlockLeft(); } } resetBlockLeft(targetX, targetY);//Recursion} private void resetBlockUp(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//Posisi sudah benar tanpa berpindah kembali;//Keluar dari rekursi} if( resetBlockY==0){//Blok reset telah mencapai puncak dan tidak dapat dipindahkan ke atas return }// System.out.println("resetBlockUp"); if (whiteBlockY < resetBlockY) {//Di atas if(whiteBlockY < resetBlockY - 1){//Beberapa baris di atas whiteBlockDown(); = = resetBlockX){//Blok putih dan blok reset berada pada kolom yang sama (kolom vertikal) Blok putih dan blok reset langsung bertukar posisi swapWhiteBlockAndCurrentBlock();//Keluar dari pengembalian rekursi; }else{ if(whiteBlockX<resetBlockX){//Blok putih berada di sebelah kiri blok putih yang dipindahkan whiteBlockRight(); }else{/ /Blok putih berada di sisi kanan blok reset; blok putih berpindah ke kiri whiteBlockLeft(); == resetBlockY) {//Blok putih dan blok reset berada pada baris yang sama; blok putih bergerak ke atas if(whiteBlockX<resetBlockX){//Maju ke kiri if(whiteBlockX<resetBlockX-1){//Maju ke kiri multi -sel whiteBlockRight(); } else{//Satu kotak di sebelah kiri if(whiteBlockY==n-1){//Akhir whiteBlockUp(); if(resetBlockX==n-1){//Blok penyetelan ulang berada di paling kanan dan tidak boleh berlawanan arah jarum jam. Hanya blok putih yang dapat dipindahkan searah jarum jam whiteBlockUp(); /kanan whiteBlockUp(); }else{//Blok putih berada di bawah blok reset. Blok putih harus bergerak ke atas melewati blok reset. Blok putih berputar berlawanan arah jarum jam ke atas blok putih//Tiga situasi: kiri bawah, bawah, bawah kanan if(whiteBlockX<=resetBlockX) {//Kiri bawah, bawah; blok putih bergerak ke kanan i f(resetBlockX==n-1){//Blok reset berada di paling kanan dan tidak boleh berlawanan arah jarum jam. Hanya blok putih yang dapat dipindahkan searah jarum jam if(whiteBlockX==resetBlockX){//Tepat di bawah whiteBlockLeft(); }else{//Kiri bawah whiteBlockUp(); } }else{ whiteBlockRight(); } }else{//Balok putih bergerak ke atas whiteBlockUp(); /Blok putih dan setel ulang posisi pertukaran blok private void swapWhiteBlockAndCurrentBlock(){ langkah++; int tempX = whiteBlockX,tempY = whiteBlockY; int temp = teka-teki[whiteBlockY][whiteBlockX]; teka-teki[whiteBlockY][whiteBlockX] = teka-teki[resetBlockY][resetBlockY]; ; println("swap"); } private void whiteBlockDown(){ langkah++; int temp = teka-teki[whiteBlockY][whiteBlockX]; teka-teki[whiteBlockY][whiteBlockY+1 ][whiteBlockX] = suhu; whiteBlockY++; println("↓"); whiteBlockUp(){ langkah++; int temp = teka-teki[whiteBlockY][whiteBlockX]; teka-teki[whiteBlockY][whiteBlockX] = teka-teki[whiteBlockY-1][whiteBlockX] teka-teki[whiteBlockY-1][whiteBlockX] = suhu; ; println("↑"); } kekosongan pribadi whiteBlockLeft(){ langkah++; teka-teki[blokputihY][blokputihX]; teka-teki[blokputihY][blokputihX-1] = teka-teki[blokputihY][blokputihX-1]; private void whiteBlockRight(){ langkah++; int temp = puzzle[whiteBlockY][whiteBlockX]; puzzle[whiteBlockY][whiteBlockX] = teka-teki[whiteBlockY][whiteBlockX+1]; teka-teki[whiteBlockY][whiteBlockX+1] = temp; whiteBlockX++; = StringBuilder baru(); sb.append("resetBlock=("+resetBlock+","+resetBlockX+","+resetBlockY+")/n"); if(puzzle!=null){ int len = String.valueOf(n*2-1 ). panjang(); untuk (int y = 0; y < n; y++) { untuk (int x = 0; x < n; x++) { if(x>0){ sb.append(","); } sb.append(_str(String.valueOf(puzzle[y][x]), len) } sb.append("/n") ; } sb.tambahkan("---------------------------------------" } else{ sb.append("puzzle bernilai null"); return sb.toString(); } String pribadi _str(String str,int len){ str=str==null?"":str; if(str.length()<len){ return _str(str+" ", len); private void println(String str){ if(isPrint){ System.out.println(str); System.out.println(ini); melempar FileNotFoundException, UnsupportedEncodingException {// System.setOut(new PrintStream("e:/puzzle.txt","UTF-8")); Puzzle p = new Puzzle(); p.sort(); } catch (Pengecualian e) { e.printStackTrace(); System.out.println("Pengecualian:"); }akhirnya{ System.out.println(p);
Di atas adalah keseluruhan isi artikel ini, saya harap Anda semua menyukainya.