超萌来袭!用 HTML、CSS 和 JavaScript 打造可爱 2048 游戏

超萌来袭!用 HTML、CSS 和 JavaScript 打造可爱 2048 游戏


游戏链接

一、引言

在如今琳琅满目的游戏世界里,简单又好玩的小游戏总能吸引众多玩家的目光。2048 这款经典数字合并游戏,以其简洁的规则和富有挑战性的玩法,一直备受欢迎。今天,咱们就用 HTML、CSS 和 JavaScript 来打造一个独具特色的可爱版 2048 游戏,用可爱的动物图片替代传统数字,让游戏更加有趣!

二、游戏功能概述

1. 核心玩法

游戏规则依旧遵循经典 2048 的玩法,玩家使用键盘方向键(上、下、左、右)控制卡片移动,相同的卡片会合并成一个数值更大的卡片,目标是合并出数值为 2048 的卡片。

2. 独特设计

  • 可爱动物图片:用一系列可爱的动物图片替代了传统的数字,为游戏增添了不少萌趣。
  • 得分与最高分记录:游戏中实时显示当前得分,并且会记录玩家的历史最高分,激励玩家不断挑战自我。
  • 重置功能:玩家可以随时点击“重置”按钮,将游戏重置到初始状态,重新开始挑战。
  • 动物介绍按钮:鼠标悬浮在“动物介绍”按钮上时,会显示每个动物图片所代表的数字,而且数字采用不同的流动渐变色显示,与对应的图片整齐对齐,增加了游戏的趣味性和可探索性。
  • 胜利提示:当玩家成功合并出 2048 时,会弹出胜利提示框,给玩家满满的成就感。

三、代码实现详解

1. HTML 部分

HTML 负责构建游戏的基本结构,包括游戏标题、得分区域、游戏棋盘、游戏规则说明和胜利提示框等。以下是关键代码片段:

<div id="header">
    <h1>可爱 2048 游戏</h1>
    <div id="score-board">
        <div id="score">得分: 0</div>
        <div id="high-score">最高分: 0</div>
        <button id="reset-button" onclick="resetGame()">重置</button>
        <div id="animal-intro">
            动物介绍
            <div id="animal-intro-content">
                <p><span class="gradient-number">数字 2</span>: <img src="图片链接" alt="2" width="30"> </p>
                <!-- 其他数字和图片对应关系 -->
            </div>
        </div>
    </div>
</div>
<div id="game-board"></div>
<div id="game-rules">
    <p>游戏规则:使用键盘方向键(上、下、左、右)控制卡片移动,相同的卡片会合并成一个数值更大的卡片,目标是合并出数值为 2048 的卡片。</p>
</div>
<div id="win-modal">
    <div id="win-modal-content">
        <p>恭喜你已经合并了一只宇宙无敌最可爱的猫咪</p>
        <button onclick="closeWinModal()">确认</button>
    </div>
</div>

2. CSS 部分

CSS 用于美化游戏界面,包括设置背景颜色、字体样式、按钮样式、棋盘布局和动物介绍的悬浮效果等。特别地,为动物介绍中的数字设置了流动渐变色效果:

@keyframes gradient {
    
    
    0% {
    
    
        background-position: 0% 50%;
    }
    50% {
    
    
        background-position: 100% 50%;
    }
    100% {
    
    
        background-position: 0% 50%;
    }
}

.gradient-number {
    
    
    background-size: 200% 200%;
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
    animation: gradient 3s ease infinite;
}

#animal-intro-content p:nth-child(1) .gradient-number {
    
    
    background-image: linear-gradient(45deg, #ff00cc, #333399);
}
/* 其他数字的渐变色设置 */

3. JavaScript 部分

JavaScript 实现了游戏的核心逻辑,包括棋盘的初始化、随机卡片的生成、卡片的移动和合并、得分计算、胜利判断等。以下是部分关键函数:

// 初始化棋盘
function createBoard() {
    
    
    gameBoard.innerHTML = '';
    for (let i = 0; i < 4; i++) {
    
    
        for (let j = 0; j < 4; j++) {
    
    
            const cell = document.createElement('div');
            cell.classList.add('cell');
            if (board[i][j]!== 0) {
    
    
                const tile = document.createElement('div');
                tile.classList.add('tile');
                tile.style.backgroundImage = `url(${
      
      images[board[i][j]]})`;
                cell.appendChild(tile);
            }
            gameBoard.appendChild(cell);
        }
    }
    scoreElement.textContent = `得分: ${
      
      score}`;
}

