基于HTML+JS实现的简单2048小游戏

 1.效果如下:

2.代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048 游戏</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #faf8ef;
            font-family: Arial, sans-serif;
        }
        .game-container {
            position: relative;
            width: 400px;
            height: 400px;
            background-color: #bbada0;
            border-radius: 10px;
            padding: 10px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
        }
        .tile {
            position: absolute;
            width: 80px;
            height: 80px;
            border-radius: 5px;
            font-size: 45px;
            font-weight: bold;
            color: #fff;
            text-align: center;
            line-height: 80px;
        }
        .tile-2 { background-color: #eee4da; }
        .tile-4 { background-color: #ede0c8; }
        .tile-8 { background-color: #f2b179; }
        .tile-16 { background-color: #f59563; }
        .tile-32 { background-color: #f67c5f; }
        .tile-64 { background-color: #f65e3b; }
        .tile-128 { background-color: #edcf72; }
        .tile-256 { background-color: #edcc61; }
        .tile-512 { background-color: #edc850; }
        .tile-1024 { background-color: #edc53f; }
        .tile-2048 { background-color: #edc22e; }
        .game-over, .game-win {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 36px;
            font-weight: bold;
            color: #ffffff;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
            display: none;
            padding: 20px;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 10px;
        }
        .game-over { background-color: #ff3b30; }
        .game-win { background-color: #4caf50; }
    </style>
</head>
<body>
<div class="game-container" id="gameContainer">
    <div class="game-over" id="gameOver">游戏结束</div>
    <div class="game-win" id="gameWin">你赢了!</div>
</div>
<script>
    const SIZE = 4;
    const TILE_SIZE = 80;
    const COLORS = {
        2: '#eee4da',
        4: '#ede0c8',
        8: '#f2b179',
        16: '#f59563',
        32: '#f67c5f',
        64: '#f65e3b',
        128: '#edcf72',
        256: '#edcc61',
        512: '#edc850',
        1024: '#edc53f',
        2048: '#edc22e'
    };

    const gameContainer = document.getElementById('gameContainer');
    const gameOverElement = document.getElementById('gameOver');
    const gameWinElement = document.getElementById('gameWin');
    let board = Array(SIZE).fill().map(() => Array(SIZE).fill(0));
    let hasMoved = false;

    function drawTile(x, y, value) {
        const tile = document.createElement('div');
        tile.className = `tile tile-${value}`;
        tile.style.left = `${x * TILE_SIZE}px`;
        tile.style.top = `${y * TILE_SIZE}px`;
        tile.textContent = value || '';
        gameContainer.appendChild(tile);
    }

    function renderBoard() {
        gameContainer.innerHTML = '';
        for (let x = 0; x < SIZE; x++) {
            for (let y = 0; y < SIZE; y++) {
                drawTile(x, y, board[x][y]);
            }
        }
        if (isGameOver()) {
            gameOverElement.style.display = 'block';
        } else if (isGameWon()) {
            gameWinElement.style.display = 'block';
        }
    }

    function initGame() {
        addRandomTile();
        addRandomTile();
        renderBoard();
        document.addEventListener('keydown', handleKeyPress);
    }

    function addRandomTile() {
        let emptyTiles = [];
        for (let x = 0; x < SIZE; x++) {
            for (let y = 0; y < SIZE; y++) {
                if (board[x][y] === 0) {
                    emptyTiles.push({ x, y });
                }
            }
        }
        if (emptyTiles.length === 0) return;

        const { x, y } = emptyTiles[Math.floor(Math.random() * emptyTiles.length)];
        board[x][y] = Math.random() < 0.9 ? 2 : 4;
    }

    function slideTiles(direction) {
        const oldBoard = JSON.stringify(board);
        switch (direction) {
            case 'up': slideUp(); break;
            case 'down': slideDown(); break;
            case 'left': slideLeft(); break;
            case 'right': slideRight(); break;
        }
        if (JSON.stringify(board) !== oldBoard) {
            addRandomTile();
            renderBoard();
        }
    }

    function slideUp() {
        for (let col = 0; col < SIZE; col++) {
            let values = [];
            for (let row = 0; row < SIZE; row++) {
                if (board[row][col] !== 0) {
                    values.push(board[row][col]);
                }
            }
            values = mergeValues(values);
            for (let row = 0; row < SIZE; row++) {
                board[row][col] = values[row] || 0;
            }
        }
    }

    function slideDown() {
        for (let col = 0; col < SIZE; col++) {
            let values = [];
            for (let row = SIZE - 1; row >= 0; row--) {
                if (board[row][col] !== 0) {
                    values.push(board[row][col]);
                }
            }
            values = mergeValues(values);
            for (let row = SIZE - 1; row >= 0; row--) {
                board[row][col] = values[SIZE - 1 - row] || 0;
            }
        }
    }

    function slideLeft() {
        for (let row = 0; row < SIZE; row++) {
            let values = [];
            for (let col = 0; col < SIZE; col++) {
                if (board[row][col] !== 0) {
                    values.push(board[row][col]);
                }
            }
            values = mergeValues(values);
            for (let col = 0; col < SIZE; col++) {
                board[row][col] = values[col] || 0;
            }
        }
    }

    function slideRight() {
        for (let row = 0; row < SIZE; row++) {
            let values = [];
            for (let col = SIZE - 1; col >= 0; col--) {
                if (board[row][col] !== 0) {
                    values.push(board[row][col]);
                }
            }
            values = mergeValues(values);
            for (let col = SIZE - 1; col >= 0; col--) {
                board[row][col] = values[SIZE - 1 - col] || 0;
            }
        }
    }

    function mergeValues(values) {
        let merged = [];
        for (let i = 0; i < values.length; i++) {
            if (i < values.length - 1 && values[i] === values[i + 1]) {
                merged.push(values[i] * 2);
                i++;
            } else {
                merged.push(values[i]);
            }
        }
        return merged;
    }

    function handleKeyPress(event) {
        switch (event.key) {
            case 'ArrowUp': slideTiles('up'); break;
            case 'ArrowDown': slideTiles('down'); break;
            case 'ArrowLeft': slideTiles('left'); break;
            case 'ArrowRight': slideTiles('right'); break;
        }
    }

    function isGameOver() {
        for (let row = 0; row < SIZE; row++) {
            for (let col = 0; col < SIZE; col++) {
                if (board[row][col] === 0 ||
                    (row < SIZE - 1 && board[row][col] === board[row + 1][col]) ||
                    (col < SIZE - 1 && board[row][col] === board[row][col + 1])) {
                    return false;
                }
            }
        }
        return true;
    }

    function isGameWon() {
        for (let row = 0; row < SIZE; row++) {
            for (let col = 0; col < SIZE; col++) {
                if (board[row][col] === 2048) {
                    return true;
                }
            }
        }
        return false;
    }

    initGame();
</script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Java小诚

新手一个,望包涵

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

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

打赏作者

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

抵扣说明:

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

余额充值