خطرت لي اليوم فكرة مفاجئة وهي أن أصنع لعبة ألغاز ذكية لصديقتي.
يجب تحقيق هذه الوظائف، الأول هو تخصيص الصورة، والثاني هو تخصيص الشبكة، بالطبع، ما فكرت به في البداية كان 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، ونطاق الإحداثيات y n-2 وn-1؛
يمكن إكمال كل منطقة وفقًا لقواعد المنطقة المعنية.
Puzzle.java
import java.io.FileNotFoundException;import java.io.PrintStream;import java.io.UnsupportedEncodingException;import java.util.Random; public class Puzzle { Private long step = 0;// قاعدة النظام الأساسي Private int [][] puzzle; Private intsetBlock = 0;// // موضع الكتلة الفارغة public int WhiteBlockX; WhiteBlockY; // إحداثيات الكتلة التي سيتم نقلها حاليًا هي كتلة إعادة التعيين Private intsetBlockY; public boolean isPrint=false; n = n init(); } public void init() { puzzle = new int[n][n]; y++) { for (int x = 0; x < n; x++) { puzzle[y][x] = x + y * n } } WhiteBlockX = 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); =n-1&&y0==n-1)||(x1==n-1&&y1==n-1)){// لم يتم استبدال الأخيرcontinue } times--; puzzle[x0][y0]; puzzle[x0][y0] = puzzle[x1][y1]; ع = {{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 voidsort(){ for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {// الأخير فارغ، } else { إعادة تعيين(x, y) ) } } } } // إعادة تعيين الكتلة إلى الموضع المستهدف Private voidset(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;// الخروج من العودية}setBlockToTarget(targetX, targetY }); وإلا إذا ( targetX==n-1 && targetY < n-2){// الحالة الثانية if(resetBlockX==targetX&&resetBlockY==targetY){// الموضع صحيح بدون تحريك return;// الخروج من العودية}set2(targetX, targetY }else if(targetX < n- 2 && targetY == n-2){// isPrint=true;set3(targetX); returnBlockToTarget(n-2, n-2); -1){ return } } إعادة تعيين (targetX, targetY);//recursion} initResetBlock الخاص void(int targetX,int targetY){setBlock = targetX + targetY * n; for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (puzzle[y][x] == ResetBlock) {// x, y هو موضع كتلة إعادة التعيينsetBlockX = x;setBlockY = y; if(targetX>=2){// } initResetBlock(targetX, n-1);resetBlockToTarget(targetX, n-2); initResetBlock(targetX, n-2); : while (!(whiteBlockX==targetX &&whiteBlockY==n-1)) { if(whiteBlockY<n-1){ WhiteBlockDown(); continue l } if(whiteBlockX>targetX){ أبيضBlockLeft(); continue l } }whiteBlockUp(); puzzle[n-1][targetX]!=(resetBlock+n)){// لم تتم إعادة التعيين بنجاح // if(resetBlockRight()); return } return; voidset2_3(){ if(whiteBlockX==resetBlockX && WhiteBlockY==resetBlockY+1){ return;// إذا تم استيفاء الشروط، فاخرج من العودية} // قد تكون الكتلة البيضاء على اليسار أو أسفل اليسار أو أقل جانب كتلة إعادة التعيين if(whiteBlockY= =resetBlockY){//leftwhiteBlockDown() }else if(whiteBlockX <resetBlockX){//أسفل اليسار WhiteBlockRight(); }else {whiteBlockUp(); }set2_3();//recursion} Private voidset2_2(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){/2 العودة أدناه؛ // الخروج من العودية} // المواضع المحتملة لإعادة تعيين الكتلة، الموضع المستهدف على اليسار، أسفل اليسار مباشرة if(resetBlockX==targetX){// تحرك مباشرة إلى الأسفل وإلى الأعلىsetsetBlockUp(targetX, targetY); تحرك لليمين ثم للأعلى إعادة تعيينBlockRight(targetX, targetY) }set2_2(targetX, targetY);//recursion} Private voidset2(int targetX, int targetY){ إذا (resetBlockX == target الجزء السفلي ليس كتلة إعادة تعيين، انقل الكتلة البيضاء إلى الموضع المستهدف* 2. انقل كتلة إعادة التعيين مباشرة أسفل الموضع المستهدف* 3. حرك الكتلة البيضاء أسفل كتلة إعادة التعيين* 4. أعد الضبط وفقًا للخطوات المقررة*/ // الخطوة الأولى if(whiteBlockX==targetX&& WhiteBlockY==targetY){ if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){// كتلة إعادة التعيين موجودة أسفل SwapWhiteBlockAndCurrentBlock() return }else{whiteBlockDown(); } } // الخطوة الثانية هي نقل كتلة إعادة التعيين مباشرة أسفل الموضع المستهدفsetset2_2(targetX, targetY+1); // الخطوة الثالثة تحرك الكتلة البيضاء أسفل إعادة تعيين الكتلة // الخطوة الرابعة تعيد ضبط SwapWhiteBlockAndCurrentBlock() وفقًا للخطوات المحددة؛ );whiteBlockUp(); WhiteBlockRight(); WhiteBlockLeft();whiteBlockUp();whiteBlockRight(); SwapWhiteBlockAndCurrentBlock(); } الأمر الخاص بدون تحريك return ;//الخروج من العودية} if(resetBlockY==targetY){// يسار إيجابي إعادة تعيينBlockLeft(targetX, targetY); }else{//أسفل اليسار، أسفل، أسفل اليمين if(resetBlockX>=targetX){//أسفل اليمين||أسفل تحرك لأعلى if (resetBlockX==n-1){// كتلة إعادة التعيين في أقصى اليمين، تحرك يسارًا أولاً لتسهيل الحركة الصعودية، الكتلة البيضاء عكس اتجاه عقارب الساعةsetBlockLeft(targetX, targetY); }else{setBlockUp(targetX, targetY);//التحول الأيمن السفليsetBlockRight(targetX, targetY); ، هدف صحيحY) { if (resetBlockX == target ; }// System.out.println("resetBlockRight"); if(whiteBlockY<resetBlockY){// أعلاه if(whiteBlockY<resetBlockY-1){// أسطر متعددة فوق WhiteBlockDown(); }else{// صف أعلاه if(whiteBlockX<resetBlockX+1){// أعلى اليسار و فوق WhiteBlockRight ()؛ }else{//أعلى اليمين WhiteBlockDown(); if(whiteBlockY==resetBlockY){// نفس السطر if(whiteBlockX<resetBlockX){// الجانب الأيسر if(whiteBlockY==n-1){// في النهاية، يمكنك فقط الصعود إلى WhiteBlockUp() }else { WhiteBlockDown ()؛ } }else{//right if(whiteBlockX==resetBlockX+1){ SwapWhiteBlockAndCurrentBlock(); return;// الخروج من العودية}else{whiteBlockLeft(); } } }else{//Bottom if(whiteBlockX <=setBlockX){//أسفل اليسار، أسفل WhiteBlockRight(); } }setBlockRight(targetX, targetY);//recursion} Private voidsetBlockLeft(int targetX,int targetY){ if (resetBlockX == target / System.out.println("resetBlockLeft"); if(whiteBlockY<resetBlockY){// أعلاه if(whiteBlockY<resetBlockY-1){// أسطر متعددة فوق WhiteBlockDown(); = =n-1){// في أقصى اليمين، لا يمكن نقل الكتلة البيضاء إلى اليمين، ولكن يمكن نقلها فقط إلى اليسار WhiteBlockLeft(); }else{; if(resetBlockY==n-1){// كتلة إعادة التعيين في أدنى نهاية، ولا يمكن للكتلة البيضاء أن تتحرك في اتجاه عقارب الساعة WhiteBlockLeft(); }else{whiteBlockRight(); } } }else if(whiteBlockX>resetBlockX){// /أعلى اليمين if(resetBlockY==n-1){// كتلة إعادة التعيين في أدنى نهاية، ولا يمكن للكتلة البيضاء أن تتحرك في اتجاه عقارب الساعة WhiteBlockLeft(); WhiteBlockDown(); } }else{//upper left WhiteBlockDown(); } } }else if(whiteBlockY==resetBlockY){// يسار، يمين if(whiteBlockX<resetBlockX){//left if(whiteBlockX= =resetBlockX- 1){// مسافة واحدة على اليسار SwapWhiteBlockAndCurrentBlock();// الخروج من العودية return; }else{whiteBlockRight(); } }else{//Right if(whiteBlockY==n-1){// إنه في الأسفل ولا يمكنه التحرك لأسفل. لا يمكن نقله إلا للأعلى WhiteBlockUp(); }else{ WhiteBlockDown(); } } }else{// أسفل اليسار، أسفل، أسفل اليمين if(whiteBlockX<resetBlockX){// أسفل اليسار if(whiteBlockX==resetBlockX-1) {whiteBlockUp() }else{ WhiteBlockRight() } }else{// أسفل، أسفل اليمين WhiteBlockLeft(); } }setBlockLeft(targetX, targetY);//Recursion} Private voidsetBlockUp(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){// الموضع صحيح دون تحريك return;//الخروج من العودية} if(resetBlockY==0){// وصلت كتلة إعادة التعيين إلى الأعلى ولا يمكن نقلها للأعلى return }// System.out.println("resetBlockUp"); if (whiteBlockY <resetBlockY) {//أعلاه if(whiteBlockY <resetBlockY - 1){//أسطر متعددة فوق WhiteBlockDown(); = =setBlockX){// الكتلة البيضاء وكتلة إعادة التعيين موجودة في نفس العمود (العمود الرأسي) تقوم الكتلة البيضاء وكتلة إعادة التعيين بتبديل المواضع مباشرة SwaWhiteBlockAndCurrentBlock();// الخروج من التكرار return; }else{ if(whiteBlockX<resetBlockX){// الكتلة البيضاء على يسار كتلة إعادة التعيين؛ the right WhiteBlockRight(); }else{/ / الكتلة البيضاء على الجانب الأيمن من كتلة إعادة التعيين؛ تتحرك الكتلة البيضاء إلى اليسار WhiteBlockLeft(); } } } } else if (whiteBlockY ==setBlockY) {// الكتلة البيضاء وكتلة إعادة التعيين موجودة في نفس الصف؛ تتحرك الكتلة البيضاء لأعلى if(whiteBlockX<resetBlockX){//للأمام لليسار if(whiteBlockX<resetBlockX-1){//للأمام لليسار متعدد -cell WhiteBlockRight(); } else {// مربع واحد إلى اليسار if(whiteBlockY==n-1){// النهاية WhiteBlockUp(); if(resetBlockX==n-1){// توجد كتلة إعادة التعيين في أقصى اليمين ولا يمكن نقلها عكس اتجاه عقارب الساعة. /يمين WhiteBlockUp ()؛ } }else{// الكتلة البيضاء أسفل كتلة إعادة التعيين. تحتاج الكتلة البيضاء إلى التحرك لأعلى بعد كتلة إعادة التعيين right if(whiteBlockX<=resetBlockX) {// أسفل اليسار، لأسفل؛ f(resetBlockX==n-1){// توجد كتلة إعادة التعيين في أقصى اليمين ولا يمكن تحريكها عكس اتجاه عقارب الساعة. if(whiteBlockX==resetBlockX){// أسفل WhiteBlockLeft(); }else{// الجزء السفلي الأيسر من WhiteBlockUp(); } }else{whiteBlockRight(); } }else{// يتحرك الجزء السفلي من اليمين إلى الأعلى WhiteBlockUp(); } }setBlockUp(targetX, targetY);//Recursion} / / الكتلة البيضاء وإعادة ضبط مواضع مبادلة الكتلة Private void SwapWhiteBlockAndCurrentBlock(){ step++; int tempX = WhiteBlockX,tempY = int temp = puzzle[whiteBlockY][whiteBlockX]; puzzle[whiteBlockY][whiteBlockX] = puzzle[resetBlockX]; ; println("swap"); } public void WhiteBlockDown(){ step++; int temp = puzzle[whiteBlockY]; ][whiteBlockX] = temp;whiteBlockY++; println("↓"); WhiteBlockUp(){ step++; ; println("↑"); } public void WhiteBlockLeft(){ step++; puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY][whiteBlockX-1]; public void WhiteBlockRight(){ step++; puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY][whiteBlockX+1]; puzzle[whiteBlockY][whiteBlockX+1] = temp; println("→"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("resetBlock=("+resetBlock+"،+resetBlockX+"،"+resetBlockY+")/n"); if(puzzle!=null){ int len = String.valueOf(n*2-1 length(); for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if(x>0){ sb.append("،" } sb.append(_str(String.valueOf(puzzle[y][x]), len)); } sb.append("/n")); } sb.append("--------------------------------------"); else{ sb.append("اللغز فارغ" } return sb.toString(); } public String_str(String str,int len){ str=str==null؟":str; if(str. length()<len){ return _str(str+" ", len }); public void println(String str){ if(isPrint){ System.out.println(str); System.out.println(this); throws FileNotFoundException, UnsupportedEncodingException {// System.setOut(new PrintStream("e:/puzzle.txt"،UTF-8")); Puzzle p = new Puzzle(); p.sort(); } Catch (Exception e) { e.printStackTrace(); }أخيرًا{ System.out.println(p);
ما ورد أعلاه هو محتوى هذه المقالة بالكامل، وآمل أن تنال إعجابكم جميعًا.