// 随机添加卡片
function addRandomTile() {
    
    
    const emptyCells = [];
    for (let i = 0; i < 4; i++) {
    
    
        for (let j = 0; j < 4; j++) {
    
    
            if (board[i][j] === 0) {
    
    
                emptyCells.push({
    
     i, j });
            }
        }
    }
    if (emptyCells.length > 0) {
    
    
        const randomIndex = Math.floor(Math.random() * emptyCells.length);
        const {
    
     i, j } = emptyCells[randomIndex];
        board[i][j] = Math.random() < 0.9? 2 : 4;
    }
}

// 合并卡片
function mergeTiles(row) {
    
    
    let newRow = row.filter(tile => tile!== 0);
    for (let i = 0; i < newRow.length - 1; i++) {
    
    
        if (newRow[i] === newRow[i + 1]) {
    
    
            newRow[i] *= 2;
            score += newRow[i];
            if (newRow[i] === 2048) {
    
    
                showWinModal();
            }
            newRow[i + 1] = 0;
        }
    }
    newRow = newRow.filter(tile => tile!== 0);
    while (newRow.length < 4) {
    
    
        newRow.push(0);
    }
    return newRow;
}

四、运行与体验

将上述 HTML、CSS 和 JavaScript 代码整合到一个 HTML 文件中,用浏览器打开该文件,就可以开始游戏啦!在游戏过程中,你能感受到可爱动物图片带来的愉悦,还能不断挑战自己的最高分。

在这里插入图片描述

五、总结

通过这个项目,我们不仅重温了经典的 2048 游戏,还学习了如何运用 HTML、CSS 和 JavaScript 来实现一个完整的网页游戏。从页面布局到样式设计,再到核心逻辑的实现,每一个环节都充满了乐趣和挑战。希望大家能喜欢这个可爱版的 2048 游戏,也可以根据自己的喜好对代码进行修改和扩展,创造出属于自己的独特游戏!

赶紧动手试试吧,说不定你就是下一个游戏小达人!
下面是完整代码,保存为html文件就可以打开玩了。

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可爱 2048 游戏</title>
    <style>
        body {
            background-color: #faf8ef;
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
        }

        #header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 90%;
            max-width: 500px;
            color: #776e65;
        }

        h1 {
            margin: 0;
        }

        #score-board {
            display: flex;
            gap: 10px;
        }

        #score,
        #high-score {
            background-color: #bbada0;
            color: white;
            padding: 5px 10px;
            border-radius: 5px;
        }

        #reset-button {
            background-color: #8f7a66;
            color: white;
            padding: 5px 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }

        #animal-intro {
            background-color: #8f7a66;
            color: white;
            padding: 5px 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            position: relative;
        }

        #animal-intro-content {
            display: none;
            position: absolute;
            background-color: #f9f9f9;
            min-width: 160px;
            box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
            padding: 12px 16px;
            z-index: 1;
            top: 100%;
            left: 0;
        }

        #animal-intro:hover #animal-intro-content {
            display: block;
        }

        #animal-intro-content p {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        @keyframes gradient {
            0% {
                background-position: 0% 50%;
            }
            50% {
                background-position: 100% 50%;
            }
            100% {
                background-position: 0% 50%;
            }
        }

        .gradient-number {
            background-size: 200% 200%;
            background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
            animation: gradient 3s ease infinite;
        }

        #animal-intro-content p:nth-child(1) .gradient-number {
            background-image: linear-gradient(45deg, #ff00cc, #333399);
        }

        #animal-intro-content p:nth-child(2) .gradient-number {
            background-image: linear-gradient(45deg, #ff6600, #ffcc00);
        }

        #animal-intro-content p:nth-child(3) .gradient-number {
            background-image: linear-gradient(45deg, #00ff00, #0066ff);
        }

        #animal-intro-content p:nth-child(4) .gradient-number {
            background-image: linear-gradient(45deg, #ff0000, #ff9900);
        }

        #animal-intro-content p:nth-child(5) .gradient-number {
            background-image: linear-gradient(45deg, #9900ff, #33cc33);
        }

        #animal-intro-content p:nth-child(6) .gradient-number {
            background-image: linear-gradient(45deg, #0099ff, #ff00ff);
        }

        #animal-intro-content p:nth-child(7) .gradient-number {
            background-image: linear-gradient(45deg, #ff3399, #00ccff);
        }

        #animal-intro-content p:nth-child(8) .gradient-number {
            background-image: linear-gradient(45deg, #66ff33, #ff66cc);
        }

        #animal-intro-content p:nth-child(9) .gradient-number {
            background-image: linear-gradient(45deg, #00ffcc, #ff9933);
        }

        #animal-intro-content p:nth-child(10) .gradient-number {
            background-image: linear-gradient(45deg, #ff0066, #33ff99);
        }

        #animal-intro-content p:nth-child(11) .gradient-number {
            background-image: linear-gradient(45deg, #99ff33, #ff0099);
        }

        #game-board {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(4, 1fr);
            gap: 10px;
            background-color: #bbada0;
            padding: 10px;
            border-radius: 5px;
            width: 90%;
            max-width: 500px;
            margin: 20px 0;
        }

        .cell {
            background-color: rgba(238, 228, 218, 0.35);
            border-radius: 5px;
            aspect-ratio: 1/1;
        }

        .tile {
            width: 100%;
            height: 100%;
            background-size: cover;
            border-radius: 5px;
        }

        #game-rules {
            text-align: left;
            color: #776e65;
            width: 90%;
            max-width: 500px;
            font-size: 14px;
        }

        #win-modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            align-items: center;
            justify-content: center;
        }

        #win-modal-content {
            background-color: white;
            padding: 20px;
            border-radius: 5px;
            text-align: center;
        }
    </style>
