吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1863|回复: 45
收起左侧

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

  [复制链接]
mr88fang 发表于 2024-3-14 09:37
本帖最后由 mr88fang 于 2024-3-19 12:05 编辑

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

预览&代码地址

代码在线预览  效果预览

增加指定数列

代码示例

<!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>
                    [1,2,3]<br>
                    [4,5,6]<br>
                    [8,7, ]<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 = [1, 2, 3, 4, 5, 6, 7, 8];
            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[i]比arr[j]大,则计数加1
                        if (arr[i] > arr[j]) {
                            inversions++;
                        }
                    }
                }
                // 返回计数结果
                return inversions;
            }
            // 随机数组
            const shuffle = (array) => {
                for (let i = array.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [array[i], array[j]] = [array[j], array[i]];
                }
                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 = '恭喜你通关啦!👌';
                }
            }
            // 更新 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[i];
                    td.innerText = data[i];
                    td.className = ''
                    series.push(data[i]);
                }
                error.innerText = '';
                step.innerText = 0;
                const last = tds[tds.length - 1];
                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 = '不能这样哦😀';
                }
            })
        </script>
    </body>
</html>

效果图

效果图

免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
Pokone13 + 1 + 1 谢谢@Thanks!
爱飞的猫 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Qim626 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

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[i], array[j]] = [array[j], array[i]];
                }
                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写的,真利害,要能点击自动移到空位就更好了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-14 10:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表