自动求解华容道,动画展示

<!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>

 

posted @ 2020-12-09 21:29  吕洋  阅读(513)  评论(0)    收藏  举报