[Java] 小游戏 →→→→→进入此内容的聊天室

来自 , 2019-05-17, 写在 Java, 查看 115 次.
URL http://www.code666.cn/view/42d6c7d6
  1. import java.io.FileNotFoundException;
  2. import java.io.PrintStream;
  3. import java.io.UnsupportedEncodingException;
  4. import java.util.Random;
  5.  
  6. public class Puzzle {
  7.  private long step = 0;
  8.  private int n = 6;// 宫格基数
  9.  private int[][] puzzle;
  10.  private int resetBlock = 0;//
  11.  //空白块位置
  12.  private int whiteBlockX;
  13.  private int whiteBlockY;
  14.    
  15.  //当前要准备移动的块的坐标即复位块
  16.  private int resetBlockX;
  17.  private int resetBlockY;
  18.    
  19.  private boolean isPrint=false;
  20.    
  21.  public Puzzle() {
  22.   init();
  23.  }
  24.  
  25.  public Puzzle(int n) {
  26.   this.n = n;
  27.   init();
  28.  }
  29.  
  30.  private void init() {
  31.   puzzle = new int[n][n];
  32.   for (int y = 0; y < n; y++) {
  33.    for (int x = 0; x < n; x++) {
  34.     puzzle[y][x] = x + y * n;
  35.    }
  36.   }
  37.   whiteBlockX = n-1;
  38.   whiteBlockY = n-1;
  39.   int times = 100;// 打乱次数,必须是偶数
  40.   Random random = new Random();
  41.   while (times > 0) {
  42.    int x0 = random.nextInt(n);
  43.    int y0 = random.nextInt(n);
  44.    int x1 = random.nextInt(n);
  45.    int y1 = random.nextInt(n);
  46.    if (x0 != x1 && y0!=y1) {// 保证是偶排序
  47.     if((x0==n-1&&y0==n-1)||(x1==n-1&&y1==n-1)){//最后一个不调换
  48.      continue;
  49.     }
  50.     times--;
  51.     int t = puzzle[x0][y0];
  52.     puzzle[x0][y0] = puzzle[x1][y1];
  53.     puzzle[x1][y1] = t;
  54.    }
  55.   }
  56. //  int[][] p = {{22,9 ,1 ,5 ,0 ,25 },{
  57. //    33,23,20,26,18,21},{
  58. //    6 ,16,17,10,34,31},{
  59. //    19,28,32,7 ,3 ,2},{
  60. //    11,4 ,12,14,27,24},{
  61. //    15,29,30,8 ,13,35}};
  62. //  puzzle = p;
  63.  }
  64.    
  65.  public void sort(){
  66.   for (int y = 0; y < n; y++) {
  67.    for (int x = 0; x < n; x++) {
  68.     if (x == n - 1 && y == n - 1) {// 最后一个为空白,
  69.     } else {
  70.      reset(x, y);
  71.     }
  72.    }
  73.   }
  74.  }
  75.  //把块复位移动目标位置
  76.  private void reset(int targetX, int targetY) {
  77.   // 找到复位块当前的位置
  78.   initResetBlock(targetX, targetY);
  79.   /*
  80.    * 复位顺序是从左到右,从上到下
  81.    * 移动方式 先上移动,再左移动
  82.    * 当前复位块,它要复位的位置可分为 四种情况
  83.    * 1、不在最右边一行也不是最下面两行
  84.    * 2、最右边一行 x=n-1,但不是下面两行;
  85.    * 3、最下面两行 y=n-2,但不是最右边一行;
  86.    * 4、即使最右边的一行也是最下面两行
  87.    */
  88.   if(targetX < n-1 && targetY < n-2){
  89.    if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  90.     return;//退出递归
  91.    }
  92.    resetBlockToTarget(targetX, targetY);
  93.   }else if(targetX==n-1 && targetY < n-2){//第二种情况
  94.    if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  95.     return;//退出递归
  96.    }
  97.    reset2(targetX, targetY);
  98.   }else if(targetX < n-2 && targetY == n-2){
  99. //   isPrint=true;
  100.    reset3(targetX);
  101.    return;
  102.   }else{
  103.    initResetBlock(n-2, n-2);
  104.    resetBlockToTarget(n-2, n-2);
  105.    if(whiteBlockX<n-1){
  106.     whiteBlockRight();
  107.    }
  108.    if(whiteBlockY<n-1){
  109.     whiteBlockDown();
  110.    }
  111.    if(whiteBlockX==n-1&&whiteBlockY==n-1){
  112.     return;
  113.    }
  114.   }
  115.   reset(targetX, targetY);//递归
  116.  }
  117.  private void initResetBlock(int targetX,int targetY){
  118.   resetBlock = targetX + targetY * n;
  119.   for (int y = 0; y < n; y++) {
  120.    for (int x = 0; x < n; x++) {
  121.     if (puzzle[y][x] == resetBlock) {// x,y就是复位块的位置
  122.      resetBlockX = x;
  123.      resetBlockY = y;
  124.      break;
  125.     }
  126.    }
  127.   }
  128.  }
  129.  private void reset3(int targetX){
  130. //  if(targetX>=2){
  131. //  }
  132.   initResetBlock(targetX, n-1);
  133.   resetBlockToTarget(targetX, n-2);
  134.    
  135.   initResetBlock(targetX, n-2);
  136.   resetBlockToTarget(targetX+1, n-2);
  137.   l:
  138.   while (!(whiteBlockX==targetX && whiteBlockY==n-1)) {
  139.    if(whiteBlockY<n-1){
  140.     whiteBlockDown();
  141.     continue l;
  142.    }
  143.    if(whiteBlockX>targetX){
  144.     whiteBlockLeft();
  145.     continue l;
  146.    }
  147.    break;
  148.   }
  149.   whiteBlockUp();
  150.   swapWhiteBlockAndCurrentBlock();
  151.    
  152.   if(puzzle[n-2][targetX]!=resetBlock||puzzle[n-1][targetX]!=(resetBlock+n)){//没有复位成功
  153. //   isPrint=true;
  154.    swapWhiteBlockAndCurrentBlock();
  155.    reset3_0();
  156.    reset3(targetX);
  157.   }
  158.  }
  159.  private void reset3_0(){
  160.   if(resetBlockX<n-1){
  161.    whiteBlockDown();
  162.    whiteBlockRight();
  163.    whiteBlockRight();
  164.    whiteBlockUp();
  165.    swapWhiteBlockAndCurrentBlock();
  166.    reset3_0();
  167.    return;
  168.   }
  169.   return;
  170.  }
  171.    
  172.    
  173.  private void reset2_3(){
  174.   if(whiteBlockX==resetBlockX && whiteBlockY==resetBlockY+1){
  175.    return;//满足条件,退出递归
  176.   }
  177.   //白块可能在复位块的:左方、左下、下方
  178.   if(whiteBlockY==resetBlockY){//左方
  179.    whiteBlockDown();
  180.   }else if(whiteBlockX < resetBlockX){//左下
  181.    whiteBlockRight();
  182.   }else {
  183.    whiteBlockUp();
  184.   }
  185.   reset2_3();//递归
  186.  }
  187.    
  188.  private void reset2_2(int targetX, int targetY){
  189.   if(resetBlockX==targetX&&resetBlockY==targetY){//2、把复位块移到目标位置正下方
  190.    return;//退出递归
  191.   }
  192.    
  193.   //复位块可能位置,目标位置左方、正下方、左下方
  194.   if(resetBlockX==targetX){//正下方 上移
  195.    resetBlockUp(targetX, targetY);
  196.   }else{//左方或左下方;先右移再上移
  197.    resetBlockRight(targetX, targetY);
  198.   }
  199.   reset2_2(targetX, targetY);//递归
  200.  }
  201.  
  202.  private void reset2(int targetX, int targetY){
  203.   if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  204.    return;//退出递归
  205.   }
  206.   /* 1、如果白块正好占了目标位置:如果复位块正好在下方,交换及完成复位,如果下方不是复位块,把白块移开目标位置
  207.    * 2、把复位块移到目标位置正下方
  208.    * 3、把白块移动复位块下方
  209.    * 4、按照规定的步骤复位
  210.    */
  211.   //第一步
  212.   if(whiteBlockX==targetX&& whiteBlockY==targetY){
  213.    if(whiteBlockX==resetBlockX&&whiteBlockY==resetBlockY+1){//复位块在下方
  214.     swapWhiteBlockAndCurrentBlock();
  215.     return;
  216.    }else{
  217.     whiteBlockDown();
  218.    }
  219.   }
  220.   //第二步 把复位块移到目标位置正下方
  221.   reset2_2(targetX, targetY+1);
  222.   //第三步 把白块移动复位块下方
  223.   reset2_3();
  224.   //第四步 按照规定的步骤复位
  225.   swapWhiteBlockAndCurrentBlock();
  226.   whiteBlockLeft();
  227.   whiteBlockUp();
  228.   whiteBlockRight();
  229.   whiteBlockDown();
  230.   whiteBlockLeft();
  231.   whiteBlockUp();
  232.   whiteBlockRight();
  233.   whiteBlockDown();
  234.   swapWhiteBlockAndCurrentBlock();
  235.   whiteBlockLeft();
  236.   whiteBlockUp();
  237.   whiteBlockUp();
  238.   whiteBlockRight();
  239.   swapWhiteBlockAndCurrentBlock();
  240.  }
  241.    
  242.  private void resetBlockToTarget(int targetX, int targetY){
  243.   if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  244.    return;//退出递归
  245.   }
  246.    
  247.   if(resetBlockY==targetY){//正左
  248.    resetBlockLeft(targetX, targetY);
  249.   }else{//左下,下,右下
  250.    if(resetBlockX>=targetX){//右下||下;上移
  251.     if(resetBlockX==n-1){//复位块在最右边,先左移;方便上移时统一的采用白块逆时针方式
  252.      resetBlockLeft(targetX, targetY);
  253.     }else{
  254.      resetBlockUp(targetX, targetY);
  255.     }
  256.    }else{//左下;右移
  257.     resetBlockRight(targetX, targetY);
  258.    }
  259.   }
  260.   resetBlockToTarget(targetX, targetY);//递归
  261.  }
  262.    
  263.  private void resetBlockRight(int targetX, int targetY){
  264.   if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  265.    return;//退出递归
  266.   }
  267.   if(resetBlockX==n-1){//复位块在最右边了,无法右移,直接退出
  268.    return;
  269.   }
  270. //  System.out.println("resetBlockRight");
  271.   if(whiteBlockY<resetBlockY){//上方
  272.    if(whiteBlockY<resetBlockY-1){//上方多行
  273.     whiteBlockDown();
  274.    }else{//上方一行
  275.     if(whiteBlockX<resetBlockX+1){//左上和正上
  276.      whiteBlockRight();
  277.     }else{//右上
  278.      whiteBlockDown();
  279.     }
  280.    }
  281.   }else if(whiteBlockY==resetBlockY){//同一行
  282.    if(whiteBlockX<resetBlockX){//左方
  283.     if(whiteBlockY==n-1){//到底了,只能往上
  284.      whiteBlockUp();
  285.     }else{
  286.      whiteBlockDown();
  287.     }
  288.    }else{//右方
  289.     if(whiteBlockX==resetBlockX+1){
  290.      swapWhiteBlockAndCurrentBlock();
  291.      return;//退出递归
  292.     }else{
  293.      whiteBlockLeft();
  294.     }
  295.    }
  296.   }else{//下方
  297.    if(whiteBlockX <= resetBlockX){//左下、下
  298.     whiteBlockRight();
  299.    }else{//右下
  300.     whiteBlockUp();
  301.    }
  302.   }
  303.   resetBlockRight(targetX, targetY);//递归
  304.  }
  305.    
  306.  private void resetBlockLeft(int targetX, int targetY){
  307.   if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  308.    return;//退出递归
  309.   }
  310.   if(resetBlockX==0){//在左边边界 复位块无法左移,直接退出递归
  311.    return;
  312.   }
  313. //  System.out.println("resetBlockLeft");
  314.   if(whiteBlockY<resetBlockY){//上方
  315.    if(whiteBlockY<resetBlockY-1){//上方多行
  316.     whiteBlockDown();
  317.    }else{//上方一行
  318.     if(whiteBlockX==resetBlockX){//上方
  319.      if(whiteBlockX==n-1){//最右边,白块无法右移,只能左移
  320.       whiteBlockLeft();
  321.      }else{
  322.       if(resetBlockY==n-1){//复位块在最低端,白块不能顺时针移动
  323.        whiteBlockLeft();
  324.       }else{
  325.        whiteBlockRight();
  326.       }
  327.      }
  328.     }else if(whiteBlockX>resetBlockX){//右上方
  329.      if(resetBlockY==n-1){//复位块在最低端,白块不能顺时针移动
  330.       whiteBlockLeft();
  331.      }else{
  332.       whiteBlockDown();
  333.      }
  334.     }else{//左上方
  335.      whiteBlockDown();
  336.     }
  337.    }
  338.   }else if(whiteBlockY==resetBlockY){//左方、右方
  339.    if(whiteBlockX<resetBlockX){//左方
  340.     if(whiteBlockX==resetBlockX-1){//左边一格
  341.      swapWhiteBlockAndCurrentBlock();//退出递归
  342.      return;
  343.     }else{
  344.      whiteBlockRight();
  345.     }
  346.    }else{//右方
  347.     if(whiteBlockY==n-1){//到底了,不能下移。只能上移
  348.      whiteBlockUp();
  349.     }else{
  350.      whiteBlockDown();
  351.     }
  352.    }
  353.   }else{//左下、下方、右下
  354.    if(whiteBlockX<resetBlockX){//左下
  355.     if(whiteBlockX==resetBlockX-1){
  356.      whiteBlockUp();
  357.     }else{
  358.      whiteBlockRight();
  359.     }
  360.    }else{//下方、右下
  361.     whiteBlockLeft();
  362.    }
  363.   }
  364.   resetBlockLeft(targetX, targetY);//递归
  365.  }
  366.    
  367.  private void resetBlockUp(int targetX, int targetY){
  368.   if(resetBlockX==targetX&&resetBlockY==targetY){//位置正确不用移动
  369.    return;//退出递归
  370.   }
  371.   if(resetBlockY==0){//复位块到顶了,无法上移
  372.    return;
  373.   }
  374. //  System.out.println("resetBlockUp");
  375.   if (whiteBlockY < resetBlockY) {//上方
  376.    if(whiteBlockY < resetBlockY - 1){//上方多行
  377.     whiteBlockDown();
  378.    }else{//上方一行
  379.     if(whiteBlockX == resetBlockX){//白块和复位块在同一列(竖列) 白块和复位块直接交换位置
  380.      swapWhiteBlockAndCurrentBlock();//退出递归
  381.      return;
  382.     }else{
  383.      if(whiteBlockX<resetBlockX){//白块在复位块的左边;白块右移
  384.       whiteBlockRight();
  385.      }else{//白块在复位块的右边;白块左移
  386.       whiteBlockLeft();
  387.      }
  388.     }
  389.    }
  390.   } else if (whiteBlockY == resetBlockY) {//白块和复位块同一行;白块上移
  391.    if(whiteBlockX<resetBlockX){//正左
  392.     if(whiteBlockX<resetBlockX-1){//正左多格
  393.      whiteBlockRight();
  394.     }else{//正左一格
  395.      if(whiteBlockY==n-1){//到底了
  396.       whiteBlockUp();
  397.      }else {
  398.       if(resetBlockX==n-1){//复位块在最右边,无法逆时针,只有顺指针移动白块
  399.        whiteBlockUp();
  400.       }else{
  401.        whiteBlockDown();
  402.       }
  403.      }
  404.     }
  405.    }else{//正右
  406.     whiteBlockUp();
  407.    }
  408.   }else{//白块在复位块下方,白块需要饶过复位块上移,白块逆时针绕到白块上面
  409.    //三种情况:左下,下,右下
  410.    if(whiteBlockX<=resetBlockX){//左下,下;白块右移
  411.     if(resetBlockX==n-1){//复位块在最右边,无法逆时针,只有顺指针移动白块
  412.      if(whiteBlockX==resetBlockX){//正下方
  413.       whiteBlockLeft();
  414.      }else{//左下方
  415.       whiteBlockUp();
  416.      }
  417.     }else{
  418.      whiteBlockRight();
  419.     }
  420.    }else{//右下;白块上移
  421.     whiteBlockUp();
  422.    }
  423.   }
  424.   resetBlockUp(targetX, targetY);//递归
  425.  }
  426.    
  427.  //白块和复位块交换位置
  428.  private void swapWhiteBlockAndCurrentBlock(){
  429.   step++;
  430.   int tempX = whiteBlockX,tempY = whiteBlockY;
  431.   int temp = puzzle[whiteBlockY][whiteBlockX];
  432.   puzzle[whiteBlockY][whiteBlockX] = puzzle[resetBlockY][resetBlockX];
  433.   puzzle[resetBlockY][resetBlockX] = temp;
  434.   whiteBlockX = resetBlockX;
  435.   whiteBlockY = resetBlockY;
  436.   resetBlockX = tempX;
  437.   resetBlockY = tempY;
  438.   println("swap");
  439.  }
  440.    
  441.  private void whiteBlockDown(){
  442.   step++;
  443.   int temp = puzzle[whiteBlockY][whiteBlockX];
  444.   puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY+1][whiteBlockX];
  445.   puzzle[whiteBlockY+1][whiteBlockX] = temp;
  446.   whiteBlockY++;
  447.   println("↓");
  448.  }
  449.  private void whiteBlockUp(){
  450.   step++;
  451.   int temp = puzzle[whiteBlockY][whiteBlockX];
  452.   puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY-1][whiteBlockX];
  453.   puzzle[whiteBlockY-1][whiteBlockX] = temp;
  454.   whiteBlockY--;
  455.   println("↑");
  456.  }
  457.    
  458.  private void whiteBlockLeft(){
  459.   step++;
  460.   int temp = puzzle[whiteBlockY][whiteBlockX];
  461.   puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY][whiteBlockX-1];
  462.   puzzle[whiteBlockY][whiteBlockX-1] = temp;
  463.   whiteBlockX--;
  464.   println("←");
  465.  }
  466.  private void whiteBlockRight(){
  467.   step++;
  468.   int temp = puzzle[whiteBlockY][whiteBlockX];
  469.   puzzle[whiteBlockY][whiteBlockX] = puzzle[whiteBlockY][whiteBlockX+1];
  470.   puzzle[whiteBlockY][whiteBlockX+1] = temp;
  471.   whiteBlockX++;
  472.   println("→");
  473.  }
  474.    
  475.    
  476.  @Override
  477.  public String toString() {
  478.   StringBuilder sb = new StringBuilder();
  479.   sb.append("resetBlock=("+resetBlock+","+resetBlockX+","+resetBlockY+")\n");
  480.   if(puzzle!=null){
  481.    int len = String.valueOf(n*2-1).length();
  482.    for (int y = 0; y < n; y++) {
  483.     for (int x = 0; x < n; x++) {
  484.      if(x>0){
  485.       sb.append(",");
  486.      }
  487.      sb.append(_str(String.valueOf(puzzle[y][x]), len));
  488.     }
  489.     sb.append("\n");
  490.    }
  491.    sb.append("---------------------------------------");
  492.   }else{
  493.    sb.append("puzzle is null");
  494.   }
  495.   return sb.toString();
  496.  }
  497.  private String _str(String str,int len){
  498.   str=str==null?"":str;
  499.   if(str.length()<len){
  500.    return _str(str+" ", len);
  501.   }
  502.   return str;
  503.  }
  504.    
  505.  private void println(String str){
  506.   if(isPrint){
  507.    System.out.println(str);
  508.    System.out.println(this);
  509.   }
  510.  }
  511.  
  512.  public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
  513. //  System.setOut(new PrintStream("e:/puzzle.txt","UTF-8"));
  514.   Puzzle p = new Puzzle();
  515.   System.out.println(p);
  516.   try {
  517.    p.sort();
  518.   } catch (Exception e) {
  519.    e.printStackTrace();
  520.    System.out.println("Exception:");
  521.   }finally{
  522.    System.out.println(p);
  523.   }
  524.  }
  525. }

回复 "小游戏"

这儿你可以回复上面这条便签

captcha