我在google 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;
}
}
在什么情况下这段代码会失败?
答案 0 :(得分:3)
如果开始为{ "other_option", required_argument, 0, 0 }
且结束为0,0
,则您的答案为1,1
移动,但这需要在国际象棋棋盘外登陆。当然,其他三个角也一样。
<强>更新强>
为了它的乐趣,我决定编写代码来找到最短的路径(无论如何),并打印所采用的路径。
代码的
2
测试
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();
}
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 |
+---------------+
答案 1 :(得分:0)
我没有考虑的测试用例是当最终位置的开始是一个相同的时候。这是缺少解决方案的一部分......