HTML5+JavaScript实现消消乐游戏

HTML5+JavaScript实现消消乐游戏

点击两个相邻的方块来交换它们位置。

如果交换后形成三个或更多相同图案的方块连成一线,这些方块会被消除。

消除后,上方的方块会下落填补空缺,顶部会生成新的方块。

每消除一个方块得10分。例如,如果一次消除了4个方块,玩家将得到40分。

运行效果如下图:

源码如下:


<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>基础消消乐游戏 - Emoji版</title>
    <style>
        body {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
            font-family: Arial, sans-serif;
        }
        #gameContainer {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        canvas {
            border: 2px solid #000;
            margin-bottom: 10px;
        }
        #scoreDisplay {
            font-size: 24px;
            margin-bottom: 10px;
        }
    </style>
</head>
<body>
    <div id="gameContainer">
        <div id="scoreDisplay">分数: 0</div>
        <canvas id="gameCanvas" width="400" height="400"></canvas>
    </div>

    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const scoreDisplay = document.getElementById('scoreDisplay');

        const GRID_SIZE = 8;
        const CELL_SIZE = canvas.width / GRID_SIZE;
        const EMOJIS = ['☮', '⚜', '♾ ', '☯', '⚛', '✳'];

        let grid = [];
        let selectedCell = null;
        let score = 0;

        function initGrid() {
            for (let i = 0; i < GRID_SIZE; i++) {
                grid[i] = [];
                for (let j = 0; j < GRID_SIZE; j++) {
                    grid[i][j] = EMOJIS[Math.floor(Math.random() * EMOJIS.length)];
                }
            }
        }

        function drawGrid() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.font = `${CELL_SIZE * 0.8}px Arial`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';

            for (let i = 0; i < GRID_SIZE; i++) {
                for (let j = 0; j < GRID_SIZE; j++) {
                    ctx.fillText(
                        grid[i][j], 
                        i * CELL_SIZE + CELL_SIZE / 2, 
                        j * CELL_SIZE + CELL_SIZE / 2
                    );
                }
            }

            if (selectedCell) {
                ctx.strokeStyle = 'black';
                ctx.lineWidth = 2;
                ctx.strokeRect(
                    selectedCell.x * CELL_SIZE, 
                    selectedCell.y * CELL_SIZE, 
                    CELL_SIZE, 
                    CELL_SIZE
                );
            }
        }

        function checkMatches() {
            let matched = [];
            
            // 检查水平匹配
            for (let j = 0; j < GRID_SIZE; j++) {
                let streak = 1;
                for (let i = 1; i < GRID_SIZE; i++) {
                    if (grid[i][j] === grid[i-1][j]) {
                        streak++;
                    } else {
                        if (streak >= 3) {
                            for (let k = i - streak; k < i; k++) {
                                matched.push({x: k, y: j});
                            }
                        }
                        streak = 1;
                    }
                }
                if (streak >= 3) {
                    for (let k = GRID_SIZE - streak; k < GRID_SIZE; k++) {
                        matched.push({x: k, y: j});
                    }
                }
            }
            
            // 检查垂直匹配
            for (let i = 0; i < GRID_SIZE; i++) {
                let streak = 1;
                for (let j = 1; j < GRID_SIZE; j++) {
                    if (grid[i][j] === grid[i][j-1]) {
                        streak++;
                    } else {
                        if (streak >= 3) {
                            for (let k = j - streak; k < j; k++) {
                                matched.push({x: i, y: k});
                            }
                        }
                        streak = 1;
                    }
                }
                if (streak >= 3) {
                    for (let k = GRID_SIZE - streak; k < GRID_SIZE; k++) {
                        matched.push({x: i, y: k});
                    }
                }
            }
            
            return matched;
        }

        function removeMatches(matches) {
            matches.forEach(cell => {
                grid[cell.x][cell.y] = null;
            });
            //updateScore(matches.length);
        }

        function updateScore(matchCount) {
            score += matchCount * 10;
            scoreDisplay.textContent = `分数: ${score}`;
        }

        function fillBlanks() {
            for (let i = 0; i < GRID_SIZE; i++) {
                let blanks = 0;
                for (let j = GRID_SIZE - 1; j >= 0; j--) {
                    if (!grid[i][j]) {
                        blanks++;
                    } else if (blanks > 0) {
                        grid[i][j + blanks] = grid[i][j];
                        grid[i][j] = null;
                    }
                }
                for (let j = 0; j < blanks; j++) {
                    grid[i][j] = EMOJIS[Math.floor(Math.random() * EMOJIS.length)];
                }
            }
        }

        function swapCells(cell1, cell2) {
            const temp = grid[cell1.x][cell1.y];
            grid[cell1.x][cell1.y] = grid[cell2.x][cell2.y];
            grid[cell2.x][cell2.y] = temp;
        }

        canvas.addEventListener('click', (event) => {
            const rect = canvas.getBoundingClientRect();
            const x = Math.floor((event.clientX - rect.left) / CELL_SIZE);
            const y = Math.floor((event.clientY - rect.top) / CELL_SIZE);

            if (selectedCell) {
                if ((Math.abs(selectedCell.x - x) === 1 && selectedCell.y === y) ||
                    (Math.abs(selectedCell.y - y) === 1 && selectedCell.x === x)) {
                    swapCells(selectedCell, {x, y});
                    let matches = checkMatches();
                    if (matches.length === 0) {
                        swapCells(selectedCell, {x, y});
                    } else {
                        let totalMatches = 0;
                        while (matches.length > 0) {
                            totalMatches += matches.length;
                            removeMatches(matches);
                            fillBlanks();
                            matches = checkMatches();
                        }
                        updateScore(totalMatches);  // 在所有匹配处理完后更新分数
                    }
                }
                selectedCell = null;
            } else {
                selectedCell = {x, y};
            }
            drawGrid();
        });

        function gameLoop() {
            drawGrid();
            requestAnimationFrame(gameLoop);
        }

        initGrid();
        gameLoop();
    </script>