</head>

<body>
    <div id="header">
        <h1>可爱 2048 游戏</h1>
        <div id="score-board">
            <div id="score">得分: 0</div>
            <div id="high-score">最高分: 0</div>
            <button id="reset-button" onclick="resetGame()">重置</button>
            <div id="animal-intro">
                动物介绍
                <div id="animal-intro-content">
                    <p><span class="gradient-number">数字 2</span>: <img src="https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/df099f209335f8b25e1d4ab9ce2867ff_1741677321668230149.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213321&x-signature=reNM%2F907NNX7Rc%2BE4FflYbWaRKo%3D" alt="2" width="30"> </p>
                    <p><span class="gradient-number">数字 4</span>: <img src="https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/322b9826909d14458d22e0931fd06aac_1741677330491084517.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213330&x-signature=a1ptVuhTOwjrpRZSdnL%2FUKYV9MY%3D" alt="4" width="30"> </p>
                    <p><span class="gradient-number">数字 8</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/1a563d103b7496a5b9eb365ff9ea58bd_1741677409407029394.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213409&x-signature=L0drmZ0N1Z2%2BjUD9g9gcP0Nn7TM%3D" alt="8" width="30"> </p>
                    <p><span class="gradient-number">数字 16</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f51aebc9e6d5eee19fc026e3f1070185_1741677412756659826.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213412&x-signature=%2F%2FMLyi7m%2Bu%2Fo%2F%2FTQeYqmUWeDtLQ%3D" alt="16" width="30"> </p>
                    <p><span class="gradient-number">数字 32</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/8693822e52091fd6896366ae4e922bc2_1741677429462075923.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213429&x-signature=tLOJO0F5DKTLStoKnja6l2fr%2FOg%3D" alt="32" width="30"> </p>
                    <p><span class="gradient-number">数字 64</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/5fbb02d79c0f16f69ec86ea7a83d7e36_1741677431738410576.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213431&x-signature=Ry8L%2FkXszOCFFHkMeIdKm6Ktg%2FQ%3D" alt="64" width="30"> </p>
                    <p><span class="gradient-number">数字 128</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f2c91103fc53286b5d481390c12d665f_1741677444595987213.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213444&x-signature=X5AHPsnNLXS25hlANqlvTtpSQmc%3D" alt="128" width="30"> </p>
                    <p><span class="gradient-number">数字 256</span>: <img src="https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/9f4e790544e519f8c110d2c73e7b03bf_1741677446066399364.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213446&x-signature=DmV9R3QrONwWz%2F4fUnoceUjiU8E%3D" alt="256" width="30"> </p>
                    <p><span class="gradient-number">数字 512</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/8f72db8a79741930894920bc8faced83_1741677458934448994.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213458&x-signature=YxMhmlrT%2FY7brkyal9u5oaifd3g%3D" alt="512" width="30"> </p>
                    <p><span class="gradient-number">数字 1024</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f565fa57b977fa953208f7a2b4edd839_1741677459756646895.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213459&x-signature=r0bBAR7T7NVF3dyu1aGI%2FlWfR4w%3D" alt="1024" width="30"> </p>
                    <p><span class="gradient-number">数字 2048</span>: <img src="https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/dbb80e7d3948b8af02664915eeee38d2_1741677502512862779.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213502&x-signature=Bv%2FEdGFqr%2Bq47a8g1D4KiU9XYqQ%3D" alt="2048" width="30"> </p>
                </div>
            </div>
        </div>
    </div>
    <div id="game-board"></div>
    <div id="game-rules">
        <p>游戏规则:使用键盘方向键(上、下、左、右)控制卡片移动,相同的卡片会合并成一个数值更大的卡片,目标是合并出数值为 2048 的卡片。</p>
    </div>
    <div id="win-modal">
        <div id="win-modal-content">
            <p>恭喜你已经合并了一只宇宙无敌最可爱的猫咪</p>
            <button onclick="closeWinModal()">确认</button>
        </div>
    </div>
    <script>
        const gameBoard = document.getElementById('game-board');
        const winModal = document.getElementById('win-modal');
        const scoreElement = document.getElementById('score');
        const highScoreElement = document.getElementById('high-score');

        const images = {
            2: 'https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/df099f209335f8b25e1d4ab9ce2867ff_1741677321668230149.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213321&x-signature=reNM%2F907NNX7Rc%2BE4FflYbWaRKo%3D',
            4: 'https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/322b9826909d14458d22e0931fd06aac_1741677330491084517.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213330&x-signature=a1ptVuhTOwjrpRZSdnL%2FUKYV9MY%3D',
            8: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/1a563d103b7496a5b9eb365ff9ea58bd_1741677409407029394.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213409&x-signature=L0drmZ0N1Z2%2BjUD9g9gcP0Nn7TM%3D',
            16: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f51aebc9e6d5eee19fc026e3f1070185_1741677412756659826.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213412&x-signature=%2F%2FMLyi7m%2Bu%2Fo%2F%2FTQeYqmUWeDtLQ%3D',
            32: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/8693822e52091fd6896366ae4e922bc2_1741677429462075923.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213429&x-signature=tLOJO0F5DKTLStoKnja6l2fr%2FOg%3D',
            64: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/5fbb02d79c0f16f69ec86ea7a83d7e36_1741677431738410576.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213431&x-signature=Ry8L%2FkXszOCFFHkMeIdKm6Ktg%2FQ%3D',
            128: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f2c91103fc53286b5d481390c12d665f_1741677444595987213.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213444&x-signature=X5AHPsnNLXS25hlANqlvTtpSQmc%3D',
            256: 'https://p9-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/9f4e790544e519f8c110d2c73e7b03bf_1741677446066399364.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213446&x-signature=DmV9R3QrONwWz%2F4fUnoceUjiU8E%3D',
            512: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/8f72db8a79741930894920bc8faced83_1741677458934448994.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213458&x-signature=YxMhmlrT%2FY7brkyal9u5oaifd3g%3D',
            1024: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/f565fa57b977fa953208f7a2b4edd839_1741677459756646895.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213459&x-signature=r0bBAR7T7NVF3dyu1aGI%2FlWfR4w%3D',
            2048: 'https://p3-flow-imagex-sign.byteimg.com/ocean-cloud-tos/image_generation/dbb80e7d3948b8af02664915eeee38d2_1741677502512862779.png~tplv-a9rns2rl98-image.png?rk3s=25bff839&x-expires=1773213502&x-signature=Bv%2FEdGFqr%2Bq47a8g1D4KiU9XYqQ%3D'
        };

        let board = [
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0]
        ];
        let score = 0;
        let highScore = localStorage.getItem('highScore')? parseInt(localStorage.getItem('highScore')) : 0;
        highScoreElement.textContent = `最高分: ${highScore}`;

        function createBoard() {
            gameBoard.innerHTML = '';
            for (let i = 0; i < 4; i++) {
                for (let j = 0; j < 4; j++) {
                    const cell = document.createElement('div');
                    cell.classList.add('cell');
                    if (board[i][j]!== 0) {
                        const tile = document.createElement('div');
                        tile.classList.add('tile');
                        tile.style.backgroundImage = `url(${images[board[i][j]]})`;
                        cell.appendChild(tile);
                    }
                    gameBoard.appendChild(cell);
                }
            }
            scoreElement.textContent = `得分: ${score}`;
        }

        function addRandomTile() {
            const emptyCells = [];
            for (let i = 0; i < 4; i++) {
                for (let j = 0; j < 4; j++) {
                    if (board[i][j] === 0) {
                        emptyCells.push({ i, j });
                    }
                }
            }
            if (emptyCells.length > 0) {
                const randomIndex = Math.floor(Math.random() * emptyCells.length);
                const { i, j } = emptyCells[randomIndex];
                board[i][j] = Math.random() < 0.9? 2 : 4;
            }
        }

        function mergeTiles(row) {
            let newRow = row.filter(tile => tile!== 0);
            for (let i = 0; i < newRow.length - 1; i++) {
                if (newRow[i] === newRow[i + 1]) {
                    newRow[i] *= 2;
                    score += newRow[i];
                    if (newRow[i] === 2048) {
                        showWinModal();
                    }
                    newRow[i + 1] = 0;
                }
            }
            newRow = newRow.filter(tile => tile!== 0);
            while (newRow.length < 4) {
                newRow.push(0);
            }
            return newRow;
        }

        function moveLeft() {
            let moved = false;
            for (let i = 0; i < 4; i++) {
                const oldRow = [...board[i]];
                board[i] = mergeTiles(board[i]);
                if (oldRow.join(',')!== board[i].join(',')) {
                    moved = true;
                }
            }
            if (moved) {
                addRandomTile();
            }
            updateScore();
            createBoard();
        }

        function moveRight() {
            let moved = false;
            for (let i = 0; i < 4; i++) {
                const oldRow = [...board[i]];
                const reversedRow = board[i].slice().reverse();
                const newReversedRow = mergeTiles(reversedRow);
                board[i] = newReversedRow.reverse();
                if (oldRow.join(',')!== board[i].join(',')) {
                    moved = true;
                }
            }
            if (moved) {
                addRandomTile();
            }
            updateScore();
            createBoard();
        }

        function moveUp() {
            let moved = false;
            for (let j = 0; j < 4; j++) {
                const column = [];
                for (let i = 0; i < 4; i++) {
                    column.push(board[i][j]);
                }
                const oldColumn = [...column];
                const newColumn = mergeTiles(column);
                for (let i = 0; i < 4; i++) {
                    board[i][j] = newColumn[i];
                }
                if (oldColumn.join(',')!== newColumn.join(',')) {
                    moved = true;
                }
            }
            if (moved) {
                addRandomTile();
            }
            updateScore();
            createBoard();
        }

        function moveDown() {
            let moved = false;
            for (let j = 0; j < 4; j++) {
                const column = [];
                for (let i = 0; i < 4; i++) {
                    column.push(board[i][j]);
                }
                const oldColumn = [...column];
                const reversedColumn = column.slice().reverse();
                const newReversedColumn = mergeTiles(reversedColumn);
                const newColumn = newReversedColumn.reverse();
                for (let i = 0; i < 4; i++) {
                    board[i][j] = newColumn[i];
                }
                if (oldColumn.join(',')!== newColumn.join(',')) {
                    moved = true;
                }
            }
            if (moved) {
                addRandomTile();
            }
            updateScore();
            createBoard();
        }

        function handleKeyPress(event) {
            switch (event.key) {
                case 'ArrowLeft':
                    moveLeft();
                    break;
                case 'ArrowRight':
                    moveRight();
                    break;
                case 'ArrowUp':
                    moveUp();
                    break;
                case 'ArrowDown':
                    moveDown();
                    break;
            }
        }

        function showWinModal() {
            winModal.style.display = 'flex';
        }

        function closeWinModal() {
            winModal.style.display = 'none';
        }

        function updateScore() {
            if (score > highScore) {
                highScore = score;
                highScoreElement.textContent = `最高分: ${highScore}`;
                localStorage.setItem('highScore', highScore);
            }
            scoreElement.textContent = `得分: ${score}`;
        }

        function resetGame() {
            board = [
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0]
            ];
            score = 0;
            addRandomTile();
            addRandomTile();
            createBoard();
            updateScore();
            closeWinModal();
        }

        window.addEventListener('keydown', handleKeyPress);

        addRandomTile();
        addRandomTile();
        createBoard();
    </script>
</body>

</html>