首先定义一个二维数组表示棋盘:
检查方式:
每次落点检查 纵向/ 左斜方/ 右斜方是否满足条件
/**
* 检查落点是否符合规则
*
* @param x 横轴(行)
* @param y 纵轴(列)
* @return {@code true} 可落点, {@code false} 不能落点
*/
private boolean check(int x, int y) {
for (int i = 0; i < y; i++) {
// 检查纵向
if (chessBoard[x][i] == 1) {
return false;
}
// 检查左斜方
if (x - 1 - i >= 0 && chessBoard[x - 1 - i][y - 1 - i] == 1) {
return false;
}
// 检查右斜方
if (x + 1 + i < MAX_NUM && chessBoard[x + 1 + i][y - 1 - i] == 1) {
return false;
}
}
return true;
}
落点的方式:
从上往下, 要求从上往下每一行的落点都能满足条件
/**
* 落点皇后
*
* @param y 纵轴(列)
* @return {@code true or false} y行以下落点完成
*/
private boolean settleQueen(int y) {
// 行数超过8, 已经找到答案
if (y == MAX_NUM) {
return true;
}
// 遍历当前行, 逐一格子验证
for (int i = 0; i < MAX_NUM; i++) {
// 为当前行清零,以免在回溯的时候出现脏数据
for (int x = 0; x < MAX_NUM; x++) {
chessBoard[x][y] = 0;
}
// 检查是否符合规则, 如果符合, 更改元素值并进一步递归
if (check(i, y)) {
chessBoard[i][y] = 1;
// 递归如果返回 true, 说明下层已找到解法, 无需继续循环
if (settleQueen(y + 1)) {
return true;
}
}
}
return false;
}
打印排序方式:
/**
* 打印棋盘当前值
*
*/
private void printChessBoard() {
for (int j = 0; j < MAX_NUM; j++) {
for (int i = 0; i < MAX_NUM; i++) {
System.out.print((chessBoard[i][j] == 0 ? "." : chessBoard[i][j]) + "\t");
}
System.out.println();
}
}
主方法:
public static void main(String[] args) {
EightQueen queen = new EightQueen();
queen.settleQueen(0);
queen.printChessBoard();
}
注意:
若把清零每行的操作取消掉, 会遗留脏数据
/**
* 落点皇后
*
* @param y 纵轴(列)
* @return {@code true or false} y行以下落点完成
*/
private boolean settleQueen(int y) {
// 行数超过8, 已经找到答案
if (y == MAX_NUM) {
return true;
}
// 遍历当前行, 逐一格子验证
for (int i = 0; i < MAX_NUM; i++) {
// 为当前行清零,以免在回溯的时候出现脏数据
// for (int x = 0; x < MAX_NUM; x++) {
// chessBoard[x][y] = 0;
// }
// 检查是否符合规则, 如果符合, 更改元素值并进一步递归
if (check(i, y)) {
chessBoard[i][y] = 1;
// 递归如果返回 true, 说明下层已找到解法, 无需继续循环
if (settleQueen(y + 1)) {
return true;
}
}
}
return false;
}
不清零的后果, 每一行往上层回溯