Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 骑士';s循环/递归_Java - Fatal编程技术网

Java 骑士';s循环/递归

Java 骑士';s循环/递归,java,Java,我试图学习更多关于递归的知识,但不知怎么的,我无法解决骑士之旅,我希望有人能指出我的逻辑错误 class main { static int fsize = 5; // board size (5*5) static int board[][] = new int[fsize][fsize]; static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis) static

我试图学习更多关于递归的知识,但不知怎么的,我无法解决骑士之旅,我希望有人能指出我的逻辑错误

class main {

    static int fsize = 5; // board size (5*5)
    static int board[][] = new int[fsize][fsize];
    static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
    static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)

    // x = current x coordinate
    // y = current y coordinate
    static void Solve(int move_number, int x, int y) {
        board[x][y] = move_number;

        // check whether the knight has been on all filds or not
        if (move_number == ((fsize * fsize) - 1)) {
            for (int i = 0; i < fsize; i++) {
                for (int c = 0; c < fsize; c++) {
                    System.out.printf("%3d", board[i][c]);
                }
                System.out.println("\n");
            }
        } 
        else {
            // calculate new board coordinates
            for (int i = 0; i < 8; i++) {
                for (int c = 0; c < 8; c++) {
                    // Check whether the new coordinates are valid or not
                    if ((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize && (y + move_y[c]) >= 0 && (y + move_y[c]) < fsize) {
                        // check whether the knight has been on this field or not (-1 = hasn't been here)
                        if (board[x + move_x[i]][y + move_y[c]] == -1) {
                            System.out.println("Move: " + move_number + "\n");
                            // Find next field
                            Solve(move_number + 1, (x + move_x[i]), (y + move_y[c]));
                        }
                    }
                }
            }
            // couldn't find a valid move
            board[x][y] = -1;
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < fsize; i++) {
            for (int c = 0; c < fsize; c++) {
                board[i][c] = -1;
            }
        }

        Solve(0, 0, 0);
    }
}
主类{
静态int fsize=5;//电路板大小(5*5)
静态int板[][]=新int[fsize][fsize];
static int[]move_x={1,2,2,1,-1,-2,-2,-1};//可能的移动(x轴)
static int[]move_y={-2,-1,1,2,2,1,-1,-2};//可能的移动(y轴)
//x=当前x坐标
//y=当前y坐标
静态无效解算(整数移动_数,整数x,整数y){
板[x][y]=移动编号;
//检查骑士是否在所有场上
if(move_number==((fsize*fsize)-1)){
对于(int i=0;i=0&&(x+move_x[i])=0&(y+move_y[c])

编辑:希望这是好的。我试着运行这个程序,但不能得到超过22个有效的动作。

嗯,所以我试了一下,试图弄清楚到底发生了什么。这是我能收集到的

  • sprung_x
    sprung_y
    应该一起移动,因为它们代表骑士的移动。您有
    c
    i
    作为在这些数组上移动的独立索引,但实际上它应该只有1个变量。我敲打内部
    for
    循环,在看到
    c
    的地方使用
    I
  • 在方法
    SucheWeg
    的末尾,将调用它的单元格重置为-1。这给我带来了无限循环。删除该行允许它在单元格1、2的19个移动中正常完成。根据骑士之旅的定义,即从(0,0)开始的牢房向外移动1次攻击,因此代表一次完整的旅行
  • 根据,您的
    fsize
    (共5个)可能未完成。我用6来代替测试
  • 你需要考虑当你到达终点时会发生什么。在您的代码中,在最后一步有一个打印输出,但是方法
    SucheWeg
    仍将继续运行,并且需要一种正常终止的方法。如果遇到死胡同(我假设-1重置是从#2开始的),你必须考虑到决策的展开,但也要意识到,如果你不小心,同样的展开将使决策永远进行下去**当您从方法返回时,在撤消步骤之前,应检查电路板是否已满。如果已满,则表示您已到达终点

  • 仅向您展示我使用的代码:

    static boolean isFull(int b [][])
    {
       for(int i = 0; i < b.length; i++)
       {
          for(int k = 0; k < b[i].length; k++)
          {
             if(b[i][k] == -1) return false;
          }
       }
       return true;
    }
    
    static void SucheWeg(int schrittnummer, int x, int y)
    {
       board[x][y] = schrittnummer;
       if(schrittnummer == ((fsize * fsize) - 1)) return;
    
       for(int i = 0; i < 8; i++)
       {
          int nextX = x + sprung_x[i];
          int nextY = y + sprung_y[i];
    
          // if we can visit the square, visit it
          if(nextX >= 0 && nextX < fsize && nextY >= 0 && nextY < fsize)
          {
             if(board[nextX][nextY] == -1)
             {
                SucheWeg(schrittnummer + 1, nextX, nextY);
             }
          }
       }
       if(isFull(board)) return;  // this is how we avoid resetting to -1
       board[x][y] = -1;          // reset if you get this far, so you can try other routes
    }
    
    输出为:

    00 33 28 17 30 35 
    27 18 31 34 21 16 
    32 01 20 29 10 05 
    19 26 11 06 15 22 
    02 07 24 13 04 09 
    25 12 03 08 23 14
    

    我想说最后一件事——该算法的良好实现将捕获无限循环。如果这实际上是作业,您应该修改它,直到您可以在任何大小的板上运行它,而不必担心无限循环。目前,如果没有解决方案,它可能会永远运行。

    因为它看起来有点像家庭作业问题,我将从一个提示开始


    move_x
    move_y
    是骑士可能的x,y移动。但是,这些可以单独编制索引(
    i
    c
    )。您可能希望重新考虑这一点。

    问题是,即使第一次尝试移动成功(导致解决方案),您也在尝试不同的有效移动。我会让函数返回一个布尔值,指定它是否达到了一个解决方案。因此,当您从函数本身调用函数时,您应该只尝试下一个有效移动,如果它返回
    false
    。此外,当您尝试其他移动时,您应该清除上一个移动(因为阵列已更改)


    编辑:

    class main {
    
    static int fsize = 5; // board size (5*5)
    static int board[][] = new int[fsize][fsize];
    static int[] move_x = {1, 2, 2, 1, -1, -2, -2, -1}; // possible moves (x-axis)
    static int[] move_y = {-2, -1, 1, 2, 2, 1, -1, -2}; // possible moves (y-axis)
    
    // x = current x coordinate
    // y = current y coordinate
    static boolean solve(int move_number, int x, int y)
    {
        boolean ret = true;
        board[x][y] = move_number;
        if(move_number == ((fsize * fsize) - 1))
        {
            for(int i = 0; i < fsize; i++)
            {
                for(int c = 0; c < fsize; c++)
                {
                    System.out.printf("%3d", board[i][c]);
                }
                System.out.println("\n");
            }
        }
        else
        {
            for(int i = 0; i < 8; i++)
            {
                if((x + move_x[i]) >= 0 && (x + move_x[i]) < fsize
                        && (y + move_y[i]) >= 0
                        && (y + move_y[i]) < fsize)
                {
                    if(board[x + move_x[i]][y + move_y[i]] == -1)
                    {
                        if (solve(move_number + 1, (x + move_x[i]), (y + move_y[i]))) {
                            break;
                        }
                    }
                }
            }
            ret = false;
            board[x][y] = -1;
        }
        return ret;
    }
    public static void main(String[] args) {
        for (int i = 0; i < fsize; i++) {
            for (int c = 0; c < fsize; c++) {
                board[i][c] = -1;
            }
        }
    
        solve(0, 0, 0);
    }
    

    我可以通过做两件事来修复您的代码:

    • 仅使用
      for(int i=0;i<8;i++)
      单级循环检查接下来的8种可能性
      • 为什么这里有两个嵌套循环?你只需要检查这8种可能性,就这样
      • 每个级别只有8个移动,而不是64个
    • 使
      板[x][y]=-1求解中的最后一条语句
      
      • 您希望在不考虑
        if
        条件的情况下执行此操作
      • 撤消
        板[x][y]=移动编号退出此级别之前
    修好这些之后,你的作业就完成了,正确了,完成了。恭喜你


    伪码 现在,这就是你所拥有的:

    static void Solve(int move_number, int x, int y) {
        board[x][y] = move_number;
    
        if (DONE) {
           PRINT;
        } else {
            for (int i = 0; i < 8; i++) {
                for (int c = 0; c < 8; c++) {
                    ATTEMPT_MOVE(i, c); // doesn't make sense!!!
                }
            }
            board[x][y] = -1; // this doesn't belong here!!!
        }
    }
    
    static void Solve(int move_number,int x,int y){
    板[x][y]=移动编号;
    如果(完成){
    印刷品;
    }否则{
    对于(int i=0;i<8;i++){
    对于(int c=0;c<8;c++){
    尝试移动(i,c);//没有意义!!!
    }
    }
    
     0 15 20  9 24
    
     19 10 23 14 21
    
     16  1 18  5  8
    
     11  6  3 22 13
    
    static void Solve(int move_number, int x, int y) {
        board[x][y] = move_number;
    
        if (DONE) {
           PRINT;
        } else {
            for (int i = 0; i < 8; i++) {
                for (int c = 0; c < 8; c++) {
                    ATTEMPT_MOVE(i, c); // doesn't make sense!!!
                }
            }
            board[x][y] = -1; // this doesn't belong here!!!
        }
    }
    
    static void Solve(int move_number, int x, int y) {
        board[x][y] = move_number;
    
        if (DONE) {
           PRINT;
        } else {
            for (int i = 0; i < 8; i++) {
               ATTEMPT_MOVE(i); // now makes more sense!
            }
        }
    
        board[x][y] = -1; // must undo assignment in first line!
    }