Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.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 验证N皇后问题的解决方案_Java_Recursion - Fatal编程技术网

Java 验证N皇后问题的解决方案

Java 验证N皇后问题的解决方案,java,recursion,Java,Recursion,我正在尝试编写一个函数,该函数将获得一个MxN大小的板,其中有一列和一行,其中放置了一个皇后。然后我想看看女王是否受到威胁。 通常我会拿那一行,检查它是否有任何其他皇后,同样的列和对角线用于循环。 不过这里有一个小小的变化,棋盘上也有墙,可以保证皇后们的安全,即使同一排还有另一面墙: * * Q X * Q * * X * * * * Q X X Q * Q * X Q Q * 其中Q是皇后,X是墙,*是空瓷砖。 处于0,2位置的女王不会受到威胁,即使那一排还有另一位 此外,整个电路板保存在二

我正在尝试编写一个函数,该函数将获得一个MxN大小的板,其中有一列和一行,其中放置了一个皇后。然后我想看看女王是否受到威胁。 通常我会拿那一行,检查它是否有任何其他皇后,同样的列和对角线用于循环。 不过这里有一个小小的变化,棋盘上也有墙,可以保证皇后们的安全,即使同一排还有另一面墙:

* * Q X * Q
* * X * * *
* Q X X Q *
Q * X Q Q *
其中Q是皇后,X是墙,*是空瓷砖。 处于0,2位置的女王不会受到威胁,即使那一排还有另一位

此外,整个电路板保存在二维数组中,其中皇后的int值为1,墙为-1,空白为0

我的想法是穿过整排,如果某个地方有一个皇后,那么我应该找一堵墙,从那个位置到我正在看的皇后,墙上有另一个for环。不过,在我的女王之后还有第二部分

我试着考虑求和,但那也不太管用。。 有人知道如何实施这一点吗? 如果威胁返回true;如果不威胁返回错误

编辑:这是我的代码

`public static boolean isQueenThreatened(int[][] board, int row, int col){
        boolean safe=true; 
        for(int j = 0; j < col & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<col ; i++ ) {
                        if(board[row][i]!=-1) safe = false;
                }
            }
        }
        for(int j = col+1; j < board[row].length & safe ; j++){
            if(board[row][j]==1) {
                for (int i = j+1 ; i<board[row].length ; i++ ) {
                    if(board[row][i]!=-1) safe = false;
                }
            }

        }
        return safe;
    }`

我用a'表示我的女王,对于那个例子,我的代码将返回false,即使它应该是true。。然后我必须对对角线和柱做同样的处理。。这就是我需要帮助的地方。

对于给定的皇后位置,需要迭代行、列和每个对角线。在每个方向上,您都可以遵循相同的规则:

如果你打了另一个女王,你会受到威胁,返回true。 如果你撞到了墙,你在那个方向是安全的,继续下一个检查。 如果你碰到了板的边缘,你在那个方向是安全的,继续下一个检查。 编辑:

为了回答评论中的要求,您可以添加额外的布尔值来查找撞墙的威胁,但是TBH,我认为代码看起来会更糟:

