1. 程式人生 > 實用技巧 >js自動求解華容道

js自動求解華容道

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>華容道</title>
    <style>
        #checkerboard {
            position: absolute;
            top: 0;
            left: 
0; width: 400px; height: 500px; border: 5px solid royalblue; } .piece { position: absolute; text-align: center; color: white; font-size: 45px; } .jiang { width: 100px; height: 200px; line
-height: 100px; } .zu { width: 100px; height: 100px; line-height: 100px; background-color: deeppink; } #caocao { width: 200px; height: 200px; background-color: sandybrown; line-height: 200px; } #guanyu { width: 200px; height: 100px; background
-color: violet; line-height: 100px; } #machao { background-color: yellow; } #huangzhong { background-color: blue; } #zhaoyun { background-color: chartreuse; } #zhangfei { background-color: cornflowerblue; } </style> </head> <body> <div id="checkerboard"> <div id="caocao" class="piece">曹 操</div> <div id="guanyu" class="piece">關 羽</div> <div id="machao" class="piece jiang">馬 超</div> <div id="huangzhong" class="piece jiang">黃 忠</div> <div id="zhaoyun" class="piece jiang">趙 雲</div> <div id="zhangfei" class="piece jiang">張 飛</div> <div id="zu1" class="piece zu">卒</div> <div id="zu2" class="piece zu">卒</div> <div id="zu3" class="piece zu">卒</div> <div id="zu4" class="piece zu">卒</div> </div> <div style="position: absolute;left: 450px;top: 50px;"> <a href="javascript: void(0)" onclick="a1()">橫刀立馬</a> <a href="javascript: void(0)" onclick="a2()">指揮若定</a> <a href="javascript: void(0)" onclick="a3()">將擁曹營</a> <a href="javascript: void(0)" onclick="a4()">齊頭並進</a> <a href="javascript: void(0)" onclick="a5()">兵分三路</a> <a href="javascript: void(0)" onclick="a6()">雨聲淅瀝</a> <a href="javascript: void(0)" onclick="a7()">左右步兵</a> <a href="javascript: void(0)" onclick="a8()">桃花源中</a> <a href="javascript: void(0)" onclick="a9()">小旋風</a> <p>注意:求解時間較長請耐心等待</p> <button onclick="start()">求最優解</button> </div> <script> /* 定義變數 start */ // 儲存不同棋子的ID let mapping = ['caocao', 'guanyu', 'machao', 'huangzhong', 'zhaoyun', 'zhangfei', 'zu1', 'zu2', 'zu3', 'zu4']; // 儲存每個棋子左上角的座標(先豎座標後橫座標),預設 小旋風 開局 let position = [[1, 1], [0, 0], [0, 3], [2, 3], [3, 0], [3, 2], [0, 2], [3, 1], [1, 0], [2, 0]]; // 小旋風 // 儲存棋盤各個方格的棋子分佈狀態 曹操0 關羽1 馬超2 黃忠3 趙雲4 張飛5 卒6789 空格-1 let checkerboard = [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]; // 棋盤歷史狀態 let historyState = {}; // 最優解 let optimalSolution = null; /* 定義變數 end */ /* 事件響應 start */ function a1() { position = [[0, 1], [2, 1], [0, 0], [2, 0], [0, 3], [2, 3], [4, 0], [3, 1], [3, 2], [4, 3]]; renderingPiecePosition(position); } function a2() { position = [[0, 1], [2, 1], [0, 0], [0, 3], [3, 0], [3, 3], [2, 0], [2, 3], [3, 1], [3, 2]]; renderingPiecePosition(position); } function a3() { position = [[0, 1], [4, 0], [1, 0], [2, 1], [2, 2], [1, 3], [3, 0], [3, 3], [4, 2], [4, 3]]; renderingPiecePosition(position); } function a4() { position = [[0, 1], [3, 1], [0, 0], [0, 3], [3, 0], [3, 3], [2, 0], [2, 1], [2, 2], [2, 3]]; renderingPiecePosition(position); } function a5() { position = [[0, 1], [2, 1], [1, 0], [3, 0], [1, 3], [3, 3], [0, 0], [0, 3], [3, 1], [3, 2]]; renderingPiecePosition(position); } function a6() { position = [[0, 1], [2, 1], [0, 0], [2, 0], [2, 3], [3, 2], [0, 3], [1, 3], [4, 0], [4, 3]]; renderingPiecePosition(position); } function a7() { position = [[0, 1], [4, 1], [2, 0], [2, 1], [2, 2], [2, 3], [0, 0], [1, 0], [0, 3], [1, 3]]; renderingPiecePosition(position); } function a8() { position = [[0, 1], [4, 1], [1, 0], [2, 1], [2, 2], [1, 3], [0, 0], [0, 3], [3, 0], [3, 3]]; renderingPiecePosition(position); } function a9() { position = [[1, 1], [0, 0], [0, 3], [2, 3], [3, 0], [3, 2], [0, 2], [3, 1], [1, 0], [2, 0]]; renderingPiecePosition(position); } function start() { createCheckerboardState(); let temp = getCompareState(checkerboard); let o = historyState[temp[0]] = {}; o = o[temp[1]] = {}; o = o[temp[2]] = {}; o[temp[3]] = true; setTimeout(() => { console.time(); let value = getStateCopy(checkerboard); let space = []; for (let i = 0; i < 5; ++i) { for (let j = 0; j < 4; ++j) { if (value[i][j] == -1) { space.push([i, j]); } } } BFS({value: value, next: [], space: space}); console.log('最優解:', optimalSolution); console.timeEnd(); alert('點選確定自動演示最優解'); let _optimalSolution = []; for (let i = optimalSolution.length - 1; i >= 0; --i) { _optimalSolution.push(createPiecePosition(optimalSolution[i])); } let x = 0; let js = setInterval(() => { renderingPiecePosition(_optimalSolution[x]); if (x == _optimalSolution.length - 1) { clearInterval(js); setTimeout(() => { a9(); checkerboard = [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]; historyState = {}; optimalSolution = null; alert('演示完畢'); }, 1000); } ++x; }, 1000); }, 10); } /* 事件響應 end */ a9(); /* 核心程式碼 start */ function renderingPiecePosition(position) { // 根據每個棋子左上角的座標來把棋子渲染到對應的位置 for (let i = 0; i < 10; ++i) { let e = document.getElementById(mapping[i]); e.style.top = position[i][0] * 100 + 'px'; e.style.left = position[i][1] * 100 + 'px'; } } function createPiecePosition(cState) { // 根據棋盤狀態生成每個棋子左上角座標 let pos = []; for (let i = 0; i < 5; ++i) { for (let j = 0; j < 4; ++j) { if (pos[cState[i][j]] == void 0) { pos[cState[i][j]] = [i, j]; } } } return pos; } function createCheckerboardState() { // 根據棋子左上角座標生成棋盤狀態 checkerboard[position[0][0]][position[0][1]] = 0; checkerboard[position[0][0]][position[0][1] + 1] = 0; checkerboard[position[0][0] + 1][position[0][1]] = 0; checkerboard[position[0][0] + 1][position[0][1] + 1] = 0; checkerboard[position[1][0]][position[1][1]] = 1; checkerboard[position[1][0]][position[1][1] + 1] = 1; checkerboard[position[2][0]][position[2][1]] = 2; checkerboard[position[2][0] + 1][position[2][1]] = 2; checkerboard[position[3][0]][position[3][1]] = 3; checkerboard[position[3][0] + 1][position[3][1]] = 3; checkerboard[position[4][0]][position[4][1]] = 4; checkerboard[position[4][0] + 1][position[4][1]] = 4; checkerboard[position[5][0]][position[5][1]] = 5; checkerboard[position[5][0] + 1][position[5][1]] = 5; checkerboard[position[6][0]][position[6][1]] = 6; checkerboard[position[7][0]][position[7][1]] = 7; checkerboard[position[8][0]][position[8][1]] = 8; checkerboard[position[9][0]][position[9][1]] = 9; } function getStateCopy(_arr) { // 返回一個棋盤狀態的複製 let arr = [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]; for (let i = 0; i < 5; ++i) { for (let j = 0; j < 4; ++j) { arr[i][j] = _arr[i][j]; } } return arr; } function getCompareState(arr) { // 接收棋盤狀態 返回比較狀態 let _arr = []; for (let i = 0; i < 5; ++i) { for (let j = 0; j < 4; ++j) { if (_arr[arr[i][j]] == void 0) { _arr[arr[i][j]] = { y: i, x: j }; } } } let a1 = _arr.slice(2, 6); let a2 = _arr.slice(6, 10); let f1 = (a, b) => { return a.y - b.y; }; let f2 = (a, b) => { return a.x - b.x; }; a1.sort(f1); a1.sort(f2); a2.sort(f1); a2.sort(f2); let result = []; result.push('$' + _arr[0].x + '$' + _arr[0].y); result.push('$' + _arr[1].x + '$' + _arr[1].y); let s = ''; for (let i = 0; i < 4; ++i) { s = s + '$' + a1[i].x + '$' + a1[i].y; } result.push(s); s = ''; for (let i = 0; i < 4; ++i) { s = s + '$' + a2[i].x + '$' + a2[i].y; } result.push(s); return result; } function isPush(arr) { // 是否應該加入歷史記錄 let o = null; if (historyState[arr[0]]) { o = historyState[arr[0]]; if (o[arr[1]]) { o = o[arr[1]]; if (o[arr[2]]) { o = o[arr[2]]; if (o[arr[3]]) { return false; } else { o[arr[3]] = true; } } else { o = o[arr[2]] = {}; o[arr[3]] = true; } } else { o = o[arr[1]] = {}; o = o[arr[2]] = {}; o[arr[3]] = true; } } else { o = historyState[arr[0]] = {}; o = o[arr[1]] = {}; o = o[arr[2]] = {}; o[arr[3]] = true; } return true; } function BFS(obj){ let x = 1; let list = [obj], listTemp = []; while(list.length != 0){ for(let i = 0, len = list.length; i < len; ++i){ if (list[i].value[4][1] == 0 && list[i].value[4][2] == 0) { let t = list[i]; let path = []; while (t) { // 回溯 path.push(t.value); t = t.top; } optimalSolution = path; console.log('共計:' + x + '個棋盤狀態'); return void 0; } else { listTemp = [...listTemp, ...createNext(list[i])]; } } list = listTemp; x += list.length; listTemp = []; } } function createNext(o) { // 根據當前棋盤狀態生成下一步所有的可能性並排除和以前重複的棋盤狀態 let list = []; let space = []; let s1 = o.space[0]; let s2 = o.space[1]; let arr = null; let _push = (arr) => { let _arr = getCompareState(arr); if (isPush(_arr)) { if (space[0][0] > space[1][0]) { space = [space[1], space[0]]; } else if (space[1][0] == space[0][0]) { if (space[0][1] > space[1][1]) { space = [space[1], space[0]]; } } else {} list.push({ value: arr, top: o, space: space }); space = []; } }; if (s1[0] == s2[0] && Math.abs(s1[1] - s2[1]) == 1) { // 連續兩個空格橫著 if (o.value[s1[0] - 1] != void 0) { // 上面可以向下移 if (o.value[s1[0] - 1][s1[1]] == 0 && o.value[s2[0] - 1][s2[1]] == 0) { // 曹操往下移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 0; arr[s1[0] - 2][s1[1]] = arr[s2[0] - 2][s2[1]] = -1; space.length = 0; space.push([s1[0] - 2, s1[1]], [s2[0] - 2, s2[1]]); _push(arr); } else if (o.value[s1[0] - 1][s1[1]] == 1 && o.value[s2[0] - 1][s2[1]] == 1) { // 關羽往下移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 1; arr[s1[0] - 1][s1[1]] = arr[s2[0] - 1][s2[1]] = -1; space.length = 0; space.push([s1[0] - 1, s1[1]], [s2[0] - 1, s2[1]]); _push(arr); } else { // 小兵或者四將向下移 let f = (pos, _pos) => { if (o.value[pos[0] - 1][pos[1]] >= 6 && o.value[pos[0] - 1][pos[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0] - 1][pos[1]]; arr[pos[0] - 1][pos[1]] = -1; space.length = 0; space.push([pos[0] - 1, pos[1]], _pos); _push(arr); } else if (o.value[pos[0] - 1][pos[1]] >= 2 && o.value[pos[0] - 1][pos[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0] - 1][pos[1]]; arr[pos[0] - 2][pos[1]] = -1; space.length = 0; space.push([pos[0] - 2, pos[1]], _pos); _push(arr); } else {} }; f(s1, s2); f(s2, s1); } } if (o.value[s1[0] + 1] != void 0) { // 下面可以往上移 if (o.value[s1[0] + 1][s1[1]] == 0 && o.value[s2[0] + 1][s2[1]] == 0) { // 曹操往上移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 0; arr[s1[0] + 2][s1[1]] = arr[s2[0] + 2][s2[1]] = -1; space.length = 0; space.push([s1[0] + 2, s1[1]], [s2[0] + 2, s2[1]]); _push(arr); } else if (o.value[s1[0] + 1][s1[1]] == 1 && o.value[s2[0] + 1][s2[1]] == 1) { // 關羽往上移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 1; arr[s1[0] + 1][s1[1]] = arr[s2[0] + 1][s2[1]] = -1; space.length = 0; space.push([s1[0] + 1, s1[1]], [s2[0] + 1, s2[1]]); _push(arr); } else { // 小兵或者四將向上移 let f = (pos, _pos) => { if (o.value[pos[0] + 1][pos[1]] >= 6 && o.value[pos[0] + 1][pos[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0] + 1][pos[1]]; arr[pos[0] + 1][pos[1]] = -1; space.length = 0; space.push([pos[0] + 1, pos[1]], _pos); _push(arr); } else if (o.value[pos[0] + 1][pos[1]] >= 2 && o.value[pos[0] + 1][pos[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0] + 1][pos[1]]; arr[pos[0] + 2][pos[1]] = -1; space.length = 0; space.push([pos[0] + 2, pos[1]], _pos); _push(arr); } else {} }; f(s1, s2); f(s2, s1); } } if (o.value[s1[0]][s1[1] - 1] != void 0) { // 左邊的可以向右移 if (o.value[s1[0]][s1[1] - 1] >= 6 && o.value[s1[0]][s1[1] - 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s1[0]][s1[1] - 1]; arr[s1[0]][s1[1] - 1] = -1; space.length = 0; space.push([s1[0], s1[1] - 1], s2); _push(arr); arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s1[0]][s1[1] - 1]; arr[s1[0]][s1[1] - 1] = -1; space.length = 0; space.push([s1[0], s1[1] - 1], s1); _push(arr); } else if (o.value[s1[0]][s1[1] - 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = 1; arr[s1[0]][s1[1] - 2] = -1; space.length = 0; space.push([s1[0], s1[1] - 2], s2); _push(arr); arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 1; arr[s1[0]][s1[1] - 1] = arr[s1[0]][s1[1] - 2] = -1; space.length = 0; space.push([s1[0], s1[1] - 1], [s1[0], s1[1] - 2]); _push(arr); } else {} } if (o.value[s2[0]][s2[1] + 1] != void 0) { // 右邊的可以向左移 if (o.value[s2[0]][s2[1] + 1] >= 6 && o.value[s2[0]][s2[1] + 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s2[0]][s2[1] + 1]; arr[s2[0]][s2[1] + 1] = -1; space.length = 0; space.push([s2[0], s2[1] + 1], s1); _push(arr); arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1] + 1]; arr[s2[0]][s2[1] + 1] = -1; space.length = 0; space.push([s2[0], s2[1] + 1], s2); _push(arr); } else if (o.value[s2[0]][s2[1] + 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = 1; arr[s2[0]][s2[1] + 2] = -1; space.length = 0; space.push([s2[0], s2[1] + 2], s1); _push(arr); arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 1; arr[s2[0]][s2[1] + 1] = arr[s2[0]][s2[1] + 2] = -1; space.length = 0; space.push([s2[0], s2[1] + 1], [s2[0], s2[1] + 2]); _push(arr); } else {} } } else if (s1[1] == s2[1] && Math.abs(s1[0] - s2[0]) == 1) { // 連續兩個空格豎著 if (o.value[s1[0] - 1] != void 0) { // 上面可以往下移 if (o.value[s1[0] - 1][s1[1]] >= 6 && o.value[s1[0] - 1][s1[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s1[0] - 1][s1[1]]; arr[s1[0] - 1][s1[1]] = -1; space.length = 0; space.push([s1[0] - 1, s1[1]], s2); _push(arr); arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s1[0] - 1][s1[1]]; arr[s1[0] - 1][s1[1]] = -1; space.length = 0; space.push([s1[0] - 1, s1[1]], s1); _push(arr); } else if (o.value[s1[0] - 1][s1[1]] >= 2 && o.value[s1[0] - 1][s1[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s1[0] - 1][s1[1]]; arr[s1[0] - 2][s1[1]] = -1; space.length = 0; space.push([s1[0] - 2, s1[1]], s2); _push(arr); arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s1[0]][s1[1]] = arr[s1[0] - 1][s1[1]]; arr[s1[0] - 1][s1[1]] = arr[s1[0] - 2][s1[1]] = -1; space.length = 0; space.push([s1[0] - 1, s1[1]], [s1[0] - 2, s1[1]]); _push(arr); } else {} } if (o.value[s2[0] + 1] != void 0) { // 下面可以往上移 if (o.value[s2[0] + 1][s2[1]] >= 6 && o.value[s2[0] + 1][s2[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s2[0] + 1][s2[1]]; arr[s2[0] + 1][s2[1]] = -1; space.length = 0; space.push([s2[0] + 1, s2[1]], s1); _push(arr); arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0] + 1][s2[1]]; arr[s2[0] + 1][s2[1]] = -1; space.length = 0; space.push([s2[0] + 1, s2[1]], s2); _push(arr); } else if (o.value[s2[0] + 1][s2[1]] >= 2 && o.value[s2[0] + 1][s2[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s2[0] + 1][s2[1]]; arr[s2[0] + 2][s2[1]] = -1; space.length = 0; space.push([s2[0] + 2, s2[1]], s1); _push(arr); arr = getStateCopy(o.value); arr[s2[0]][s2[1]] = arr[s1[0]][s1[1]] = arr[s2[0] + 1][s2[1]]; arr[s2[0] + 1][s2[1]] = arr[s2[0] + 2][s2[1]] = -1; space.length = 0; space.push([s2[0] + 1, s2[1]], [s2[0] + 2, s2[1]]); _push(arr); } else {} } if (o.value[s1[0]][s1[1] - 1] != void 0) { // 左邊可以往右邊移 if (o.value[s1[0]][s1[1] - 1] == 0 && o.value[s2[0]][s2[1] - 1] == 0) { // 曹操往右移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 0; arr[s1[0]][s1[1] - 2] = arr[s2[0]][s2[1] - 2] = -1; space.length = 0; space.push([s1[0], s1[1] - 2], [s2[0], s2[1] - 2]); _push(arr); } else if (o.value[s1[0]][s1[1] - 1] >= 2 && o.value[s2[0]][s2[1] - 1] <= 5 && o.value[s1[0]][s1[1] - 1] == o.value[s2[0]][s2[1] - 1]) { // 四將往右移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = arr[s1[0]][s1[1] - 1]; arr[s1[0]][s1[1] - 1] = arr[s2[0]][s2[1] - 1] = -1; space.length = 0; space.push([s1[0], s1[1] - 1], [s2[0], s2[1] - 1]); _push(arr); } else { // 小兵或者關羽向右移 let f = (pos, _pos) => { if (o.value[pos[0]][pos[1] - 1] >= 6 && o.value[pos[0]][pos[1] - 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0]][pos[1] - 1]; arr[pos[0]][pos[1] - 1] = -1; space.length = 0; space.push([pos[0], pos[1] - 1], _pos); _push(arr); } else if (o.value[pos[0]][pos[1] - 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0]][pos[1] - 1]; arr[pos[0]][pos[1] - 2] = -1; space.length = 0; space.push([pos[0], pos[1] - 2], _pos); _push(arr); } else {} }; f(s1, s2); f(s2, s1); } } if (o.value[s1[0]][s1[1] + 1] != void 0) { // 右邊可以往左邊移 if (o.value[s1[0]][s1[1] + 1] == 0 && o.value[s2[0]][s2[1] + 1] == 0) { // 曹操往左移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = 0; arr[s1[0]][s1[1] + 2] = arr[s2[0]][s2[1] + 2] = -1; space.length = 0; space.push([s1[0], s1[1] + 2], [s2[0], s2[1] + 2]); _push(arr); } else if (o.value[s1[0]][s1[1] + 1] >= 2 && o.value[s2[0]][s2[1] + 1] <= 5 && o.value[s1[0]][s1[1] + 1] == o.value[s2[0]][s2[1] + 1]) { // 四將往左移 arr = getStateCopy(o.value); arr[s1[0]][s1[1]] = arr[s2[0]][s2[1]] = arr[s1[0]][s1[1] + 1]; arr[s1[0]][s1[1] + 1] = arr[s2[0]][s2[1] + 1] = -1; space.length = 0; space.push([s1[0], s1[1] + 1], [s2[0], s2[1] + 1]); _push(arr); } else { // 小兵或者關羽向左移 let f = (pos, _pos) => { if (o.value[pos[0]][pos[1] + 1] >= 6 && o.value[pos[0]][pos[1] + 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0]][pos[1] + 1]; arr[pos[0]][pos[1] + 1] = -1; space.length = 0; space.push([pos[0], pos[1] + 1], _pos); _push(arr); } else if (o.value[pos[0]][pos[1] + 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[pos[0]][pos[1]] = arr[pos[0]][pos[1] + 1]; arr[pos[0]][pos[1] + 2] = -1; space.length = 0; space.push([pos[0], pos[1] + 2], _pos); _push(arr); } else {} }; f(s1, s2); f(s2, s1); } } } else { // 兩個空格不相鄰 let f = (s, _s) => { if (o.value[s[0] - 1] != void 0) { // 上邊的可以向下移動 if (o.value[s[0] - 1][s[1]] >= 6 && o.value[s[0] - 1][s[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0] - 1][s[1]]; arr[s[0] - 1][s[1]] = -1; space.length = 0; space.push([s[0] - 1, s[1]], _s); _push(arr); } else if (o.value[s[0] - 1][s[1]] >= 2 && o.value[s[0] - 1][s[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0] - 1][s[1]]; arr[s[0] - 2][s[1]] = -1; space.length = 0; space.push([s[0] - 2, s[1]], _s); _push(arr); } else {} } if (o.value[s[0] + 1] != void 0) { // 下邊的可以向上移動 if (o.value[s[0] + 1][s[1]] >= 6 && o.value[s[0] + 1][s[1]] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0] + 1][s[1]]; arr[s[0] + 1][s[1]] = -1; space.length = 0; space.push([s[0] + 1, s[1]], _s); _push(arr); } else if (o.value[s[0] + 1][s[1]] >= 2 && o.value[s[0] + 1][s[1]] <= 5) { // 四將 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0] + 1][s[1]]; arr[s[0] + 2][s[1]] = -1; space.length = 0; space.push([s[0] + 2, s[1]], _s); _push(arr); } else {} } if (o.value[s[0]][s[1] - 1] != void 0) { // 左邊的可以向右移動 if (o.value[s[0]][s[1] - 1] >= 6 && o.value[s[0]][s[1] - 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0]][s[1] - 1]; arr[s[0]][s[1] - 1] = -1; space.length = 0; space.push([s[0], s[1] - 1], _s); _push(arr); } else if (o.value[s[0]][s[1] - 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0]][s[1] - 1]; arr[s[0]][s[1] - 2] = -1; space.length = 0; space.push([s[0], s[1] - 2], _s); _push(arr); } else {} } if (o.value[s[0]][s[1] + 1] != void 0) { // 右邊的可以向左移動 if (o.value[s[0]][s[1] + 1] >= 6 && o.value[s[0]][s[1] + 1] <= 9) { // 小兵 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0]][s[1] + 1]; arr[s[0]][s[1] + 1] = -1; space.length = 0; space.push([s[0], s[1] + 1], _s); _push(arr); } else if (o.value[s[0]][s[1] + 1] == 1) { // 關羽 arr = getStateCopy(o.value); arr[s[0]][s[1]] = arr[s[0]][s[1] + 1]; arr[s[0]][s[1] + 2] = -1; space.length = 0; space.push([s[0], s[1] + 2], _s); _push(arr); } else {} } }; f(s1, s2); f(s2, s1); } return list; } /* 核心程式碼 end */ </script> </body> </html>