今日、ガールフレンドのためにスマートなパズルゲームを作ろうという突然のアイデアが思いつきました。
これらの機能を実現する必要があります。1 つ目は画像のカスタマイズ、2 つ目はグリッドのカスタマイズです。もちろん、最初に考えたのは 3*3 4*4 5*5 であり、使用しませんでした。 3*5 のようなグリッド。
3つ目は、自動パズル機能の実現です。女性はゲームが苦手であることは皆さんご存知だと思いますので、この自動パズル機能は必要です。
他の休載やランキングについては書きません!
ここで重要な質問が出てきますが、自動パズル機能を実現するための要件は少し高いようです。コンピュータは人間と同じで、次のことしかできません。
まずは本質に迫ろう
ジグソーパズルは実際には配置の問題です。
順列の定義があります。1、2、...、n の配列で、1 組の数字の前と後ろの位置が逆の順序である場合、つまり、前の数字が後ろの数字より大きい場合、その場合、それらは逆順序と呼ばれます。順列内の逆順の総数を、この順列の逆順数と呼びます。逆数が偶数の配列を偶数配列、逆数が奇数の配列を奇数配列と呼びます。たとえば、2431 では、21、43、41、31 が逆順になっており、逆順は 4 で偶数配置になります。
ここに別の定義があります。順列で 2 つの数値を交換すると、順列のパリティが変化します。
上記の定義はすべて「Advanced Algebra」から引用しています。
パズルの配置は均等に配置する必要があります。これは私の参考文献に記載されています。
これが私のパズルの実装方法です。
後ほど書きます
参考: http://en.wikipedia.org/wiki/Fifteen_puzzle
自動パズル:
まず、自動パズルには特定のルールが必要です。私のパズルの経験によると、パズルを完成させるには、エリアごとに異なるパズル ルールが使用されます。
私のグリッド マップは 4 つのエリアに分割されています (グリッド マップに n*n グリッドがある場合)
1番目のエリア:x座標範囲0~n-2、y座標範囲0~n-3
2番目のエリア:x座標n-1、y座標範囲0~n-3
3 番目の領域: x 座標範囲 0 ~ n-3、y 座標範囲 n-2 および n-1
4 番目の領域: x 座標範囲 n-2 から n-1、y 座標範囲 n-2 と n-1、つまり最後の 4 つのセル。
各エリアは、それぞれのエリアのルールに従ってクリアできます。
パズル.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 [][] パズル; private int reverseBlock = 0;// //空白ブロックの位置 private int whiteBlockX; WhiteBlockY; //現在移動するブロックの座標はリセットブロックです private int reverseBlockY; public Puzzle() { init() } public Puzzle(int n); n = n; } private void init() { パズル = new int[n][n]; y++) { for (int x = 0; x < n; x++) { パズル [y][x] = x + y * n; } ホワイトブロック X = n-1; ホワイトブロック Y = n-1; // シャッフルの数は偶数である必要があります。 Random random = new Random(); while (times > 0) { int x0 =random.nextInt(n);ランダム.nextInt(n); int x1 = ランダム.nextInt(n); int y1 = ランダム.nextInt(n); if (x0 != x1 && y0!=y1) {// 均等な並べ替えが保証されます。 =n-1&&y0==n-1)||(x1==n-1&&y1==n-1)){//最後のものは置換されませんContinue;回--; int t = パズル[x0][y0] = パズル[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}};// パズル = p; } public void sort(){ for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {//最後のものは空白です。 } else { replace(x, y) ) ; } } } } //ブロックをターゲット位置にリセットします private void replace(int targetX, int targetY) { //リセットされたブロックの現在位置を検索します initResetBlock(targetX, targetY);リセット順序は左から右、上から下* 移動方法は上、次に左へ移動* 現在のリセットブロック、リセットしたい位置は4つの状況に分けられます* 1.右端の行も下の 2 行 * 2. 右端の行 x=n-1 ですが、下の 2 行は除きます。 * 3. 下の 2 行は y=n-2 ですが、右端の行は含みません。右端の行は下2行でもOK*/ if(targetX < n-1 && targetY < n-2){ if(resetBlockX==targetX&&resetBlockY==targetY){//位置は移動せずに正しい return;//再帰を終了} replaceBlockToTarget(targetX, targetY) } else if( targetX==n-1 && targetY < n-2){//2 番目のケース if(resetBlockX==targetX&&resetBlockY==targetY){//位置は移動せずに正しい return;//再帰を終了する} replace2(targetX, targetY) }else if(targetX < n- 2 && targetY == n-2){// isPrint=true; }else{ initResetBlock(n-2, n-2);ターゲットにリセット(n-2, n-2); if(whiteBlockX<n-1){whiteBlockRight(); } if(whiteBlockX==n-1&&whiteBlockY==n) -1){ return; } }reset(targetX, targetY);//recursion} private void initResetBlock(int targetX,int) targetY){resetBlock = targetX + targetY * n; for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (パズル[y][x] == setBlock) {// x, y はリセット ブロックの位置です。resetBlockX = x; } } } } if(targetX>=2){// } initResetBlock(targetX, n-1); resetBlockToTarget(targetX, n-2); : while (!(whiteBlockX==targetX &&whiteBlockY==n-1)) { if(whiteBlockY<n-1){ WhiteBlockDown(); 続行 l; } if(whiteBlockX>targetX); 続行 l; swapWhiteBlockAndCurrentBlock();パズル[n-1][ターゲットX]!=(resetBlock+n)){//リセットは成功しませんでした// isPrint=true; リセット3_0(); } } プライベートvoidreset3_0(){whiteBlockRight(); swapWhiteBlockAndCurrentBlock(); } 戻り値void replace2_3(){ if(whiteBlockX==resetBlockX &&whiteBlockY==resetBlockY+1){ return;//条件が満たされた場合、再帰を終了} //白いブロックは左、左下、または下にある可能性がありますリセット ブロックの側面 if(whiteBlockY= =resetBlockY){//leftwhiteBlockDown(); }else if(whiteBlockX <resetBlockX){//左下whiteBlockRight(); }else {whiteBlockUp(); }reset2_3();//recursion} private void replace2_2(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//2 リセット ブロックをターゲット位置に移動します。以下に戻ります;//再帰を終了します} //リセットブロックの可能な位置、ターゲット位置左、真下、左下 if(resetBlockX==targetX){//真下および上に移動resetBlockUp(targetX, targetY); }else{//最初に左または左下;右に移動してから上に移動します。resetBlockRight(targetX, targetY);//recursion} private void restart2(int targetX, int targetY){ if (resetBlockX == target 一番下はリセットブロックではないので、白いブロックを目標位置に移動* 2. リセットブロックを目標位置の真下に移動* 3. 白いブロックをリセットブロックの下に移動* 4. に従ってリセット所定の手順へ*/ //最初のステップ if(whiteBlockX==targetX&&whiteBlockY==targetY){ if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){//リセットブロックは swapWhiteBlockAndCurrentBlock() }else{whiteBlockDown(); } } //2 番目のステップは、リセット ブロックをターゲット位置の真下に移動することです。reset2_2(targetX, targetY+1); // 3 番目のステップでは、白いブロックをリセット ブロックの下に移動します。 // 4 番目のステップでは、所定の手順に従って swapWhiteBlockAndCurrentBlock() をリセットします。 ); ホワイトブロックアップ(); ホワイトブロックダウン(); WhiteBlockLeft();whiteBlockUp(); swapWhiteBlockAndCurrentBlock(); } private void replaceBlockToTarget(int targetX&resetBlockY==targetY){// 移動せずに位置を修正;//再帰を終了する} if(resetBlockY==targetY){//正の左resetBlockLeft(targetX, targetY); }else{//左下、下、右下 if(resetBlockX>=targetX){//右下に移動 if (resetBlockX==n-1){//リセット ブロックは右端にあり、上方向への移動を容易にするために最初に左に移動します。白いブロックは反時計回りにresetBlockLeft(targetX, targetY); }else{resetBlockUp(targetX, targetY); }else{//右下シフトresetBlockRight(targetX, targetY);//Recursion} , int targetY){ 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{//下 if(whiteBlockX <=resetBlockX){//左下、下whiteBlockRight() }else{//右下whiteBlockUp(); } }resetBlockRight(targetX, targetY);//再帰} private voidresetBlockLeft(int targetX, int targetY){ if (resetBlockX == target / System.out.println("resetBlockLeft"); if(whiteBlockY<resetBlockY){//上 if(whiteBlockY<resetBlockY-1){//whiteBlockDown() の上の複数行; }else{//上 if(whiteBlockX==resetBlockX){//上 if(whiteBlockX) = =n-1){//右端の白いブロックは右には移動できませんが、左にのみ移動できます。 if(resetBlockY==n-1){//リセット ブロックは最下位にあり、白いブロックは時計回りに移動できません。 /右上 if(resetBlockY==n-1){//リセットブロックは最下端にあり、白いブロックは時計回りに移動できませんwhiteBlockLeft(); }else{ whiteBlockDown(); } }else{//左上whiteBlockDown(); } }else if(whiteBlockY==resetBlockY){//left, right if(whiteBlockX<resetBlockX){//left if(whiteBlockX= =resetBlockX- 1){// 左側にスペース 1 つ swapWhiteBlockAndCurrentBlock();// 再帰を終了します return; }else{whiteBlockRight(); } }else{//右 if(whiteBlockY==n-1){//一番下にあるため、下に移動できません。上にのみ移動可能whiteBlockUp(); }else{whiteBlockDown(); } }else{//左下、下、右下 if(whiteBlockX<resetBlockX){//左下 if(whiteBlockX==resetBlockX-1) {whiteBlockUp(); }else{whiteBlockRight()} }else{//下、右下whiteBlockLeft(); } } replaceBlockLeft(targetX, targetY);//再帰} private void replaceBlockUp(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//位置は移動せずに正しい return;//再帰を終了} if(resetBlockY==0){//リセット ブロックが一番上に到達したため、上に移動できません return; System.out.println("resetBlockUp"); if (whiteBlockY <resetBlockY) {//上 if(whiteBlockY < replaceBlockY - 1){//whiteBlockDown() の上の行 }else{//if(whiteBlockX) = =resetBlockX){//白いブロックとリセットブロックは同じ列(垂直列)にあります白いブロックとリセット ブロックは位置を直接交換します swapWhiteBlockAndCurrentBlock();//再帰を終了します return; }else{ if(whiteBlockX<resetBlockX){//白いブロックはリセット ブロックの左側にあります。右のwhiteBlockRight(); }else{/ /白いブロックはリセットブロックの右側にあります;白いブロックは左に移動しますwhiteBlockLeft(); ==resetBlockY) {//白いブロックとリセット ブロックは同じ行にあり、白いブロックは上に移動します if(whiteBlockX<resetBlockX){//左方向へ if(whiteBlockX<resetBlockX-1){//左方向へ multi -cellwhiteBlockRight(); } else{//左に 1 マス if(whiteBlockY==n-1){//最後whiteBlockUp(); if(resetBlockX==n-1){//リセット ブロックは右端にあり、反時計回りに移動できるのは白いブロックのみです。 /right ホワイトブロックアップ (); }else{//白いブロックはリセット ブロックの下にあります。白いブロックはリセット ブロックを超えて上に移動する必要があります。//3 つの状況: 左下、下、下。 right if(whiteBlockX<=resetBlockX) {//左下、下に白いブロックが移動します。 f(resetBlockX==n-1){//リセット ブロックは右端にあり、反時計回りに移動できないのは白いブロックのみです。 if(whiteBlockX==resetBlockX){//whiteBlockLeft() のすぐ下にあります。 }else{//左下whiteBlockUp(); }else{whiteBlockRight(); }else{//右下に移動whiteBlockUp();//Recursion /ホワイトブロックとリセットブロックの位置を交換します private void swapWhiteBlockAndCurrentBlock(){ step++;ホワイトブロック Y; int テンポ = パズル [ホワイトブロック Y] [ホワイトブロック X] = パズル [リセットブロック Y] [リセットブロック X] = テンポ; ホワイトブロック Y = リセットブロック X; ; リセットブロックY = 一時Y; println("swap"); } private voidwhiteBlockDown(){ step++; int temp = パズル[ホワイトブロックY][ホワイトブロックX] = パズル[ホワイトブロックY+1][ホワイトブロックX]; ][whiteBlockX] = temp; println("↓"); WhiteBlockUp(){ step++; int temp = パズル[whiteBlockY][whiteBlockX] = パズル[whiteBlockY-1][whiteBlockX]; ; println("↑"); } プライベート void WhiteBlockLeft(){ step++;パズル[ホワイトブロックY][ホワイトブロックX]; パズル[ホワイトブロックY][ホワイトブロックX-1]; パズル[ホワイトブロックY][ホワイトブロックX-1]; private void WhiteBlockRight(){ step++; int temp = パズル[whiteBlockY][whiteBlockX];パズル[ホワイトブロックY][ホワイトブロックX] = パズル[ホワイトブロックY][ホワイトブロックX+1] = temp; @Override public String toString(); = 新しい 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("-------------------------------------"); else{ sb.append("パズルは null") } return sb.toString(); } private String _str(String str,int len){ str=str==null?"":str; if(str.length()<len){ return _str(str+" , len); public static void main(String[] args); throws FileNotFoundException, UnsupportedEncodingException {// System.setOut(new PrintStream("e:/puzzle.txt","UTF-8")); パズル p = new Puzzle(); p.sort(); } catch (例外 e) { e.printStackTrace(); }最後に{ System.out.println(p) } }}
以上がこの記事の全内容です。皆さんに気に入っていただければ幸いです。