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