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 n = 6;// 宫格基数 private int[][] puzzle; private int resetBlock = 0;// //空白块位置 private int whiteBlockX; private int whiteBlockY; //当前要准备移动的块的坐标即复位块 private int resetBlockX; private int resetBlockY; private boolean isPrint=false; public Puzzle() { init(); } public Puzzle(int n) { this.n = n; init(); } private void init() { puzzle = new int[n][n]; for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { puzzle[y][x] = x + y * n; } } whiteBlockX = n-1; whiteBlockY = n-1; int times = 100;// 打乱次数,必须是偶数 Random random = new Random(); while (times > 0) { int x0 = random.nextInt(n); int y0 = 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)){//最后一个不调换 continue; } times--; int t = puzzle[x0][y0]; puzzle[x0][y0] = puzzle[x1][y1]; puzzle[x1][y1] = t; } } // int[][] 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(){ for (int y = 0; y < n; y++) { for (int x = 0; x < n; x++) { if (x == n - 1 && y == n - 1) {// 最后一个为空白, } else { reset(x, y); } } } } //把块复位移动目标位置 private void reset(int targetX, int targetY) { // 找到复位块当前的位置 initResetBlock(targetX, targetY); /* * 复位顺序是从左到右,从上到下 * 移动方式 先上移动,再左移动 * 当前复位块,它要复位的位置可分为 四种情况 * 1、不在最右边一行也不是最下面两行 * 2、最右边一行 x=n-1,但不是下面两行; * 3、最下面两行 y=n-2,但不是最右边一行; * 4、即使最右边的一行也是最下面两行 */ if(targetX < n-1 && targetY < n-2){ if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动 return;//退出递归 } resetBlockToTarget(targetX, targetY); }else if(targetX==n-1 && targetY < n-2){//第二种情况 if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动 return;//退出递归 } reset2(targetX, targetY); }else if(targetX < n-2 && targetY == n-2){ // isPrint=true; reset3(targetX); return; }else{ initResetBlock(n-2, n-2); resetBlockToTarget(n-2, n-2); if(whiteBlockX=2){ // } initResetBlock(targetX, n-1); resetBlockToTarget(targetX, n-2); initResetBlock(targetX, n-2); resetBlockToTarget(targetX+1, n-2); l: while (!(whiteBlockX==targetX && whiteBlockY==n-1)) { if(whiteBlockYtargetX){ whiteBlockLeft(); continue l; } break; } whiteBlockUp(); swapWhiteBlockAndCurrentBlock(); if(puzzle[n-2][targetX]!=resetBlock||puzzle[n-1][targetX]!=(resetBlock+n)){//没有复位成功 // isPrint=true; swapWhiteBlockAndCurrentBlock(); reset3_0(); reset3(targetX); } } private void reset3_0(){ if(resetBlockX=targetX){//右下||下;上移 if(resetBlockX==n-1){//复位块在最右边,先左移;方便上移时统一的采用白块逆时针方式 resetBlockLeft(targetX, targetY); }else{ resetBlockUp(targetX, targetY); } }else{//左下;右移 resetBlockRight(targetX, targetY); } } resetBlockToTarget(targetX, targetY);//递归 } private void resetBlockRight(int targetX, int targetY){ if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动 return;//退出递归 } if(resetBlockX==n-1){//复位块在最右边了,无法右移,直接退出 return; } // System.out.println("resetBlockRight"); if(whiteBlockYresetBlockX){//右上方 if(resetBlockY==n-1){//复位块在最低端,白块不能顺时针移动 whiteBlockLeft(); }else{ whiteBlockDown(); } }else{//左上方 whiteBlockDown(); } } }else if(whiteBlockY==resetBlockY){//左方、右方 if(whiteBlockX0){ sb.append(","); } sb.append(_str(String.valueOf(puzzle[y][x]), len)); } sb.append("\n"); } sb.append("---------------------------------------"); }else{ sb.append("puzzle is null"); } return sb.toString(); } private String _str(String str,int len){ str=str==null?"":str; if(str.length()