当前位置: 首页 > article >正文

HTML5+JavaScript实现连连看游戏

HTML5+JavaScript实现连连看游戏

连连看游戏连接规则:

只能连接相同图案(或图标、字符)的方块。

连线路径必须是由直线段组成的,最多可以有两个拐角。

连线路径必须是空的,不能穿过其他方块。

当两个相同图案的方块被有效连接时,它们会从游戏板上消失。当所有方块都被消除时,玩家获胜。

运行效果:

源码如下(参考https://blog.csdn.net/time1812/article/details/79513508 略有修改):

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>连连看</title>
    <style>
        /* 单元格边框样式 */
        .border {
            display: inline-block;
            width: 40px;
            height: 40px;
            font-weight: 600;
            font-size: 36px;
            margin: 1px;
        }

        /* 显示路径时的样式 */
        .border.showPath {
            background-color: #99FF00;
        }

        /* 单元格样式 */
        .cell {
            display: inline-block;
            width: 40px;
            height: 40px;
            border: 1px solid #0099FF;
            text-align: center;
            font-weight: 600;
            font-size: 36px;
            background-color: #FFFFFF;
            color: #000000;
        }

        /* 选中单元格的样式 */
        .cell.selected {
            background-color: #3399FF;
            color: #FFFFFF;
        }
 
        /* 显示路径的单元格样式 */
        .cell.showPath {
            background-color: #99FF00;
        }

        /* 行样式 */ 
        .row {
            display: block;
            height: 42px;
        }

        /* 游戏区域的边框样式 */
        #game {
            border: 2px solid #0033FF;
            width: 600px; /* 设置游戏区域的宽度  */
        }
    </style>
</head>
<body onselectstart="return false">
    <div id="game"></div>
    <script type="text/javascript">
        let nx = 12, ny = 8; // 游戏网格的宽和高
        let gameDiv = document.getElementById('game');
        let selectedCell = null; // 当前选中的方块
        let empty = '&nbsp;'; // 空方块
        let count = nx * ny; // 方块总数
        let cellArray = []; // 存储方块的数组

        // 获取特定坐标的方块
        function fc(x, y) {
            return (x < 0 || x > nx + 1 || y < 0 || y > ny + 1) ? null : cellArray[y][x];
        }

        // 获取方块的邻居
        function neighbors(c) {
            return [
                fc(c.x - 1, c.y),
                fc(c.x + 1, c.y),
                fc(c.x, c.y + 1),
                fc(c.x, c.y - 1)
            ];
        }

        // 查找连接路径
        function findPath(c, target, pathStack, turnCount) {
            if (!c) return false;
            let prev = pathStack[pathStack.length - 2];
            if (prev && prev.x !== c.x && prev.y !== c.y && ++turnCount > 2) return false;
            if (c === target) {
                pathStack.push(c);
                return true;
            }
            if (c.innerHTML !== empty || pathStack.includes(c)) return false;

            pathStack.push(c);
            let nexts = neighbors(c);
            for (let next of nexts) {
                if (findPath(next, target, pathStack, turnCount)) return true;
            }
            pathStack.pop();
            return false;
        }

        // 清除路径样式
        function clearPath(path) {
            for (let cell of path) {
                cell.classList.remove('showPath');
            }
        }

        // 绘制路径
        function drawPath(path) {
            for (let cell of path) {
                cell.classList.add('showPath');
            }
            setTimeout(clearPath, 150, path);
        }

        // 尝试匹配两个方块
        function tryMatch(ca, cb) {
            if (ca === cb || ca.innerHTML !== cb.innerHTML) return;

            let pathStack = [ca];
            let found = false;
            let nexts = neighbors(ca);
            for (let next of nexts) {
                if (findPath(next, cb, pathStack, 0)) {
                    found = true;
                    break;
                }
            }

            if (!found) return;

            ca.innerHTML = cb.innerHTML = empty;
            setTimeout(drawPath, 10, pathStack);
            count -= 2;
            if (count < 2) alert('You win!');
        }

        // 处理方块点击事件
        function onCellClicked() {
            if (this.innerHTML === empty) return;

            if (selectedCell) {
                tryMatch(selectedCell, this);
                selectedCell.className = 'cell';
                selectedCell = null;
            } else {
                selectedCell = this;
                selectedCell.className = 'cell selected';
            }
        }

        // 初始化游戏网格
        function init(m, n) {
            for (let i = 0; i < n + 2; i++) {
                let row = document.createElement('div');
                row.className = 'row';
                let cellArrayRow = [];
                cellArray.push(cellArrayRow);
                gameDiv.appendChild(row);
                for (let j = 0; j < m + 2; j++) {
                    let cell = document.createElement('div');
                    cellArrayRow.push(cell);
                    if (i === 0 || j === 0 || i === n + 1 || j === m + 1) {
                        cell.className = 'border';
                        cell.innerHTML = empty;
                    } else {
                        cell.className = 'cell';
                        cell.addEventListener('click', onCellClicked);
                    }
                    cell.id = j + '_gc_' + i;
                    cell.x = j;
                    cell.y = i;
                    row.appendChild(cell);
                }
            }
        }
        
        // 随机重置游戏
        function reset() {
            let all = count = nx * ny;
            let halfAll = all / 2;
            let tmp = [];
            for (let i = 0; i < halfAll; i++) {
                let c = symbols.charAt(Math.floor(Math.random() * 35));
                tmp.push(c, c);
            }
            for (let i = all - 1; i >= 0; i--) {
                let r = Math.floor(Math.random() * i);
                let c = tmp.splice(r, 1);
                let y = Math.floor(i / nx);
                let x = i - y * nx;
                fc(x + 1, y + 1).innerHTML = c;
            }
        }

        init(nx, ny);
        //let symbols = 'ABCDEFGHIGKLMNOPQRSTUVWXYZ123456789'; // 可用符号
        let symbols = 'πφω▽Ф#*∩+■▲▼◆●★♀∽※⊕☆㐃□◇△◎○Ω⊙Θ☮☯㊣@$θ'; // 可用符号

        reset(); // 初始化游戏
    </script>
</body>
</html>


http://www.kler.cn/a/421138.html

相关文章:

  • Linux 定时任务 命令解释 定时任务格式详解
  • PyTorch|彩色图片识别
  • 洛谷P2084
  • OD C卷 - 实现 【手机App防沉迷系统】
  • C++:map容器——自定义数据类型进行自定义排序规则
  • 贴片式内存卡 ​SD NAND​
  • 2025年软考开考科目有哪些?中高级科目哪个容易拿证?
  • 基于“微店 Park”模式下 2+1 链动模式商城小程序的创新发展与应用研究
  • 24年某马最新大数据相关软件安装文档
  • 每日小知识
  • autogen-agentchat 0.4.0.dev8版本的安装
  • HarmonyOS开发:关于签名信息配置详解
  • 【系统架构设计师】真题论文: 论软件质量保证及其应用(包括解题思路和素材)
  • Chromium网络调试篇-Fiddler 5.21.0 使用指南:捕获浏览器HTTP(S)流量(二)
  • CPU渲染和GPU渲染各自特点,优势,场景使用
  • 微信小程序横滑定位元素案例代码
  • 【GPT】代谢概念解读
  • uni-app打包为安卓APP的权限配置问题探索
  • 高效数据分析:五款报表工具助力企业智能决策
  • Spring Boot 启动流程详解
  • CSS定位技术详解:从基础到高级应用
  • koa中间件
  • AcWing 841. 字符串哈希
  • 深入探索进程间通信:System V IPC的机制与应用
  • PLC协议
  • eBPF:现代Linux的强大内核扩展技术