function queen(n) {
if(n === 1) {
return [["Q"]]
}
let i = 0;
let arr = [];
//保存皇后放在那列的索引
for(let k = 0; k < n; k++) {
arr.push(0);
}
let isOk = true;
while(i < n) {
let solve = true;
//let j = arr[r];
for(let j = arr[i]; j < n; j++) {
//检查该处皇后是否不被上面行的皇后攻击
let a = checkLeftTop(i, j, arr);
let b = checkTop(i, j, arr);
let c = checkRightTop(i, j, n, arr);
solve = a && b && c;
if(solve) {
//放这行皇后的列位置
arr[i] = j;
break;
}
}
//此行所有位置都不满足,回溯到祖先行
if(solve === false) {
let info = back(i, arr, n);
if(info.status) {
i = info.row;
continue;
} else {
//第一行全都遍历不满足,无解
console.log(info);
console.error("no solve");
isOk = false;
break;
}
}
i++;
}
if(isOk === false){
return [];
}
let result = [];
let firstGroup = [];
for(let i = 0;i<n;i++){
firstGroup.push(arr[i]);
}
result.push(firstGroup);
let step = true;
while (step){
let next = other(n, arr);
//console.log(next);
if(Array.isArray(next)){
let otherGroup = [];
for(let i = 0;i<n;i++){
otherGroup.push(arr[i]);
}
result.push(otherGroup);
}
else{
step = false;
}
}
//result.push(firstGroup);
//let next = other(n, arr);
console.log(result.length);
let answer = [];
for(let group of result){
let s = formatQueen(group,n);
answer.push(s);
}
//console.log(answer);
return answer;
}
/**
* 不被攻击true
* @param {number} i row
* @param {number} j column
* @param {array} a
* @returns boolean
*/
function checkLeftTop(i, j, a) {
for(let m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
//a[m] 上行皇后所在列
if(a[m] === n) {
return false;
}
}
return true;
}
function checkTop(i, j, a) {
for(let m = i - 1; m >= 0; m--) {
if(a[m] === j) {
return false;
}
}
return true;
}
function checkRightTop(i, j, colNum = 8, a) {
for(let m = i - 1, n = j + 1; m >= 0 && n < colNum; m--, n++) {
if(a[m] === n) {
return false;
}
}
return true;
}
/**
* back parent row
* @param {number} i row
* @param {array} a
* @param {number} rowNum
* @returns
*/
function back(i, a, rowNum) {
let status = false;
//回溯列
let row = i;
//console.log(i,a);
for(let r = i - 1; r >= 0; r--) {
if(a[r] < rowNum - 1) {
a[r] = a[r] + 1;
//回到上一行
row = r;
status = true;
//清空数据
for(let m = r + 1; m < rowNum; m++) {
a[m] = 0;
}
break;
}
}
return {
status,
row
}
}
/**
*下一组解,从最后一行回溯
* @param {number} n
* @param {array} arr 前一组解
* @returns
*/
function other(n, arr) {
let column = arr[n-1];
let i = n - 1;
//console.log(column);
if(column === n - 1) {
let info = back(n - 1, arr, n);
if(info.status) {
i = info.row;
//console.log(i);
} else {
console.log(info);
return;
}
}
else{
//last row next column;
arr[i] = arr[i] + 1;
}
let isOk = true;
while(i < n) {
let solve = true;
//let j = arr[r];
for(let j = arr[i]; j < n; j++) {
let a = checkLeftTop(i, j, arr);
let b = checkTop(i, j, arr);
let c = checkRightTop(i, j, n, arr);
solve = a && b && c;
if(solve) {
arr[i] = j;
break;
}
}
//此行所有位置都不满足,回溯到祖先行
if(solve === false) {
let info = back(i, arr, n);
if(info.status) {
i = info.row;
continue;
} else {
//第一行全都遍历不满足,无解
//console.log(info);
console.error("no solve");
isOk = false;
}
}
i++;
}
if(isOk){
return arr;
}
}
function formatQueen(arr,n){
let result = [];
for(let i = 0; i < n;i++){
let row = [];
let index = arr[i];
for(let j = 0;j < n;j++){
if(j === index){
row.push("Q")
}
else{
row.push(".")
}
}
let str = row.join("");
result.push(str);
}
return result;
}