-
Notifications
You must be signed in to change notification settings - Fork 137
/
nQueens.js
102 lines (86 loc) · 3.77 KB
/
nQueens.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import QueenPosition from './QueenPosition';
/**
* @param {QueenPosition[]} queensPositions
* @param {number} rowIndex
* @param {number} columnIndex
* @return {boolean}
*/
function isSafe(queensPositions, rowIndex, columnIndex) {
// Vị trí mới cho việc đặt Quân Hậu.
const newQueenPosition = new QueenPosition(rowIndex, columnIndex);
// Kiếm tra vị mới có xung đột với quân hậu nào không.
for (let queenIndex = 0; queenIndex < queensPositions.length; queenIndex += 1) {
const currentQueenPosition = queensPositions[queenIndex];
if (
// Kiếm tra nếu vị quân hậu đã được đặt.
currentQueenPosition
&& (
// Kiểm tra nếu có quân hậu trên cùng cột.
newQueenPosition.columnIndex === currentQueenPosition.columnIndex
// Kiểm tra nếu có quân hậu trên cùng hàng.
|| newQueenPosition.rowIndex === currentQueenPosition.rowIndex
// Kiểm tra nếu có quân hậu trên cùng đường chéo trái.
|| newQueenPosition.leftDiagonal === currentQueenPosition.leftDiagonal
// Kiểm tra nếu có quân hậu trên cùng đường chéo phải.
|| newQueenPosition.rightDiagonal === currentQueenPosition.rightDiagonal
)
) {
// Không thể đặt quân hậu vào vị tri hiện tại vì những con hậu khác có thể ăn nó.
return false;
}
}
// An toàn để đặt hậu.
return true;
}
/**
* @param {QueenPosition[][]} solutions
* @param {QueenPosition[]} previousQueensPositions
* @param {number} queensCount
* @param {number} rowIndex
* @return {boolean}
*/
function nQueensRecursive(solutions, previousQueensPositions, queensCount, rowIndex) {
// Tạo bản sao mảng vị trí.
const queensPositions = [...previousQueensPositions].map((queenPosition) => {
return !queenPosition ? queenPosition : new QueenPosition(
queenPosition.rowIndex,
queenPosition.columnIndex,
);
});
if (rowIndex === queensCount) {
// Chúng ta đã thành công đi đến cuối bàn cờ.
// Lưu trữ vào danh sách giải pháp.
solutions.push(queensPositions);
// Báo đã tìm ra giải pháp.
return true;
}
// Đặt quân Hậu vào vị trí cột an toàn tương ứng với hàng rowIndex.
for (let columnIndex = 0; columnIndex < queensCount; columnIndex += 1) {
if (isSafe(queensPositions, rowIndex, columnIndex)) {
// Đặt quân hậu hiện tại vào vị trí hiện tại.
queensPositions[rowIndex] = new QueenPosition(rowIndex, columnIndex);
// Thử với tất cả quân hậu khác.
nQueensRecursive(solutions, queensPositions, queensCount, rowIndex + 1);
// QUAY LÙI.
// Xoá quân hậu khỏi hàng để tránh isSafe() trả về false.
queensPositions[rowIndex] = null;
}
}
return false;
}
/**
* @param {number} queensCount
* @return {QueenPosition[][]}
*/
export default function nQueens(queensCount) {
// Khởi tạo bàn cờ NxN với tất cả phần tử bằng 0.
// const chessboard = Array(queensCount).fill(null).map(() => Array(queensCount).fill(0));
// Mảng này sẽ giữ các vị trị hoặc toạ độ của từng quân hậu
// có dạng [rowIndex, columnIndex].
const queensPositions = Array(queensCount).fill(null);
/** @var {QueenPosition[][]} solutions */
const solutions = [];
// Đê quy giải quyết vấn đề.
nQueensRecursive(solutions, queensPositions, queensCount, 0);
return solutions;
}