八皇后規則:任意兩個棋子都不能處於同一行、同一列或同一斜線上
分析:(下面 將要放的棋子用a表示,已經放下的棋子用b表示)
一、橫軸不重複
橫軸不重複,也就是說水平方向只能有一個棋子 :所以我們可以採取一行一行放,這樣一定是不重複的
二、縱軸不重複
縱軸不重複,也就是說垂直方向只能有一個棋子。那麼,放下的棋子(這裏用a表示)與已經放下的棋子(這裏用b表示)兩者 的y軸相比,不相等說明豎着沒有重複
三、斜着不重複
斜着不重複,每條斜線只能有一個棋子。這個實際上比較的是a到b的水平方向和a到b的垂直方向相等就是斜向(相當於ab爲邊長的正方形的對角線),最終用公式表示:ax-bx = ay-by 只要保證ax-bx 不等於 ay-by 就可以了
下面代碼演示:
先實現2,3步 的函數,用一個數組arr表示已經放入的所有棋子,將要放的棋子爲a,如果條件符合爲true,反之爲false。
const arr = []
function fn (ax, ay) {
for (let i = 1; i < ax; i++) {
if (ay === arr[i-1].y || Math.abs(ax - arr[i-1].x) === Math.abs(ay - arr[i-1].y)) return false
}
return true
}
其次,實現按行嘗試放棋子 row:將要放的第幾行 n:能放置的行數與列數
const n = 8
function ab (row) {
if (row > n) console.log(arr.map(item => item.y)) // 這裏的n是行
for (let i = 1; i <= n; i++) { // 這裏的n是列
// 若是第一個棋子直接進入下一行
if (row === 1 || fn(row, i)) {
arr[row-1] = {x: row, y: i}
ab(row + 1)
}
}
}
最後,執行
ab(1)
結果,92種
遊戲玩完了。現在說一下解決的這種算法:回溯算法
回溯算法
https://baike.baidu.com/item/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95/9258495?fr=aladdin
百度百科這麼解釋:
回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。回溯法是一種選優搜索法,按選優條件向前搜索,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術爲回溯法,而滿足回溯條件的某個狀態的點稱爲“回溯點”。
上面八皇后的遊戲就是如此,一行一行,一列一列的嘗試放下棋子,當符合條件就嘗試去下一行放下棋子,反之,嘗試放下當前行的下一列繼續嘗試!