mr88fang 发表于 2024-3-14 09:37

[数字华容道] Html+css+js 实现小游戏

本帖最后由 mr88fang 于 2024-3-19 12:05 编辑

# [数字华容道] Html+css+js 实现小游戏
## 预览&代码地址

[代码在线预览](https://playcode.io/hua)[效果预览](https://hua.playcode.io/)

增加指定数列

## 代码示例

```html
<!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8">
                <title>数字华容道</title>
                <style>
                        h1 {
                                text-align: center;
                        }

                        .box {
                                border: 1px solid #cfcfcf;
                                margin: 0 auto;
                                max-width: 647px;
                                padding: 20px;
                                border-radius: 20px;
                                display: flex;
                        }

                        .fun {
                                display: flex;
                                justify-content: space-between;
                        }


                        td {
                                width: 100px;
                                height: 100px;
                                text-align: center;
                                background-color: #f1c385;
                                user-select: none;
                        }

                        .current {
                                background-color: #fff !important;
                                transition: all .3s;
                        }

                        #error {
                                color: red;
                        }
                </style>
        </head>
        <body>
                <div class="box">
                        <div style="flex: 1;">
                                <h1>数字华容道</h1>
                                <p><strong>规则:</strong>移动方块依次出现1、2、3、4、5、6、7、8就可通关!不能对角线移动,不能跳格子移动。只能相邻上下或左右</p>
                                <hr />
                                <div class="fun">
                                        <div><span>计次:</span><span id="num">0</span></div>
                                        <div><span>提示:</span><span id="error"></span></div>
                                        <div><span>功能:</span><button id="reset">重开</button></div>
                                </div>
                                <hr />
                                <div class="fun">
                                        <div><label>指定序列:</label><input type="text" placeholder="指定数列,例如:1,2,3,4,6,7,8" /></div>
                                        <div><button id="confirm">确定</button></div>
                                </div>
                                <hr />
                                <table border="1">
                                        <tr>
                                                <td>1</td>
                                                <td>2</td>
                                                <td>3</td>
                                        </tr>
                                        <tr>
                                                <td>4</td>
                                                <td>5</td>
                                                <td>6</td>
                                        </tr>
                                        <tr>
                                                <td>7</td>
                                                <td>8</td>
                                                <td class="current"></td>
                                        </tr>
                                </table>
                        </div>
                        <div style="flex: 1;padding: 10px;">
                                <p>
                                        <strong>逆序数:</strong>
                                        是指,在一个数列中,任取两个数字,如果前面的数字大于后面的数字,则这两个数字形成一个逆序。在数字华容道中,忽略空位,将盘面上的数字从上到下、从左到右排列成一个序列,然后计算这个序列的逆序数总和。如果逆序数的总和是偶数,那么这个布局是有解的;如果是奇数,则这个布局是无解的
                                </p>
                                <p>
                                        <strong>例如:</strong>如果一个布局的数字序列(空格忽略不计)是12345678,那么其逆序数为0(因为它已经是顺序排列),这是一个有解的布局。如果布局是12345687,其逆序数为1(因为只有数字8和7是逆序的),所以这个布局是无解的
                                </p>
                                <div id="desc" style="color: red;visibility: hidden;">
                                        逆序数为“奇数”,次局无解,建议重开<br>
                                        <br>
                                        <br>
                                        <br>
                                </div>
                        </div>
                </div>
                <script>
                        const step = document.getElementById('num');
                        const error = document.getElementById('error');
                        const desc = document.getElementById('desc');
                        const input = document.querySelector('input')
                        const seed = ;
                        let custom_seed = [];
                        // 计算逆序数总和
                        const countInversions = (arr) => {
                                // 定义变量inversions用于计数
                                let inversions = 0;
                                // 遍历数组arr,从第一个元素开始,到最后一个元素结束
                                for (let i = 0; i < arr.length - 1; i++) {
                                        // 内层循环,从i+1开始,到最后一个元素结束
                                        for (let j = i + 1; j < arr.length; j++) {
                                                // 如果arr比arr大,则计数加1
                                                if (arr > arr) {
                                                        inversions++;
                                                }
                                        }
                                }
                                // 返回计数结果
                                return inversions;
                        }
                        // 随机数组
                        const shuffle = (array) => {
                                for (let i = array.length - 1; i > 0; i--) {
                                        const j = Math.floor(Math.random() * (i + 1));
                                        , array] = , array];
                                }
                                return array;
                        }
                        // 检查结果
                        const check = () => {
                                let flag = true;
                                document.querySelectorAll('td').forEach((item, i) => {
                                        if (i + 1 !== parseInt(item.innerText)) {
                                                flag = false;
                                        }
                                })
                                if (flag) {
                                        error.innerText = '恭喜你通关啦!&#128076;';
                                }
                        }
                        // 更新 td 数据
                        const init = () => {
                                desc.style.visibility = 'hidden'
                                const series = []; // 数列
                                const data = custom_seed.length ? custom_seed : shuffle(seed);
                                const tds = document.querySelectorAll('td');
                                for (let i = 0; i < tds.length - 1; i++) {
                                        let td = tds;
                                        td.innerText = data;
                                        td.className = ''
                                        series.push(data);
                                }
                                error.innerText = '';
                                step.innerText = 0;
                                const last = tds;
                                last.className = 'current'
                                last.innerText = '';
                                // 数列(逆序数)计算,次局是否有解
                                const total = countInversions(series)
                                if (total % 2 !== 0) desc.style.visibility = 'visible';
                                custom_seed = []; // 清空
                                seed.sort(); // 恢复
                        }
                        init()
                        // 重开
                        document.getElementById('reset').addEventListener('click', () => {
                                input.value = '';
                                init();
                        });
                        // 自定义数列
                        document.getElementById('confirm').addEventListener('click', () => {
                                const value = input.value;
                                if (value) {
                                        custom_seed = value.split(',').filter(item => {
                                                if (item) return item
                                        }).map(item => {
                                                return parseInt(item)
                                        });
                                        let sort_seed = [];
                                        sort_seed = [...custom_seed]
                                        if (seed.toString() !== sort_seed.sort().toString()) {
                                                alert('指定数列错误,请输入1~8英文逗号分隔');
                                                return;
                                        }
                                        init();
                                }
                        });
                        // 监听点击事件,移动方块处理
                        document.querySelector('table').addEventListener('click', (event) => {
                                const target = event.target;
                                const current = document.querySelector('.current');

                                const {
                                        x: cx,
                                        y: cy
                                } = current.getBoundingClientRect();
                                const {
                                        x: tx,
                                        y: ty
                                } = target.getBoundingClientRect();
                                const w = Math.abs(cx - tx);
                                const h = Math.abs(cy - ty);
                                if ((cx === tx || ty === cy) && (w < 200 && h < 200)) {
                                        if (target.nodeName === 'TD' && target !== current) {
                                                const innerText = target.innerText;
                                                target.classList = 'current';
                                                target.innerText = '';
                                                // 当前空白块
                                                current.innerText = innerText
                                                current.classList.remove('current');
                                                // 更新步骤
                                                let num = step.innerText || 0;
                                                num++;
                                                step.innerText = num;
                                                error.innerText = '';
                                                check();
                                        }
                                } else {
                                        error.innerText = '不能这样哦&#128512;';
                                }
                        })
                </script>
        </body>
</html>
```

kkuto 发表于 2024-3-14 15:18

请问这段代码为什么可以保证这是一道有解的华容道啊
         // 随机数组
            const shuffle = (array) => {
                for (let i = array.length - 1; i > 0; i--) {
                  const j = Math.floor(Math.random() * (i + 1));
                  , array] = , array];
                }
                return array;
            }

milkyway123 发表于 2024-3-14 09:43

谢谢分享谢谢分享

wsz214 发表于 2024-3-14 09:46

这个可以下来试试,新手不知道能不能下载

mr88fang 发表于 2024-3-14 09:49

wsz214 发表于 2024-3-14 09:46
这个可以下来试试,新手不知道能不能下载

上面有源码拷贝,新建txt文本粘贴进去,后缀名改Html就可以了

mr88fang 发表于 2024-3-14 09:59

补充在线预览地址 https://hua.playcode.io/

A2407118 发表于 2024-3-14 10:00

感谢分享

btmanman 发表于 2024-3-14 10:04

感谢分享

Qim626 发表于 2024-3-14 10:19

很不好,写的很好!支持!
期待可以持续优化升级!

qq421305628 发表于 2024-3-14 10:21

写的很有意思,支持一下

anoming 发表于 2024-3-14 10:26

纯js写的,真利害,要能点击自动移到空位就更好了
页: [1] 2 3 4 5
查看完整版本: [数字华容道] Html+css+js 实现小游戏