Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.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 骑士最短路径测试案例在foobar中失败_Java_Algorithm - Fatal编程技术网

Java 骑士最短路径测试案例在foobar中失败

Java 骑士最短路径测试案例在foobar中失败,java,algorithm,Java,Algorithm,我遇到了谷歌foobar问题的麻烦。我只有一个测试不及格。我想确定一个骑士在测试板上的点之间移动的最小移动次数。算法如下所示 import java.lang.Math; public class Answer { public static int answer(int start, int end) { int[][] board = new int[8][8]; int[] startLocation = new int[2]; int[] end

我遇到了谷歌foobar问题的麻烦。我只有一个测试不及格。我想确定一个骑士在测试板上的点之间移动的最小移动次数。算法如下所示

import java.lang.Math;

public class Answer {   
    public static int answer(int start, int end) {

    int[][] board = new int[8][8];
    int[] startLocation = new int[2];
    int[] endLocation = new int[2];


    //chess board generated in nested loop
    for (int j = 0; j < 8; j++) {
        int[] row = new int[8];
        for (int i = 0; i < 8; i++) {
            row[i] = i + 8 * j;
        }
        board[j] = row;
    }

    //find locations of start and end points on board
    for (int m = 0; m < 8; m++){
        for (int n = 0; n < 8; n++){
            if (board[m][n] == start) startLocation = new int[]{m,n};
            if (board[m][n] == end) endLocation = new int[]{m,n};
        }
    }

    int[] delta = new int[]{Math.abs(endLocation[0] - startLocation[0]),Math.abs(endLocation[1]-startLocation[1])};

    if (delta[0] < delta[1]){
        int temp = delta[0];
        delta[0] = delta[1];
        delta[1] = temp;
    }
    //generate double array of possible moves
    if (delta[0] == 2 & delta[1] == 1) return 1;
    if ((delta[0]+ delta[1] == 2) || (delta[0] == 3 && delta[1] == 1) || 
            (delta[0] == 3 && delta[1] == 3) || (delta[0] == 4 && delta[1] == 2) || (delta[0] == 4 && delta[1] == 0)){
        return 2;
    }
    if ((delta[0] == 1 && delta[1] == 0) || (delta[0] == 3 && delta[1] == 0) || 
            (delta[0] == 5 && delta[1] == 0) || (delta[0] == 3 && delta[1] == 2) || (delta[0] == 4 && delta[1] == 3)
            || (delta[0] == 4 && delta[1] == 1) || (delta[0] == 6 && delta[1] == 1) || (delta[0] == 6 && delta[1] == 3)
            || (delta[0] == 5 && delta[1] == 2) || (delta[0] == 5 && delta[1] == 4)){
        return 3;
    }
    if ((delta[0] == 6 && delta[1] == 0) || (delta[0] == 2 && delta[1] == 2) ||
            (delta[0] == 5 && delta[1] == 1) || (delta[0] == 7 && delta[1] == 1) || (delta[0] == 6 && delta[1] == 2)
            || (delta[0] == 7 && delta[1] == 5) || (delta[0] == 7 && delta[1] == 3) || (delta[0] == 5 && delta[1] == 3)
            || (delta[0] == 4 && delta[1] == 4) || (delta[0] == 5 && delta[1] == 5) || (delta[0] == 6 && delta[1] == 6)
            || (delta[0] == 6 && delta[1] == 4)){
        return 4;
    }
    if ((delta[0] == 7 && (delta[1] == 0 || delta[1] == 2 || delta[1] == 4 || delta[1] == 6)) || (delta[0] == 6 && delta[1] == 5)){
        return 5;
    }
    return 6;
}
}
import java.lang.Math;
公共类答案{
公共静态整数应答(整数开始,整数结束){
int[][]板=新int[8][8];
int[]位=新的int[2];
int[]endLocation=新的int[2];
//嵌套循环生成的棋盘
对于(int j=0;j<8;j++){
int[]行=新int[8];
对于(int i=0;i<8;i++){
行[i]=i+8*j;
}
board[j]=行;
}
//查找板上起点和终点的位置
对于(int m=0;m<8;m++){
对于(int n=0;n<8;n++){
if(board[m][n]==start)startLocation=newint[]{m,n};
如果(board[m][n]==end)endLocation=newint[]{m,n};
}
}
int[]delta=newint[]{Math.abs(endLocation[0]-startLocation[0]),Math.abs(endLocation[1]-startLocation[1]);
if(增量[0]<增量[1]){
内部温度=增量[0];
δ[0]=δ[1];
δ[1]=温度;
}
//生成可能移动的双数组
if(delta[0]==2&delta[1]==1)返回1;
如果((δ[0]+δ[1]==2)| |(δ[0]==3&&δ[1]==1)| |
(δ[0]==3和δ[1]==3)| |(δ[0]==4和δ[1]==2)| |(δ[0]==4和δ[1]==0)){
返回2;
}
如果((δ[0]==1&&δ[1]==0)| |(δ[0]==3&&δ[1]==0)| |
(δ[0]==5和δ[1]==0)| |(δ[0]==3和δ[1]==2)| |(δ[0]==4和δ[1]==3)
||(δ[0]==4和δ[1]==1)| |(δ[0]==6和δ[1]==1)| |(δ[0]==6和δ[1]==3)
||(δ[0]==5&&δ[1]==2)| |(δ[0]==5&&δ[1]==4)){
返回3;
}
如果((δ[0]==6&&δ[1]==0)| |(δ[0]==2&&δ[1]==2)||
(δ[0]==5和δ[1]==1)| |(δ[0]==7和δ[1]==1)| |(δ[0]==6和δ[1]==2)
||(δ[0]==7和δ[1]==5)| |(δ[0]==7和δ[1]==3)| |(δ[0]==5和δ[1]==3)
||(δ[0]==4和δ[1]==4)| |(δ[0]==5和δ[1]==5)| |(δ[0]==6和δ[1]==6)
||(增量[0]==6和增量[1]==4)){
返回4;
}
如果((δ[0]==7&&(δ[1]==0 | |δ[1]==2 | | |δ[1]==4 | | |δ[1]==6&&δ[1]==5)){
返回5;
}
返回6;
}
}

在什么情况下此代码会失败?

如果开始是
0,0
,结束是
1,1
,您的答案是
2
移动,但这需要在棋盘外着陆。当然,其他三个角也是这样


更新

为了好玩,我决定编写代码来找到最短的路径(无论如何是其中一条),并打印所采用的路径

代码

输出

2:2,2->4,1->3,3
+---------------+
|               |
|        1      |
|    0          |
|      2        |
|               |
|               |
|               |
|               |
+---------------+
4:0,0->2,1->0,2->2,3->1,1
+---------------+
|0              |
|  4 1          |
|2              |
|    3          |
|               |
|               |
|               |
|               |
+---------------+
6:0,0->2,1->3,3->5,4->7,5->5,6->7,7
+---------------+
|0              |
|    1          |
|               |
|      2        |
|          3    |
|              4|
|          5    |
|              6|
+---------------+
5:0,0->1,2->3,3->5,4->7,5->6,7
+---------------+
|0              |
|               |
|  1            |
|      2        |
|          3    |
|              4|
|               |
|            5  |
+---------------+
6:7,7->6,5->4,4->3,2->2,0->1,2->0,0
+---------------+
|6   4          |
|               |
|  5   3        |
|               |
|        2      |
|            1  |
|               |
|              0|
+---------------+

我没有考虑的测试用例是当“开始在结束”位置为一且相同时。这是解决方案中缺少的一部分…

欢迎使用堆栈溢出。这不是调试服务。你应该自己提出一些测试用例。您甚至可以编写一个测试程序来生成所有64*64可能的输入。看看那些你最难用手解决的问题…然后用手解决它们,看看它们是否与你的算法的输出相匹配。注意,如果你考虑到棋盘的所有对称性,你可以显著减少可能的输入数量。例如,从左上角移动到右上角是从左下角移动到右下角的镜像。因此,两种情况下所需的移动次数将完全相同。事实上,您可以在测试中使用它来确保两种情况下得到相同的答案。如果您没有,那么您知道您的代码有问题。不幸的是,如果你得到了相同的答案,那么它不会告诉你太多。你基本上预先计算了所有可能的情况。“很可能你在其中一个问题上犯了错误。”代码学徒,注释的作者。我已经考虑到对称性,并手工求解了几对……我将尝试求解更多……我建议您开发一种算法来计算所需的移动次数,而不是将解编码为一组if语句。用算法解决问题是计算机程序员最重要的技能之一。代码基于相对定位。起点是
class Path {
    private final int  x;
    private final int  y;
    private final int  moveNo;
    private final Path prev;
    private Path(int x, int y, int moveNo, Path prev) {
        this.x = x;
        this.y = y;
        this.moveNo = moveNo;
        this.prev = prev;
    }
    public static Path startAt(int x, int y) {
        if (x < 0 || x >= 8 || y < 0 || y >= 8)
            throw new IllegalArgumentException("Invalid position: " + x + "," + y);
        return new Path(x, y, 0, null);
    }
    public Path move(Move move) {
        int newX = this.x + move.getX();
        int newY = this.y + move.getY();
        if (newX < 0 || newX >= 8 || newY < 0 || newY >= 8)
            return null; // Outside board
        for (Path step = this.prev; step != null; step = step.prev)
            if (step.x == newX && step.y == newY)
                return null; // Backstep
        return new Path(newX, newY, this.moveNo + 1, this);
    }
    public int getX() {
        return this.x;
    }
    public int getY() {
        return this.y;
    }
    public int getNumberOfMoves() {
        return this.moveNo;
    }
    @Override
    public String toString() {
        if (this.prev == null)
            return this.x + "," + this.y;
        return this.prev + " -> " + this.x + "," + this.y;
    }
    public void printBoard() {
        char[][] board = new char[8][15];
        for (char[] row : board)
            Arrays.fill(row, ' ');
        for (Path step = this; step != null; step = step.prev)
            board[step.y][step.x * 2] = Character.forDigit(step.moveNo, 36);
        System.out.println("  +---------------+");
        for (char[] row : board)
            System.out.println("  |" + new String(row) + "|");
        System.out.println("  +---------------+");
    }
}

class Move {
    private static final Move[] KNIGHT_MOVES = {
            new Move(-1, -2), new Move( 1, -2),
            new Move( 2, -1), new Move( 2,  1),
            new Move( 1,  2), new Move(-1,  2),
            new Move(-2,  1), new Move(-2, -1) };
    private final int  x;
    private final int  y;
    public Move(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() {
        return this.x;
    }
    public int getY() {
        return this.y;
    }
    public static Path find(int startX, int startY, int endX, int endY) {
        final Comparator<Path> distanceComparator = new Comparator<Path>() {
            @Override
            public int compare(Path step1, Path step2) {
                int dx1 = step1.getX() - endX, dy1 = step1.getY() - endY;
                int dx2 = step2.getX() - endX, dy2 = step2.getY() - endY;
                return Integer.compare(dx1 * dx1 + dy1 * dy1, dx2 * dx2 + dy2 * dy2);
            }
        };
        Queue<Path> queue = new ArrayDeque<>();
        queue.add(Path.startAt(startX, startY));
        for (Path step; (step = queue.poll()) != null; ) {
            List<Path> nextSteps = new ArrayList<>();
            for (Move move : KNIGHT_MOVES) {
                Path newStep = step.move(move);
                if (newStep != null) {
                    if (newStep.getX() == endX && newStep.getY() == endY)
                        return newStep;
                    nextSteps.add(newStep);
                }
            }
            Collections.sort(nextSteps, distanceComparator);
            queue.addAll(nextSteps);
        }
        return null;
    }
}
public static void main(String[] args) {
    test(2,2, 3,3);
    test(0,0, 1,1);
    test(0,0, 7,7);
    test(0,0, 6,7);
    test(7,7, 0,0);
}
private static void test(int startX, int startY, int endX, int endY) {
    Path step = Move.find(startX, startY, endX, endY);
    System.out.println(step.getNumberOfMoves() + ": " + step.toString());
    step.printBoard();
}