递归 N 皇后区:缺少解决方案
Recursive N-Queens : missing solutions
我写了一个 Java N 皇后拼图的小算法(带有 c*c 棋盘)。您将在下面找到我的递归方法的代码。
它没有找到所有的解决方案。
我的功能是什么
我的想法是,在 main 方法中,第一次调用我的函数,为它提供最大数量的皇后,直到找到解决方案,没有任何皇后的棋盘和这些新皇后的坐标:x=0 ,y=0.
函数会遍历棋盘。对于每个方块,它测试是否可以放置皇后 (0;0)(即:没有威胁)。皇后(0;0)可以放置吗?好吧,我们这样做(修改棋盘)并调用函数(递归调用)。此递归调用是通过以下方式完成的:"maximum number of queens - 1"、修改后的棋盘和 "new-queen's y + 1"(有点复杂)。
找到 n=4 和 c=4 的解决方案(通常有两个解决方案...!)
&&问&
问&&&
&&&Q
&问&&
我函数的最新代码
private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) {
if (nb_queens == 0) { // If there isn't any queen remaining, it means we found a solution
drawChessboard(chessboard);
solutions.add(chessboard);
}
for(int i = x; i < chessboard.size(); i++) {
for (int z = y; z < chessboard.get(i).size(); z++) {
if(!canBePlaced(i, z, chessboard)) {
chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait
setQueen(nb_queens-1, chessboard, i+1, 0, solutions);
chessboard.get(z).set(i, false);
}
}
}
}
旧代码
private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) {
if (nb_queens == 0) {
drawChessboard(chessboard); // Il n'y a plus de reine à placer => on dessine cette solution
solutions.add(chessboard);
}
for(int i = x; i < chessboard.size(); i++) {
for (int z = y; z < chessboard.get(i).size(); z++) {
if(!isAQueenAlreadyPresent(i, z, chessboard)) {
chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait
setQueen(nb_queens-1, chessboard, i, (z+1 >= WIDTH) ? 0 : z+1, solutions);
chessboard.get(z).set(i, false);
}
}
}
}
哦对了,那是因为你如何递归调用,你在做什么 setQueen(nb_queens-1, chessboard, i, z+1, solutions);
。 z+1
部分是问题所在,它总是会在您放置在全局板上的第一个皇后的右侧找到解决方案。
编辑:啊你之前发现了,不错。
因此,问题在于 for 循环充当 if(z>=y)
,因为它从 y
开始。 i = x
(读第一行)的时候可以,但是i > x
的时候不行。因此,一个简单的解决方法是将 y = ( i == x ) ? y : 0
放在第一个 for
循环之后。
还有更简洁的解决方案,比如使用单个索引遍历整个棋盘。
我还建议您将参数重命名为 startX 和 startY(而不是 x 和 y,您可以在循环中使用 x 和 y 以便更清楚)。
Edit2:由于游戏规则,同一条线上永远不会有皇后,所以您可以像 setQueen(nb_queens-1, chessboard, i+1, 0, solutions);
一样进行递归调用(i+1
因为您从下一个开始直接上线)。因此,您甚至可以从 setQueen
方法中删除 int y
参数并始终从 0.
开始 z loop
我写了一个 Java N 皇后拼图的小算法(带有 c*c 棋盘)。您将在下面找到我的递归方法的代码。
它没有找到所有的解决方案。
我的功能是什么
我的想法是,在 main 方法中,第一次调用我的函数,为它提供最大数量的皇后,直到找到解决方案,没有任何皇后的棋盘和这些新皇后的坐标:x=0 ,y=0.
函数会遍历棋盘。对于每个方块,它测试是否可以放置皇后 (0;0)(即:没有威胁)。皇后(0;0)可以放置吗?好吧,我们这样做(修改棋盘)并调用函数(递归调用)。此递归调用是通过以下方式完成的:"maximum number of queens - 1"、修改后的棋盘和 "new-queen's y + 1"(有点复杂)。
找到 n=4 和 c=4 的解决方案(通常有两个解决方案...!)
&&问&
问&&&
&&&Q
&问&&
我函数的最新代码
private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) {
if (nb_queens == 0) { // If there isn't any queen remaining, it means we found a solution
drawChessboard(chessboard);
solutions.add(chessboard);
}
for(int i = x; i < chessboard.size(); i++) {
for (int z = y; z < chessboard.get(i).size(); z++) {
if(!canBePlaced(i, z, chessboard)) {
chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait
setQueen(nb_queens-1, chessboard, i+1, 0, solutions);
chessboard.get(z).set(i, false);
}
}
}
}
旧代码
private static void setQueen(int nb_queens, ArrayList<ArrayList<Boolean>> chessboard, int x, int y, ArrayList<ArrayList<ArrayList<Boolean>>> solutions) {
if (nb_queens == 0) {
drawChessboard(chessboard); // Il n'y a plus de reine à placer => on dessine cette solution
solutions.add(chessboard);
}
for(int i = x; i < chessboard.size(); i++) {
for (int z = y; z < chessboard.get(i).size(); z++) {
if(!isAQueenAlreadyPresent(i, z, chessboard)) {
chessboard.get(z).set(i, true); // On peut donc placer cette reine(x;y) et on le fait
setQueen(nb_queens-1, chessboard, i, (z+1 >= WIDTH) ? 0 : z+1, solutions);
chessboard.get(z).set(i, false);
}
}
}
}
哦对了,那是因为你如何递归调用,你在做什么 setQueen(nb_queens-1, chessboard, i, z+1, solutions);
。 z+1
部分是问题所在,它总是会在您放置在全局板上的第一个皇后的右侧找到解决方案。
编辑:啊你之前发现了,不错。
因此,问题在于 for 循环充当 if(z>=y)
,因为它从 y
开始。 i = x
(读第一行)的时候可以,但是i > x
的时候不行。因此,一个简单的解决方法是将 y = ( i == x ) ? y : 0
放在第一个 for
循环之后。
还有更简洁的解决方案,比如使用单个索引遍历整个棋盘。
我还建议您将参数重命名为 startX 和 startY(而不是 x 和 y,您可以在循环中使用 x 和 y 以便更清楚)。
Edit2:由于游戏规则,同一条线上永远不会有皇后,所以您可以像 setQueen(nb_queens-1, chessboard, i+1, 0, solutions);
一样进行递归调用(i+1
因为您从下一个开始直接上线)。因此,您甚至可以从 setQueen
方法中删除 int y
参数并始终从 0.
z loop