深入解析:js--2048小游戏

以下是一个完整的2048 游戏(DOM 操控版) 的 HTML 实现代码,包含 CSS 样式和 JavaScript 游戏逻辑,可直接保存为 .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 {
            font-family: Arial, sans-serif;
            text-align: center;
            background-color: #faf8ef;
            margin: 0;
            padding: 20px;
            }
            h1 {
            font-size: 40px;
            margin: 0;
            color: #776e65;
            }
            .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            width: 450px;
            margin: 0 auto 20px;
            }
            .score-container {
            background-color: #bbada0;
            color: white;
            padding: 5px 15px;
            border-radius: 5px;
            font-weight: bold;
            }
            #game-board {
            width: 450px;
            height: 450px;
            background-color: #bbada0;
            margin: 0 auto;
            border-radius: 6px;
            padding: 15px;
            box-sizing: border-box;
            position: relative;
            }
            .grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-gap: 15px;
            width: 100%;
            height: 100%;
            }
            .cell {
            background-color: #cdc1b4;
            border-radius: 5px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 35px;
            font-weight: bold;
            color: #776e65;
            }
            .tile {
            width: 100%;
            height: 100%;
            border-radius: 5px;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #eee4da;
            transition: all 0.1s ease-in-out;
            }
            .tile-2 {
            background-color: #eee4da;
            }
            .tile-4 {
            background-color: #ede0c8;
            }
            .tile-8 {
            background-color: #f2b179;
            color: white;
            }
            .tile-16 {
            background-color: #f59563;
            color: white;
            }
            .tile-32 {
            background-color: #f67c5f;
            color: white;
            }
            .tile-64 {
            background-color: #f65e3b;
            color: white;
            }
            .tile-128 {
            background-color: #edcf72;
            color: white;
            font-size: 30px;
            }
            .tile-256 {
            background-color: #edcc61;
            color: white;
            font-size: 30px;
            }
            .tile-512 {
            background-color: #edc850;
            color: white;
            font-size: 30px;
            }
            .tile-1024 {
            background-color: #edc53f;
            color: white;
            font-size: 25px;
            }
            .tile-2048 {
            background-color: #edc22e;
            color: white;
            font-size: 25px;
            }
            .game-over {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(238, 228, 218, 0.73);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            border-radius: 6px;
            z-index: 100;
            display: none;
            }
            .game-over-text {
            font-size: 60px;
            font-weight: bold;
            color: #776e65;
            margin-bottom: 30px;
            }
            button {
            background-color: #8f7a66;
            color: white;
            border: none;
            border-radius: 5px;
            padding: 10px 20px;
            font-size: 18px;
            cursor: pointer;
            }
            button:hover {
            background-color: #9f8b77;
            }
          </style>
        </head>
        <body>
            <div class="header">
          <h1>2048</h1>
              <div class="score-container">
            <div>分数: <span id="score">0</span></div>
            </div>
          </div>
            <div id="game-board">
          <div class="grid" id="grid"></div>
              <div class="game-over" id="game-over">
            <div class="game-over-text">游戏结束!</div>
            <button onclick="resetGame()">再玩一次</button>
            </div>
          </div>
          <script>
            // 游戏状态
            let grid = [];
            let score = 0;
            const GRID_SIZE = 4;
            // 初始化游戏
            function initGame() {
            // 清空网格
            document.getElementById('grid').innerHTML = '';
            grid = Array(GRID_SIZE).fill().map(() =>
            Array(GRID_SIZE).fill(0));
            score = 0;
            updateScore();
            document.getElementById('game-over').style.display = 'none';
            // 创建网格单元格
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 0; j <
            GRID_SIZE; j++) {
            const cell = document.createElement('div');
            cell.className = 'cell';
            cell.id = `cell-${i
            }-${j
            }`;
            document.getElementById('grid').appendChild(cell);
            }
            }
            // 添加初始方块
            addRandomTile();
            addRandomTile();
            renderGrid();
            }
            // 添加随机方块
            function addRandomTile() {
            const emptyCells = [];
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 0; j <
            GRID_SIZE; j++) {
            if (grid[i][j] === 0) {
            emptyCells.push({i, j
            });
            }
            }
            }
            if (emptyCells.length >
            0) {
            const {i, j
            } = emptyCells[Math.floor(Math.random() * emptyCells.length)];
            grid[i][j] = Math.random() <
            0.9 ? 2 : 4;
            }
            }
            // 渲染网格
            function renderGrid() {
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 0; j <
            GRID_SIZE; j++) {
            const cell = document.getElementById(`cell-${i
            }-${j
            }`);
            cell.innerHTML = '';
            if (grid[i][j] !== 0) {
            const tile = document.createElement('div');
            tile.className = `tile tile-${grid[i][j]
            }`;
            tile.textContent = grid[i][j];
            cell.appendChild(tile);
            }
            }
            }
            }
            // 更新分数
            function updateScore() {
            document.getElementById('score').textContent = score;
            }
            // 移动方块
            function moveTiles(direction) {
            let moved = false;
            const oldGrid = JSON.parse(JSON.stringify(grid));
            // 根据方向处理移动
            switch (direction) {
            case 'up':
            for (let j = 0; j <
            GRID_SIZE; j++) {
            for (let i = 1; i <
            GRID_SIZE; i++) {
            if (grid[i][j] !== 0) {
            let k = i;
            while (k >
            0 && grid[k-1][j] === 0) {
            grid[k-1][j] = grid[k][j];
            grid[k][j] = 0;
            k--;
            moved = true;
            }
            if (k >
            0 && grid[k-1][j] === grid[k][j]) {
            grid[k-1][j] *= 2;
            score += grid[k-1][j];
            grid[k][j] = 0;
            moved = true;
            }
            }
            }
            }
            break;
            case 'down':
            for (let j = 0; j <
            GRID_SIZE; j++) {
            for (let i = GRID_SIZE - 2; i >= 0; i--) {
            if (grid[i][j] !== 0) {
            let k = i;
            while (k <
            GRID_SIZE - 1 && grid[k+1][j] === 0) {
            grid[k+1][j] = grid[k][j];
            grid[k][j] = 0;
            k++;
            moved = true;
            }
            if (k <
            GRID_SIZE - 1 && grid[k+1][j] === grid[k][j]) {
            grid[k+1][j] *= 2;
            score += grid[k+1][j];
            grid[k][j] = 0;
            moved = true;
            }
            }
            }
            }
            break;
            case 'left':
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 1; j <
            GRID_SIZE; j++) {
            if (grid[i][j] !== 0) {
            let k = j;
            while (k >
            0 && grid[i][k-1] === 0) {
            grid[i][k-1] = grid[i][k];
            grid[i][k] = 0;
            k--;
            moved = true;
            }
            if (k >
            0 && grid[i][k-1] === grid[i][k]) {
            grid[i][k-1] *= 2;
            score += grid[i][k-1];
            grid[i][k] = 0;
            moved = true;
            }
            }
            }
            }
            break;
            case 'right':
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = GRID_SIZE - 2; j >= 0; j--) {
            if (grid[i][j] !== 0) {
            let k = j;
            while (k <
            GRID_SIZE - 1 && grid[i][k+1] === 0) {
            grid[i][k+1] = grid[i][k];
            grid[i][k] = 0;
            k++;
            moved = true;
            }
            if (k <
            GRID_SIZE - 1 && grid[i][k+1] === grid[i][k]) {
            grid[i][k+1] *= 2;
            score += grid[i][k+1];
            grid[i][k] = 0;
            moved = true;
            }
            }
            }
            }
            break;
            }
            if (moved) {
            addRandomTile();
            updateScore();
            renderGrid();
            if (isGameOver()) {
            document.getElementById('game-over').style.display = 'flex';
            }
            }
            }
            // 检查游戏是否结束
            function isGameOver() {
            // 检查是否有空格
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 0; j <
            GRID_SIZE; j++) {
            if (grid[i][j] === 0) {
            return false;
            }
            }
            }
            // 检查是否有相邻相同数字
            for (let i = 0; i <
            GRID_SIZE; i++) {
            for (let j = 0; j <
            GRID_SIZE; j++) {
            if (j <
            GRID_SIZE - 1 && grid[i][j] === grid[i][j+1]) {
            return false;
            }
            if (i <
            GRID_SIZE - 1 && grid[i][j] === grid[i+1][j]) {
            return false;
            }
            }
            }
            return true;
            }
            // 重置游戏
            function resetGame() {
            initGame();
            }
            // 键盘控制
            document.addEventListener('keydown', function(event) {
            switch (event.key) {
            case 'ArrowUp':
            moveTiles('up');
            break;
            case 'ArrowDown':
            moveTiles('down');
            break;
            case 'ArrowLeft':
            moveTiles('left');
            break;
            case 'ArrowRight':
            moveTiles('right');
            break;
            }
            });
            // 触摸控制 (移动端支持)
            let touchStartX = 0;
            let touchStartY = 0;
            document.addEventListener('touchstart', function(event) {
            touchStartX = event.touches[0].clientX;
            touchStartY = event.touches[0].clientY;
            });
            document.addEventListener('touchend', function(event) {
            const touchEndX = event.changedTouches[0].clientX;
            const touchEndY = event.changedTouches[0].clientY;
            const dx = touchEndX - touchStartX;
            const dy = touchEndY - touchStartY;
            if (Math.abs(dx) > Math.abs(dy)) {
            if (dx >
            0) moveTiles('right');
            else moveTiles('left');
            } else {
            if (dy >
            0) moveTiles('down');
            else moveTiles('up');
            }
            });
            // 初始化游戏
            initGame();
          </script>
        </body>
      </html>

游戏机制说明

  1. 核心玩法

    • 使用方向键(或触摸滑动)移动方块
    • 相同数字的方块碰撞后会合并
    • 每次移动后随机生成一个 2 或 4 的新方块
  2. 特色实现

    • 响应式设计,支持键盘和触摸操作
    • 动态分数计算
    • 游戏结束检测
    • 不同数字的方块有不同的颜色样式
  3. 技术要点

    • 纯 DOM 执行实现,无第三方依赖
    • 二维数组管理游戏状态
    • 移动逻辑处理(包括合并和移动动画)

使用方法

  1. 将代码保存为 2048.html 文件
  2. 用浏览器打开即可开始游戏
  3. 键盘方向键控制移动,或触摸屏滑动操作

您可以根据必须修改样式或添加新功能,如最高分记录、动画效果等。

posted @ 2025-08-11 12:49  wzzkaifa  阅读(55)  评论(0)    收藏  举报