public static boolean isQueenThreatened(int[][] board, int row, int col) {
    boolean threat = false;

    // Go over the row, to the left:
    boolean wall = false;
    for (int i = col - 1; i >= 0 && !threat && !wall; --i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Go over the row, to the right.
    // Reset the wall variable, as you haven't detected a wall in this direction yet
    // The threat potentially found in the previous loop is still present
    // so if it still exists, the loop will be skipped 
    boolean wall = false;
    for (int i = col + 1; i < board[row].length && !threat && !wall; ++i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Same logic for:
    // - Going over the column to the top
    // - Going over the column to the bottom
    // - Going over the top left diagonal
    // - Going over the top right diagonal
    // - Going over the bottom left diagonal
    // - Going over the bottom right diagonal

    // If you reached here, it means that no early return was performed,
    // and the queen is safe
    return threat;
}

这是使用迭代器的绝佳机会


顺便问一下,你的女王在0,2岁时受到女王在2,4岁时的威胁。

你有问题吗?是的。如果有什么想法可以让我的想法发挥作用?如何有效地越过这一排,看看女王是否受到威胁,因为我不能仅仅决定右边有墙是安全的,因为左边可能有女王,或者根本没有女王,没有墙,如果你展示你正在尝试的代码以及哪里出了问题,你会得到一个更好的答案。我已经添加了我的代码。你知道如何做到这一点而不中断,也不提前返回吗。我的意思是在函数结束时只返回一次。。我必须这样做,这对我来说有点困难。@lidorportal我已经编辑了我的答案并添加了它,但是TBH,我认为在这种情况下,使用早期返回和中断可以使代码更干净。
public static boolean isQueenThreatened(int[][] board, int row, int col) {
    // Go over the row, to the left:
    for (int i = col - 1; i >= 0; --i) {
        int val = board[row][i];
        if (val == 1) {
            return true;
        }
        if (val == -1) {
            break;
        }
    }

    // Same logic for:
    // - Going over the row to the right
    // - Going over the column to the top
    // - Going over the column to the bottom
    // - Going over the top left diagonal
    // - Going over the top right diagonal
    // - Going over the bottom left diagonal
    // - Going over the bottom right diagonal

    // If you reached here, it means that no early return was performed,
    // and the queen is safe
    return false;
}
public static boolean isQueenThreatened(int[][] board, int row, int col) {
    boolean threat = false;

    // Go over the row, to the left:
    boolean wall = false;
    for (int i = col - 1; i >= 0 && !threat && !wall; --i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Go over the row, to the right.
    // Reset the wall variable, as you haven't detected a wall in this direction yet
    // The threat potentially found in the previous loop is still present
    // so if it still exists, the loop will be skipped 
    boolean wall = false;
    for (int i = col + 1; i < board[row].length && !threat && !wall; ++i) {
        int val = board[row][i];
        if (val == 1) {
            threat = true;
        }
        if (val == -1) {
            wall = true;
        }
    }

    // Same logic for:
    // - Going over the column to the top
    // - Going over the column to the bottom
    // - Going over the top left diagonal
    // - Going over the top right diagonal
    // - Going over the bottom left diagonal
    // - Going over the bottom right diagonal

    // If you reached here, it means that no early return was performed,
    // and the queen is safe
    return threat;
}
static class Board {
    private final int width;
    private final int height;
    private final int[][] board;
    private static final int EMPTY = 0;
    private static final int WALL = -1;
    private static final int QUEEN = 1;


    public Board(int width, int height) {
        this.width = width;
        this.height = height;
        board = new int[height][width];
    }

    public Board(String[] setup) {
        this(setup[0].length(), setup.length);
        for (int y = 0; y < setup.length; y++) {
            for (int x = 0; x < setup[y].length(); x++) {
                switch (setup[y].charAt(x)) {
                    case '*':
                        board[y][x] = EMPTY;
                        break;
                    case 'X':
                        board[y][x] = WALL;
                        break;
                    case 'Q':
                        board[y][x] = QUEEN;
                        break;
                }
            }
        }
    }

    public Iterator<Integer> walk(int xStart, int yStart, int dx, int dy) {
        return new Iterator<Integer>() {
            int x = xStart;
            int y = yStart;

            @Override
            public boolean hasNext() {
                return x + dx < width && y + dy < height
                        && x + dx >= 0 && y + dy >= 0;
            }

            @Override
            public Integer next() {
                return board[y += dy][x += dx];
            }
        };
    }

    public int get(int x, int y) {
        return board[y][x];
    }
}

enum Direction {
    NORTH(0, -1),
    NORTH_WEST(1, -1),
    WEST(1, 0),
    SOUTH_WEST(1, 1),
    SOUTH(0, 1),
    SOUTH_EAST(-1, 1),
    EAST(-1, 0),
    NORTH_EAST(-1, -1),
    ;
    private final int dx;
    private final int dy;

    Direction(int dx, int dy) {
        this.dx = dx;
        this.dy = dy;
    }
}

public static boolean isQueenThreatened(Board board, int row, int col) {
    for (Direction direction : Direction.values()) {
        walk: for (Iterator<Integer> attack = board.walk(col, row, direction.dx, direction.dy); attack.hasNext(); ) {
            switch (attack.next()) {
                case Board.QUEEN:
                    return true;
                case Board.WALL:
                    break walk;
            }
        }
    }
    return false;
}

private void test() {
    String[] test = new String[]{
            "**QX*Q",
            "**X***",
            "*QXXQ*",
            "Q*XQQ*"
    };
    Board board = new Board(test);
    for (int y = 0; y < board.height; y++) {
        for (int x = 0; x < board.width; x++) {
            if (board.get(x, y) == Board.QUEEN) {
                System.out.println("Queen at position (" + x + "," + y + ") is " + (isQueenThreatened(board, y, x) ? "" : "NOT") + " threatened");
            }
        }

    }
}