วันนี้ฉันมีความคิดฉับพลันที่จะสร้างเกมไขปริศนาอัจฉริยะให้กับแฟนของฉัน
จำเป็นต้องตระหนักถึงฟังก์ชั่นเหล่านี้ สิ่งแรกคือการปรับแต่งรูปภาพ และอย่างที่สองคือการปรับแต่งตาราง แน่นอนว่าสิ่งที่ฉันคิดในตอนแรกคือ 3*3 4*4 5*5 และฉันไม่ได้ใช้ ตารางเช่น 3*5
ประการที่สามคือการใช้ฟังก์ชันไขปริศนาอัตโนมัติ ฉันเชื่อว่าทุกคนรู้ดีว่าผู้หญิงเล่นเกมไม่เก่ง ดังนั้นฟังก์ชันไขปริศนาอัตโนมัตินี้จึงมีความจำเป็น
ฉันจะไม่เขียนเกี่ยวกับการระงับและการจัดอันดับอื่นๆ!
ตอนนี้คำถามสำคัญปรากฏขึ้น ดูเหมือนว่าข้อกำหนดในการตระหนักถึงฟังก์ชั่นปริศนาอัตโนมัตินั้นสูงสักหน่อย! คอมพิวเตอร์สามารถเป็นเหมือนมนุษย์ได้และทำได้เพียง:
เรามาเข้าเรื่องสาระสำคัญกันก่อน
จริงๆ แล้วจิ๊กซอว์เป็นเพียงเรื่องของการจัดการ:
มีคำจำกัดความของการเรียงสับเปลี่ยน: ในการจัดเรียง 1, 2,...,n หากตำแหน่งด้านหน้าและด้านหลังของคู่ตัวเลขอยู่ในลำดับย้อนกลับ นั่นคือ เลขหน้ามากกว่าเลขหลัง จากนั้นจะเรียกว่าลำดับย้อนกลับ จำนวนลำดับย้อนกลับทั้งหมดในการเรียงสับเปลี่ยนเรียกว่าหมายเลขลำดับย้อนกลับของการเรียงสับเปลี่ยนนี้ การจัดเรียงที่เลขกลับตัวเป็นเลขคู่เรียกว่าการจัดเรียงเลขคู่ การจัดเรียงที่เลขกลับกันเป็นเลขคี่เรียกว่าการจัดเรียงคี่ ตัวอย่างเช่น ในปี 2431, 21, 43, 41 และ 31 อยู่ในลำดับย้อนกลับ และลำดับย้อนกลับคือ 4 ซึ่งเป็นการจัดเรียงเลขคู่
อีกคำจำกัดความหนึ่ง: การแลกเปลี่ยนตัวเลขสองตัวในการเรียงสับเปลี่ยน ความเท่าเทียมกันของการเรียงสับเปลี่ยนจะเปลี่ยนไป
คำจำกัดความข้างต้นนำมาจาก "พีชคณิตขั้นสูง" ทั้งหมด
การจัดเรียงปริศนาจะต้องเป็นแบบคู่ สามารถพบได้ในข้อมูลอ้างอิงของฉัน
นี่คือวิธีนำปริศนาของฉันไปใช้!
จะมาเขียนทีหลังครับ
อ้างอิง: http://en.wikipedia.org/wiki/Fifteen_puzzle
ปริศนาอัตโนมัติ:
ก่อนอื่น ควรมีกฎเกณฑ์บางประการสำหรับปริศนาอัตโนมัติ ตามประสบการณ์ปริศนาของฉัน พื้นที่ต่างๆ จะใช้กฎปริศนาที่แตกต่างกัน ดังนั้น:
แผนที่กริดของฉันแบ่งออกเป็น 4 พื้นที่ (หากแผนที่กริดมีกริด n*n)
พื้นที่แรก: ช่วงพิกัด x 0 ถึง n-2, ช่วงพิกัด y 0 ถึง n-3
พื้นที่ที่สอง: พิกัด x n-1, ช่วงพิกัด y 0 ถึง n-3
พื้นที่ที่สาม: ช่วงพิกัด x 0 ถึง n-3, ช่วงพิกัด y n-2 และ n-1
พื้นที่ที่สี่: ช่วงพิกัด x n-2 ถึง n-1, ช่วงพิกัด n-2 และ n-1; นั่นคือสี่เซลล์สุดท้าย
แต่ละพื้นที่สามารถทำได้ตามกฎของพื้นที่นั้น ๆ
ปริศนา.java
นำเข้า java.io.FileNotFoundException; นำเข้า java.io.PrintStream; นำเข้า java.io.UnsupportedEncodingException; นำเข้า java.util.Random; ปริศนาคลาสสาธารณะ { ขั้นตอนยาวส่วนตัว = 0; ส่วนตัว int n = 6; // ฐานแพลตฟอร์มส่วนตัว int [] [] ปริศนา; int ส่วนตัว resetBlock = 0; // // ตำแหน่งบล็อกว่าง int ส่วนตัว whiteBlockX; whiteBlockY; // พิกัดของบล็อกที่กำลังจะถูกย้ายคือรีเซ็ตบล็อกส่วนตัว int resetBlockY; บูลีนส่วนตัว isPrint=false; ปริศนาสาธารณะ () { init (); n = n; init(); } โมฆะส่วนตัว init() { ปริศนา = int ใหม่ [n]; y++) { สำหรับ (int x = 0; x < n; x++) { ปริศนา [y] [x] = x + y * n; } } whiteBlockX = n-1; whiteBlockY = n-1; // จำนวนสับเปลี่ยนต้องเป็นเลขคู่ 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) {// รับประกันแม้กระทั่งการเรียงลำดับ if((x0 = =n-1&&y0==n-1)||(x1==n-1&&y1==n-1))//อันสุดท้ายไม่ได้ถูกแทนที่ต่อไป } ครั้ง--; int t = ปริศนา[x0][y0]; ปริศนา[x0][y0] = ปริศนา[x1][y1] = t; พี = {{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}};// ปริศนา = p; } การเรียงลำดับโมฆะสาธารณะ () { สำหรับ (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {//อันสุดท้ายว่างเปล่า } else { รีเซ็ต(x, y ) ; } } } // รีเซ็ตบล็อกไปยังตำแหน่งเป้าหมาย รีเซ็ตเป็นโมฆะส่วนตัว (int targetX, int targetY) { // ค้นหาตำแหน่งปัจจุบันของบล็อกรีเซ็ต initResetBlock (targetX, targetY); ลำดับการรีเซ็ตคือจากซ้ายไปขวา บนลงล่าง* วิธีการเคลื่อนไหวคือการเลื่อนขึ้นก่อน จากนั้นไปทางซ้าย* บล็อกการรีเซ็ตปัจจุบัน ตำแหน่งที่ต้องการรีเซ็ตสามารถแบ่งออกเป็นสี่สถานการณ์* 1. ไม่อยู่ใน แถวขวาสุดหรือสองแถวล่าง * 2 แถวขวาสุด x=n-1 แต่ไม่ใช่สองแถวล่าง * 3. สองแถวล่าง y=n-2 แต่ไม่ใช่แถวขวาสุด; แถวขวาสุดก็เป็นสองแถวล่างเช่นกัน OK*/ if(targetX < n-1 && targetY < n-2){ if(resetBlockX==targetX&&resetBlockY==targetY){//ตำแหน่งถูกต้องโดยไม่ต้องย้าย return;//ออกจากการเรียกซ้ำ} ResetBlockToTarget(targetX, targetY } อย่างอื่นถ้า ( targetX==n-1 && targetY < n-2){//กรณีที่สอง if(resetBlockX==targetX&&resetBlockY==targetY){//ตำแหน่งถูกต้องโดยไม่ต้องย้าย return;//Exit the recursion} reset2(targetX, targetY); }else if(targetX < n- 2 && targetY == n-2){// isPrint=true; reset3(targetX); }else{ initResetBlock(n-2, n-2); ResetBlockToTarget(n-2, n-2); if(whiteBlockX<n-1){ whiteBlockRight(); } if(whiteBlockY<n-1){ whiteBlockDown(); } ถ้า(whiteBlockX==n-1&&whiteBlockY==n -1) { return; } } รีเซ็ต (targetX, targetY); // recursion} โมฆะส่วนตัว initResetBlock (int targetX, int targetY){ ResetBlock = targetX + targetY * n; สำหรับ (int y = 0; y < n; y++) { สำหรับ (int x = 0; x < n; x++) { ถ้า (ปริศนา [y] [x] == ResetBlock) {// x, y คือตำแหน่งของบล็อกรีเซ็ต ResetBlockX = x; ResetBlockY = y; break; } } } } if(targetX>=2){// } initResetBlock(targetX, n-1); ResetBlockToTarget(targetX, n-2); initResetBlock(targetX, n-2); : ในขณะที่ (!(whiteBlockX==targetX && whiteBlockY==n-1)) { ถ้า(whiteBlockY<n-1){ whiteBlockDown(); ดำเนินการต่อ l; } if(whiteBlockX>targetX){ whiteBlockLeft(); } whiteBlockUp(); ปริศนา [n-1] [targetX]! = (รีเซ็ตบล็อก + n)){// ไม่มีการรีเซ็ตสำเร็จ // isPrint=true; swapWhiteBlockAndCurrentBlock(); reset3(targetX); } } โมฆะส่วนตัว () swapWhiteBlockAndCurrentBlock(); รีเซ็ต 3_0(); กลับ; } ส่วนตัว void reset2_3(){ if(whiteBlockX==resetBlockX && whiteBlockY==resetBlockY+1){ return;//หากตรงตามเงื่อนไข ให้ออกจากการเรียกซ้ำ} //บล็อกสีขาวอาจอยู่ทางซ้าย ซ้ายล่าง หรือต่ำกว่า ด้านข้างของบล็อกรีเซ็ต if(whiteBlockY= =resetBlockY){//left whiteBlockDown(); }else if(whiteBlockX < resetBlockX){//ซ้ายล่าง whiteBlockRight(); }else { whiteBlockUp(); } reset2_3();//recursion} รีเซ็ตเป็นโมฆะส่วนตัว2_2(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){/2 กลับมาด้านล่าง;//ออกจากการเรียกซ้ำ} //ตำแหน่งที่เป็นไปได้ของบล็อกรีเซ็ต ตำแหน่งเป้าหมายซ้าย ด้านล่างซ้ายล่าง if(resetBlockX==targetX){//เลื่อนลงไปด้านล่างโดยตรงและขึ้น resetBlockUp(targetX, targetY); }else{//ซ้ายหรือล่างซ้ายก่อน เลื่อนไปทางขวาแล้วขึ้น ResetBlockRight(targetX, targetY); } Reset2_2(targetX, targetY);//recursion} รีเซ็ตโมฆะส่วนตัว2(int targetX, int targetY){ ถ้า (resetBlockX == เป้าหมาย ด้านล่างไม่ใช่บล็อกรีเซ็ต ให้ย้ายบล็อกสีขาวไปยังตำแหน่งเป้าหมาย* 2. ย้ายบล็อกรีเซ็ตไปด้านล่างตำแหน่งเป้าหมาย* 3. ย้ายบล็อกสีขาวด้านล่างบล็อกรีเซ็ต* 4. รีเซ็ตตาม ตามขั้นตอนที่กำหนด*/ //ขั้นตอนแรก if(whiteBlockX==targetX&& whiteBlockY==targetY){ if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){//บล็อกการรีเซ็ตอยู่ต่ำกว่า swapWhiteBlockAndCurrentBlock(); return; } } //ขั้นตอนที่สองคือการย้ายบล็อกรีเซ็ตไปด้านล่างตำแหน่งเป้าหมายที่รีเซ็ต2_2(targetX, targetY+1); //ขั้นตอนที่สามย้ายบล็อกสีขาวด้านล่างรีเซ็ตบล็อก2_3(); //ขั้นตอนที่สี่รีเซ็ตswapWhiteBlockAndCurrentBlock() ตามขั้นตอนที่กำหนด; whiteBlockUp(); whiteBlockUp(); whiteBlockDown(); whiteBlockDown(); whiteBlockLeft(); whiteBlockUp(); whiteBlockRight(); } โมฆะส่วนตัวรีเซ็ตBlockToTarget(int targetX, int targetY){ ถ้า(resetBlockX==targetX&&resetBlockY==targetY){//แก้ไขตำแหน่ง ;//ออกจากการเรียกซ้ำ} if(resetBlockY==targetY){//positive left resetBlockLeft(targetX, targetY); }else{//ล่างซ้าย, ล่าง, ขวาล่าง if(resetBlockX>=targetX){//ล่างขวา||ลง; (resetBlockX==n-1){//บล็อกรีเซ็ตอยู่ทางขวาสุด เลื่อนไปทางซ้ายก่อน เพื่ออำนวยความสะดวกในการเคลื่อนที่ขึ้น บล็อกสีขาวทวนเข็มนาฬิการีเซ็ตBlockLeft(targetX, targetY); }else{ resetBlockUp(targetX, targetY); // Recursion} โมฆะส่วนตัว resetBlockRight (int targetX) , int เป้าหมาย Y){ ถ้า (resetBlockX == target ; }// System.out.println("resetBlockRight"); if(whiteBlockY<resetBlockY){//ด้านบน if(whiteBlockY<resetBlockY-1){//หลายบรรทัดด้านบน whiteBlockDown(); }else{//A แถวด้านบน if(whiteBlockX<resetBlockX+1){//ด้านบนซ้ายและ เหนือ whiteBlockRight (); }else{//upper right whiteBlockDown(); } } }else if(whiteBlockY==resetBlockY){//บรรทัดเดียวกัน if(whiteBlockX<resetBlockX){//ด้านซ้าย if(whiteBlockY==n-1){//ในตอนท้าย คุณสามารถขึ้นไปได้เฉพาะ whiteBlockUp(); } เท่านั้น { whiteBlockDown (); } }else{//ขวา if(whiteBlockX==resetBlockX+1){ swapWhiteBlockAndCurrentBlock(); return;//ออกจากการเรียกซ้ำ}else{ whiteBlockLeft(); } }else{//ล่างขวา whiteBlockUp(); } }รีเซ็ตBlockRight(targetX, targetY);//recursion} โมฆะส่วนตัวresetBlockLeft(int targetX, int targetY){ ถ้า (resetBlockX == เป้าหมาย / System.out.println("resetBlockLeft"); if(whiteBlockY<resetBlockY){//เหนือ if(whiteBlockY<resetBlockY-1){//หลายบรรทัดเหนือ whiteBlockDown(); }else{//A แถวด้านบน if(whiteBlockX==resetBlockX){//เหนือ if(whiteBlockX = =n-1){//ทางด้านขวาสุด ไม่สามารถย้ายบล็อกสีขาวไปทางขวาได้ แต่สามารถย้ายไปทางซ้ายได้เท่านั้น whiteBlockLeft(); }else{); if(resetBlockY==n-1){//บล็อกรีเซ็ตอยู่ที่ต่ำสุด บล็อกสีขาวไม่สามารถเลื่อนตามเข็มนาฬิกา whiteBlockLeft(); }else{ whiteBlockRight(); } }else if(whiteBlockX>resetBlockX){/ /มุมขวาบน if(resetBlockY==n-1){//บล็อกรีเซ็ตอยู่ที่ต่ำสุด บล็อกสีขาวไม่สามารถเลื่อนตามเข็มนาฬิกา whiteBlockLeft(); }else{ whiteBlockDown(); } }else{//บนซ้าย whiteBlockDown(); } } }else if(whiteBlockY==resetBlockY){//left, right if(whiteBlockX<resetBlockX){//left if(whiteBlockX= =resetBlockX- 1){//หนึ่งช่องว่างทางด้านซ้าย swapWhiteBlockAndCurrentBlock();//ออกจากการเรียกกลับการเรียกซ้ำ; }else{ whiteBlockRight(); } }else{//Right if(whiteBlockY==n-1){//อยู่ด้านล่างและไม่สามารถเลื่อนลงได้ สามารถเลื่อนขึ้นได้ whiteBlockUp(); }else{ whiteBlockDown(); } }else{//ล่างซ้าย, ล่าง, ขวาล่าง if(whiteBlockX<resetBlockX){//ล่างซ้าย if(whiteBlockX==resetBlockX-1) { whiteBlockUp( ); }else{ whiteBlockRight(); } }else{//ล่างขวา whiteBlockLeft(); } } resetBlockLeft(targetX, targetY);//Recursion} โมฆะส่วนตัว resetBlockUp(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//ตำแหน่งถูกต้องโดยไม่ต้องย้าย return;//ออกจากการเรียกซ้ำ} if( ResetBlockY==0){//บล็อกรีเซ็ตถึงด้านบนแล้วและไม่สามารถเลื่อนขึ้นได้ }// System.out.println("resetBlockUp"); if (whiteBlockY < resetBlockY) {//ด้านบน if(whiteBlockY < resetBlockY - 1){//หลายบรรทัดด้านบน whiteBlockDown(); }else{//A แถวด้านบน if(whiteBlockX = = resetBlockX){//บล็อกสีขาวและบล็อกรีเซ็ตอยู่ในคอลัมน์เดียวกัน (คอลัมน์แนวตั้ง) บล็อกสีขาวและบล็อกรีเซ็ตสลับตำแหน่งโดยตรง swapWhiteBlockAndCurrentBlock();//ออกจากการเรียกซ้ำกลับ; }else{ if(whiteBlockX<resetBlockX){//บล็อกสีขาวอยู่ทางด้านซ้ายของบล็อกรีเซ็ต whiteBlockRight(); }else{/ /บล็อกสีขาวอยู่ทางด้านขวาของบล็อกรีเซ็ต; บล็อกสีขาวเลื่อนไปทางซ้าย whiteBlockLeft(); } } } } else if (whiteBlockY == resetBlockY) {//บล็อกสีขาวและบล็อกรีเซ็ตอยู่ในแถวเดียวกัน บล็อกสีขาวเลื่อนขึ้น if(whiteBlockX<resetBlockX){//ไปข้างหน้าซ้าย if(whiteBlockX<resetBlockX-1){//ไปข้างหน้าซ้ายหลาย -cell whiteBlockRight(); } else{//หนึ่งช่องทางซ้าย if(whiteBlockY==n-1){//ส่วนท้าย whiteBlockUp(); }else { if(resetBlockX==n-1){//บล็อกรีเซ็ตจะอยู่ทางขวาสุดและไม่สามารถเลื่อนทวนเข็มนาฬิกาได้เฉพาะบล็อกสีขาวเท่านั้นที่สามารถย้ายตามเข็มนาฬิกา whiteBlockUp(); }else{ whiteBlockDown(); /ขวา whiteBlockUp (); } }อื่น ๆ{//บล็อกสีขาวอยู่ด้านล่างบล็อกรีเซ็ต บล็อกสีขาวจะต้องเลื่อนขึ้นผ่านบล็อกรีเซ็ต ขวา if(whiteBlockX<=resetBlockX) {//ล่างซ้าย, ลง; บล็อกสีขาวเลื่อนไปทางขวา i f(resetBlockX==n-1){//บล็อกรีเซ็ตจะอยู่ทางขวาสุดและไม่สามารถหมุนทวนเข็มนาฬิกาได้ เฉพาะบล็อกสีขาวเท่านั้นที่สามารถเลื่อนตามเข็มนาฬิกาได้ ถ้า(whiteBlockX==resetBlockX){//ต่ำกว่า whiteBlockLeft(); }else{//Lower left whiteBlockUp(); } }else{ whiteBlockRight(); // Recursion} / /White block และรีเซ็ตตำแหน่งการสลับบล็อก private void swapWhiteBlockAndCurrentBlock(){ step++; int tempX = whiteBlockX,tempY = whiteBlockY; int temp = ปริศนา[whiteBlockY][whiteBlockX]; ปริศนา[whiteBlockY][whiteBlockX] = ปริศนา[resetBlockY][resetBlockX] = temp; ; รีเซ็ตบล็อก Y = ชั่วคราว; println("swap"); } โมฆะส่วนตัว whiteBlockDown(){ ขั้นตอน ++; ปริศนา [whiteBlockY] [whiteBlockX]; ][whiteBlockX] = temp; whiteBlockY++; println("↓"); } เป็นโมฆะส่วนตัว whiteBlockUp(){ ขั้นตอน ++; int temp = ปริศนา [whiteBlockY] [whiteBlockX] = ปริศนา [whiteBlockY-1] [whiteBlockX]; ; println("↑"); } โมฆะส่วนตัว whiteBlockLeft(){ step++; ปริศนา[whiteBlockY][whiteBlockX] = ปริศนา[whiteBlockY][whiteBlockX-1]; โมฆะส่วนตัว whiteBlockRight(){ ขั้นตอน ++ int temp = ปริศนา [whiteBlockY] [whiteBlockX]; ปริศนา [whiteBlockY] [whiteBlockX] = ปริศนา [whiteBlockY] [whiteBlockX+1]; ปริศนา [whiteBlockY] [whiteBlockX+1] = temp; whiteBlockX++; } @Override สตริงสาธารณะ toString() = StringBuilder ใหม่ (); sb.append("resetBlock=("+resetBlock+","+resetBlockX+","+resetBlockY+")/n"); if(puzzle!=null){ int len = String.valueOf(n*2-1 ). length(); สำหรับ (int y = 0; y < n; y++) { สำหรับ (int x = 0; x < n; x++) { if(x>0){ sb.append(","); } sb.append(_str(String.valueOf(ปริศนา[y][x]), len) } sb.append("/n") ; } sb.ผนวก("---------------------------------" } else{ sb.append("ปริศนาเป็นโมฆะ"); } return sb.toString(); } ส่วนตัว String _str(String str,int len){ str=str==null?"":str; if(str.length()<len){ return _str(str+" ", len); } โมฆะส่วนตัว println (String str) { if (isPrint) { System.out.println (str); System.out.println (สิ่งนี้); } } โมฆะสาธารณะหลัก (String [] args) พ่น FileNotFoundException, UnsupportedEncodingException {// System.setOut(new PrintStream("e:/puzzle.txt", "UTF-8")); Puzzle p = new Puzzle(); System.out.println(p); p.sort(); } catch (ข้อยกเว้น e) { e.printStackTrace(); System.out.println("ข้อยกเว้น:"); }ในที่สุด{ System.out.println(p);
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าทุกคนจะชอบมัน