【发布时间】:2016-02-12 20:19:55
【问题描述】:
我正在解决一个在初级程序员中似乎有点名气的问题,即 8 个皇后谜题。我已经看到使用 2D 数组、递归等方法解决这个问题的几种方法,但是这个问题是 CS 课程书中介绍 1D 数组的章节中给出的作业,因此解决这个问题的可用技术是有限的。
我使用的过程是首先创建一个大小为 64 的一维数组,这使得可以放置从索引 0 到 63 的皇后的位置。然后生成一个随机位置索引,并进行测试以检查如果有任何皇后攻击这个位置。如果这个位置没有被任何皇后攻击,则通过设置board[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;
}
}
【问题讨论】:
-
“while 循环中断”是指无限循环吗?
-
我想这就是我的意思,程序会尝试 n 次放置 8 个皇后,直到无法再放置。但是,我在输出中看到应该可以再放置 1 或 2 个。
-
是否有检查以确保皇后不在同一个位置?
-
我现在添加了一个,但现在它无限循环。似乎第一个解决方案将皇后放置在已经被占用的位置。编辑了代码,因此检查以确认皇后占据同一地点。