Java中具有一维数组的N皇后难题
我正在研究一个在初学者中似乎有点有名的问题,8皇后之谜。我见过一些使用2D数组、递归等来解决这个问题的方法,但这个问题是CS课程书中介绍1D数组一章中给出的作业,因此解决这个问题的可用技术是有限的 我使用的过程是首先创建一个大小为64的1D数组,这样就可以放置索引0到63之间的皇后。然后生成一个随机位置索引,并进行测试以检查是否有任何皇后攻击该位置。如果此位置未受到任何皇后的攻击,则通过设置Java中具有一维数组的N皇后难题,java,arrays,n-queens,Java,Arrays,N Queens,我正在研究一个在初学者中似乎有点有名的问题,8皇后之谜。我见过一些使用2D数组、递归等来解决这个问题的方法,但这个问题是CS课程书中介绍1D数组一章中给出的作业,因此解决这个问题的可用技术是有限的 我使用的过程是首先创建一个大小为64的1D数组,这样就可以放置索引0到63之间的皇后。然后生成一个随机位置索引,并进行测试以检查是否有任何皇后攻击该位置。如果此位置未受到任何皇后的攻击,则通过设置板[position]=true放置皇后。放置皇后后,queenCount将递增,此过程将重复,直到放置了
板[position]=true
放置皇后。放置皇后后,queenCount
将递增,此过程将重复,直到放置了8个皇后
如果皇后的放置方式无法放置8,则电路板在1毫秒后通过执行时间检查重置,并重试放置8个皇后。我最多只能放置7个皇后,但最后一个皇后从未放置过。每次尝试都会打印出来,同时打印此尝试的queenCount
。是否有可能使用这种方法,或者这是一条死胡同
代码示例如下:
package ch7;
public class Chapter_07_E22_EightQueens64bool {
public static void main(String[] args) {
int queenCount = 0;
int attemptCount = 0;
boolean[] board = new boolean[8 * 8];
final long TIME_LIMIT = 1; //Milliseconds
long startTime = System.currentTimeMillis();
while (queenCount < 8) {
int position = placeQueen(board.length);
if(checkPosition(position, board) && !board[position]) {
board[position] = true;
queenCount++;
}
long timeCheck = System.currentTimeMillis();
if (timeCheck - startTime > TIME_LIMIT) {
clearBoard(board);
queenCount = 0;
startTime = System.currentTimeMillis();
}
System.out.println("Attempt #" + ++attemptCount);
System.out.println(queenCount + " queens placed.");
printBoard(board);
}
}
public static void printBoard(boolean[] board) {
for (int i = 0; i < board.length; i++) {
if (board[i])
System.out.print("|Q");
else
System.out.print("| ");
if ((i + 1) % 8 == 0)
System.out.println("|");
}
}
public static int placeQueen(int boardSize) {
return (int)(Math.random() * boardSize);
}
public static boolean[] clearBoard(boolean[] board) {
for (int i = 0; i < board.length; i++)
board[i] = false;
return board;
}
public static boolean checkPosition(int position, boolean[] board) {
return checkTop(position, board) && checkBottom(position, board) && checkLeft(position, board) &&
checkRight(position, board) && checkTopLeft(position, board) && checkTopRight(position, board) &&
checkBottomLeft(position, board) && checkBottomRight(position, board);
}
public static boolean checkTop(int position, boolean[] board) {
// Checks each field above the current position while i >= 8
for (int i = position; i >= 8; i -= 8) {
if (board[i - 8])
return false;
}
return true;
}
public static boolean checkBottom(int position, boolean[] board) {
// Checks each field below the current position while i <= 55;
for (int i = position; i <= 55; i += 8) {
if (board[i + 8])
return false;
}
return true;
}
public static boolean checkRight(int position, boolean[] board) {
// Checks each field to the right of the current position while i % 8 < 7
for (int i = position; i % 8 < 7; i += 1) {
if (board[i + 1])
return false;
}
return true;
}
public static boolean checkLeft(int position, boolean[] board) {
// Checks each field to the left of the current position while i % 8 != 0
for (int i = position; i % 8 != 0; i -= 1) {
if (board[i - 1])
return false;
}
return true;
}
public static boolean checkTopLeft(int position, boolean[] board) {
// Checks each field top left of the current position while i >= 9
for (int i = position; i >= 9; i -= 9) {
if (board[i - 9])
return false;
}
return true;
}
public static boolean checkTopRight(int position, boolean[] board) {
// Checks each field top right of the current position while i >= 7
for (int i = position; i >= 7; i -= 7) {
if (board[i - 7])
return false;
}
return true;
}
public static boolean checkBottomRight(int position, boolean[] board) {
// Checks each field below the current position while i <= 54
for (int i = position; i <= 54; i += 9) {
if (board[i + 9])
return false;
}
return true;
}
public static boolean checkBottomLeft(int position, boolean[] board) {
// Checks each field below the current position while i <= 56
for (int i = position; i <= 56; i += 7) {
if (board[i + 7])
return false;
}
return true;
}
}
package ch7;
public class Chapter_07_E22_EightQueens {
static final int N = 8;
public static void main(String[] args) {
int[] queens = new int[N];
int attempts = 0;
for (int i = 0; i < N; i++)
queens[i] = i;
while (checkBoardForCollision(queens)) {
shuffleBoard(queens);
attempts++;
}
printBoard(queens);
System.out.println("Solution found in " + attempts + " attempts");
}
public static void printBoard(int[] queens) {
for (int row = 0; row < N; row++) {
System.out.printf("%-1c", '|');
for (int column = 0; column < N; column++) {
System.out.printf("%-1c|", (queens[row] == column) ? 'Q' : ' ');
}
System.out.println();
}
}
public static boolean shareDiagonal(int x0, int y0, int x1, int y1) {
int dy = Math.abs(y1 - y0);
int dx = Math.abs(x1 - x0);
return dx == dy;
}
public static boolean checkRowForCollision(int[] queens, int row) {
for (int i = 0; i < row; i++) {
if (shareDiagonal(i, queens[i], row, queens[row]))
return true;
}
return false;
}
public static boolean checkBoardForCollision(int[] queens) {
for (int row = 0; row < queens.length; row++)
if (checkRowForCollision(queens, row))
return true;
return false;
}
public static int[] shuffleBoard(int[] queens) {
for (int i = queens.length - 1; i > 0; i--) {
int j = (int)(Math.random() * (i + 1));
int temp = queens[i];
queens[i] = queens[j];
queens[j] = temp;
}
return queens;
}
}
包装ch7;
公共课第七章第二十二章第八节{
公共静态void main(字符串[]args){
int queenCount=0;
int attemptCount=0;
布尔[]板=新布尔[8*8];
最终长时间限制=1;//毫秒
long startTime=System.currentTimeMillis();
而(皇后数<8){
int位置=placeQueen(板长);
if(检查位置(位置,板)和&!板[位置]){
板[位置]=真;
queenCount++;
}
长时间检查=System.currentTimeMillis();
if(时间检查-开始时间>时间限制){
透明板;
queenCount=0;
startTime=System.currentTimeMillis();
}
System.out.println(“尝试”++++attemptCount);
System.out.println(queenscount+“queens放置”);
印刷板;
}
}
公共静态无效打印板(布尔[]板){
对于(int i=0;i=8时检查当前位置上方的每个字段
对于(int i=位置;i>=8;i-=8){
如果(董事会[i-8])
返回false;
}
返回true;
}
公共静态布尔checkBottom(int位置,布尔[]板){
//在i=9;i-=9)时检查当前位置下方的每个字段{
如果(董事会[i-9])
返回false;
}
返回true;
}
公共静态布尔checkTopRight(整型位置,布尔[]板){
//在i>=7时检查当前位置右上角的每个字段
对于(int i=位置;i>=7;i-=7){
如果(董事会[i-7])
返回false;
}
返回true;
}
公共静态布尔checkBottomRight(整型位置,布尔[]板){
//检查当前位置下方的每个字段,而我其中一个问题(可能还有更多问题)是在checkTop
方法中
public static boolean checkTop(int position, boolean[] board)
{
// Checks each field above the current position while i - 8 > - 1
for (int i = position; i > (i - 8); i -= 8)
{
if ((i - 8) > -1)
{
if (board[i - 8])
return false;
}
}
return true;
}
在某些情况下,当该方法没有找到插槽(board[i-8]=true
)并且i
达到7
的值时。在这一点之后,for loop
(i>(i-8)
)的条件将始终是true
,而最外面的if
的条件将始终是在循环内(if((i-8)>-1
)将始终为false
。这将导致程序无限地停留在循环中
示例(i
reats-5):
i=-5;
i>(i-8):-5>(-5-8=-13)(始终正确)
(i-8)>-1:-13>-1(false)对于i始终为false首先,大小为8的数组就足够了。
数组索引表示皇后所在的列,值表示行
表示第一列中的皇后位于第一行,第二个皇后位于第三行,第三个皇后位于第五行,以此类推
因此,当您放置新皇后时,请检查您添加它的行是否不在数组中。这样,您只需担心对角线碰撞
解决此问题的最简单方法是递归(回溯)。如果不允许,您可以使用堆栈模拟递归。如果也不允许,您可以使用8个嵌套循环-丑陋
您可以使用一个简单的技巧改进碰撞检查。其工作原理如下-
假设你的女王在第三排。
她对角攻击哪些细胞?
在…上
[0, 2, 4, 6, 1, 3, 5, 7]
boolean canAdd(List<Integer> p, int newRow) {
if (p.contains(newRow))
return false;
int insertIndex = p.size();
for (int i = 0; i < p.size(); i++) {
if (p.get(i) + (insertIndex - i) == newRow || p.get(i) - (insertIndex - i) == newRow)
return false;
}
return true;
}
void solve(List<Integer> p, int index) {
if (index == 8) {
System.out.println(p);
return;
}
for (int i = 0; i < 8; i++) {
if (canAdd(p, i)) {
p.add(i);
solve(p, index + 1);
p.remove(p.size() - 1);
}
}
}
solve(new ArrayList<Integer>(), 0);
package ch7;
public class Chapter_07_E22_EightQueens {
static final int N = 8;
public static void main(String[] args) {
int[] queens = new int[N];
int attempts = 0;
for (int i = 0; i < N; i++)
queens[i] = i;
while (checkBoardForCollision(queens)) {
shuffleBoard(queens);
attempts++;
}
printBoard(queens);
System.out.println("Solution found in " + attempts + " attempts");
}
public static void printBoard(int[] queens) {
for (int row = 0; row < N; row++) {
System.out.printf("%-1c", '|');
for (int column = 0; column < N; column++) {
System.out.printf("%-1c|", (queens[row] == column) ? 'Q' : ' ');
}
System.out.println();
}
}
public static boolean shareDiagonal(int x0, int y0, int x1, int y1) {
int dy = Math.abs(y1 - y0);
int dx = Math.abs(x1 - x0);
return dx == dy;
}
public static boolean checkRowForCollision(int[] queens, int row) {
for (int i = 0; i < row; i++) {
if (shareDiagonal(i, queens[i], row, queens[row]))
return true;
}
return false;
}
public static boolean checkBoardForCollision(int[] queens) {
for (int row = 0; row < queens.length; row++)
if (checkRowForCollision(queens, row))
return true;
return false;
}
public static int[] shuffleBoard(int[] queens) {
for (int i = queens.length - 1; i > 0; i--) {
int j = (int)(Math.random() * (i + 1));
int temp = queens[i];
queens[i] = queens[j];
queens[j] = temp;
}
return queens;
}
}