</body>
</html>

在这个数字化的时代,人们越来越倾向于在电子屏幕前寻找趣与放松。而一款结合了HTML、CSS和JavaScript技术的健康消消游戏——“绿意盎然消消”应运而生,它不仅是一款简单的休闲娱产品,更是一种新型的健康生活方式的体现。 “绿意盎然消消”以其清新脱俗的设计理念,将游戏的界面设计得如同置身于一片翠绿的森林之中。玩家在游戏中仿佛成为了一位森林探险家,通过点击或拖动相同图案的植物图标来进行消除,每成功消除一组,就能听到清脆悦耳的自然音效,仿佛真的有微风拂过树叶,带来阵阵清爽。 这款游戏的核心玩法简单易懂,但却蕴含着深层次的策略性。玩家需要在限定的时间内,尽可能多地消除图标,以获得高分。随着关卡的推进,游戏的难度也会逐渐增加,新的元素如冰冻图标、爆炸果实等会陆续出现,考验玩家的反应速度和策略规划。 除了基本的消除玩法,游戏还融入了健康元素。例如,每当玩家连续消除一定数量的图标后,屏幕上会出现提示,提醒玩家适时休息,保护视力。此外,游戏还会记录玩家的游戏时长,并在适当的时候弹出提醒,鼓励玩家起身活动,避免长时间久坐对身体造成的伤害。 在视觉设计上,“绿意盎然消消”采用了柔和的绿色调为主色,搭配清新的植物图案,旨在营造一种宁静和谐的游戏氛围,让玩家在紧张的工作学习之余,能够得到心灵的舒缓和平静。同时,游戏中的动画效果流畅自然,每一次消除都伴随着精美的粒子特效,给玩家带来视觉上的享受。 在技术层面,游戏充分利用了HTML5的跨平台特性,使得玩家可以在不同的设备上无缝体验。CSS3的运用则为游戏带来了丰富的视觉效果和动态交互。而JavaScript则作为游戏逻辑的核心,保证了游戏的流畅运行和丰富多变的游戏机制。 总之,“绿意盎然消消”不仅是一款能够带给玩家欢游戏,更是一种倡导健康生活理念的媒介。它以其独特的设计和寓教于的方式,成为了现代人追求健康生活的一个新选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值