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

“2048”游戏网页版html+css+js

“2048”游戏网页版html+css+js

 别忘了请点个赞+收藏+关注支持一下博主喵!!!

   2048 游戏是一个非常流行的数字拼图游戏,玩家通过移动方块使相同数字的方块合并,最终达到 2048 或更高分数。本教程将详细介绍如何使用 HTML、CSS 和 JavaScript 创建一个简单的 2048 游戏网页。。

  项目结构如下:(懒得搭vue了)

2048-game/
├── index.html
├── styles.css
└── script.js

1. index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> <!-- 设置文档的字符编码为 UTF-8 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 使页面在移动设备上适配屏幕宽度 -->
    <title>2048 Game</title> <!-- 页面标题 -->
    <link rel="stylesheet" href="styles.css"> <!-- 引入外部 CSS 文件 -->
</head>
<body>
    <div class="game-container"> <!-- 游戏容器,用于包裹整个游戏界面 -->
        <div class="score-container">0</div> <!-- 分数显示区域 -->
        <div class="grid-container"> <!-- 网格容器,用于包裹 4x4 的游戏网格 -->
            <div class="grid-row"> <!-- 每一行的网格 -->
                <div class="grid-cell"></div> <!-- 每一个网格单元 -->
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
            </div>
            <div class="grid-row">
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
            </div>
            <div class="grid-row">
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
            </div>
            <div class="grid-row">
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
                <div class="grid-cell"></div>
            </div>
        </div>
        <button id="restart-button">Restart</button> <!-- 重新开始按钮 -->
    </div>
    <script src="script.js"></script> <!-- 引入外部 JavaScript 文件 -->
</body>
</html>

2. styles.css

body {
    display: flex; /* 使用 Flexbox 布局 */
    justify-content: center; /* 水平居中 */
    align-items: center; /* 垂直居中 */
    height: 100vh; /* 占满整个视窗高度 */
    margin: 0; /* 移除默认外边距 */
    background-color: #faf8ef; /* 背景颜色 */
    font-family: Arial, sans-serif; /* 字体设置 */
}

.game-container {
    width: 500px; /* 容器宽度 */
    height: 500px; /* 容器高度 */
    position: relative; /* 相对定位 */
    background-color: #bbada0; /* 背景颜色 */
    border-radius: 10px; /* 圆角 */
    box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3); /* 阴影效果 */
}

.score-container {
    position: absolute; /* 绝对定位 */
    top: 10px; /* 距离顶部 10px */
    left: 10px; /* 距离左边 10px */
    background-color: #eee4da; /* 背景颜色 */
    padding: 10px; /* 内边距 */
    border-radius: 5px; /* 圆角 */
    font-size: 24px; /* 字体大小 */
    font-weight: bold; /* 加粗字体 */
}

.grid-container {
    width: 400px; /* 网格容器宽度 */
    height: 400px; /* 网格容器高度 */
    position: absolute; /* 绝对定位 */
    top: 50%; /* 距离顶部 50% */
    left: 50%; /* 距离左边 50% */
    transform: translate(-50%, -50%); /* 居中对齐 */
    display: grid; /* 使用 Grid 布局 */
    grid-template-columns: repeat(4, 100px); /* 4 列,每列 100px */
    grid-template-rows: repeat(4, 100px); /* 4 行,每行 100px */
    gap: 10px; /* 网格间距 */
}

.grid-cell {
    background-color: #cdc1b4; /* 背景颜色 */
    border-radius: 3px; /* 圆角 */
    display: flex; /* 使用 Flexbox 布局 */
    justify-content: center; /* 水平居中 */
    align-items: center; /* 垂直居中 */
    font-size: 32px; /* 字体大小 */
    font-weight: bold; /* 加粗字体 */
    color: #776e65; /* 文字颜色 */
}

/* 不同数字的方块样式 */
.grid-cell.number-2 { background-color: #eee4da; color: #776e65; }
.grid-cell.number-4 { background-color: #ede0c8; color: #776e65; }
.grid-cell.number-8 { background-color: #f2b179; color: #f9f6f2; }
.grid-cell.number-16 { background-color: #f59563; color: #f9f6f2; }
.grid-cell.number-32 { background-color: #f67c5f; color: #f9f6f2; }
.grid-cell.number-64 { background-color: #f65e3b; color: #f9f6f2; }
.grid-cell.number-128 { background-color: #edcf72; color: #f9f6f2; }
.grid-cell.number-256 { background-color: #edcc61; color: #f9f6f2; }
.grid-cell.number-512 { background-color: #edc850; color: #f9f6f2; }
.grid-cell.number-1024 { background-color: #edc53f; color: #f9f6f2; }
.grid-cell.number-2048 { background-color: #edc22e; color: #f9f6f2; }

#restart-button {
    position: absolute; /* 绝对定位 */
    bottom: 10px; /* 距离底部 10px */
    left: 50%; /* 距离左边 50% */
    transform: translateX(-50%); /* 水平居中 */
    padding: 10px 20px; /* 内边距 */
    background-color: #8f7a66; /* 背景颜色 */
    color: #f9f6f2; /* 文字颜色 */
    border: none; /* 无边框 */
    border-radius: 5px; /* 圆角 */
    cursor: pointer; /* 鼠标指针样式 */
    font-size: 18px; /* 字体大小 */
    font-weight: bold; /* 加粗字体 */
}

#restart-button:hover {
    background-color: #746655; /* 鼠标悬停时的背景颜色 */
}

3. 最难的script.js

代码分布详解:

1. 获取 DOM 元素

const grid = document.querySelector('.grid-container'); // 获取网格容器
const cells = document.querySelectorAll('.grid-cell'); // 获取所有网格单元
const scoreContainer = document.querySelector('.score-container'); // 获取分数显示区域
const restartButton = document.getElementById('restart-button'); // 获取重新开始按钮

这些代码通过 querySelectorgetElementById 方法获取页面上的各个元素,以便后续操作。

2. 初始化变量

let score = 0; // 初始化分数
let hasWon = false; // 标记是否已经赢得游戏

const matrix = [
    [0, 0, 0, 0], // 初始化 4x4 的矩阵
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
];

const winNumber = 2048; // 赢得游戏的目标数字
  • score:当前得分。
  • hasWon:标记是否已经赢得游戏。
  • matrix:4x4 的二维数组,用于存储游戏中的数字。
  • winNumber:赢得游戏的目标数字,即 2048。

 3. 获取随机空格子

function getRandomEmptyCell() {
    const emptyCells = []; // 存储所有空格子的坐标
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (matrix[i][j] === 0) { // 如果格子为空
                emptyCells.push({ row: i, col: j }); // 将坐标加入空格子列表
            }
        }
    }
    if (emptyCells.length > 0) { // 如果有空格子
        const randomIndex = Math.floor(Math.random() * emptyCells.length); // 随机选择一个空格子
        return emptyCells[randomIndex];
    }
    return null; // 没有空格子返回 null
}

这个函数遍历 matrix,找到所有为空的格子,并将它们的坐标存储在 emptyCells 数组中。如果存在空格子,则随机选择一个返回;否则返回 null。 

算法步骤:

  1. 初始化一个空数组 emptyCells,用于存储所有空格子的坐标。
  2. 使用两层嵌套循环遍历 matrix,检查每个格子是否为空(即 matrix[i][j] === 0)。
  3. 如果格子为空,将该格子的坐标 { row: i, col: j } 推入 emptyCells 数组。
  4. 循环结束后,检查 emptyCells 是否有元素。
  5. 如果有空格子,随机选择一个空格子的索引 randomIndex,并返回该空格子的坐标。
  6. 如果没有空格子,返回 null

4. 添加随机方块

function addRandomTile() {
    const cell = getRandomEmptyCell();
    if (cell) {
        const value = Math.random() < 0.9 ? 2 : 4; // 90% 的概率生成 2,10% 的概率生成 4
        matrix[cell.row][cell.col] = value; // 更新矩阵
        updateGrid(); // 更新网格显示
    }
}

这个函数调用 getRandomEmptyCell 获取一个随机的空格子,然后以 90% 的概率生成 2,10% 的概率生成 4,并更新 matrix 和网格显示。 

算法步骤:

  1. 调用 getRandomEmptyCell 获取一个随机的空格子。
  2. 如果找到了空格子:
    • 生成一个随机值 value,90% 的概率生成 2,10% 的概率生成 4。
    • 更新 matrix 中对应位置的值为 value
    • 调用 updateGrid 更新网格显示。

5. 更新网格显示

function updateGrid() {
    cells.forEach((cell, index) => {
        const row = Math.floor(index / 4); // 计算当前单元格所在的行
        const col = index % 4; // 计算当前单元格所在的列
        const value = matrix[row][col]; // 获取矩阵中的值
        cell.textContent = value || ''; // 显示值,如果没有值则显示空字符串
        cell.classList.remove('number-2', 'number-4', 'number-8', 'number-16', 'number-32', 'number-64', 'number-128', 'number-256', 'number-512', 'number-1024', 'number-2048'); // 移除所有样式类
        if (value !== 0) { // 如果有值,添加对应的样式类
            cell.classList.add(`number-${value}`);
        }
    });
}

这个函数遍历所有 cells,根据 matrix 中的值更新每个单元格的文本内容和样式类。 

算法步骤:

  1. 遍历所有 cells,使用 forEach 方法。
  2. 对于每个 cell,计算其在 matrix 中的行 row 和列 col
  3. 获取 matrix 中对应位置的值 value
  4. 设置 cell 的文本内容为 value,如果没有值则显示为空字符串。
  5. 移除 cell 上的所有样式类。
  6. 如果 value 不为 0,添加对应的样式类 number-${value}

6. 向上移动

function moveUp() {
    for (let col = 0; col < 4; col++) { // 遍历每一列
        let tempCol = []; // 临时存储非零值
        for (let row = 0; row < 4; row++) {
            if (matrix[row][col] !== 0) {
                tempCol.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempCol = mergeTiles(tempCol); // 合并相同的值
        for (let row = 0; row < 4; row++) {
            matrix[row][col] = tempCol[row] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

这个函数处理向上移动的操作:

  1. 遍历每一列。
  2. 将每列中的非零值存储到 tempCol 中。
  3. 调用 mergeTiles 合并相同的值。
  4. 更新 matrix
  5. 添加新的方块。
  6. 检查游戏是否结束。

算法步骤:

  1. 遍历每一列 col
  2. 初始化一个空数组 tempCol,用于存储当前列中的非零值。
  3. 使用内层循环遍历当前列的每一行 row,将非零值推入 tempCol
  4. 调用 mergeTiles 合并 tempCol 中的相同值。
  5. 使用内层循环更新 matrix 中当前列的值,从 tempCol 中取值,如果 tempCol 中没有值则设为 0。
  6. 调用 addRandomTile 添加一个新的方块。
  7. 调用 checkGameOver 检查游戏是否结束。

 7. 向下移动

function moveDown() {
    for (let col = 0; col < 4; col++) { // 遍历每一列
        let tempCol = []; // 临时存储非零值
        for (let row = 3; row >= 0; row--) {
            if (matrix[row][col] !== 0) {
                tempCol.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempCol = mergeTiles(tempCol); // 合并相同的值
        for (let row = 3; row >= 0; row--) {
            matrix[row][col] = tempCol[3 - row] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

这个函数处理向下移动的操作,与 moveUp 类似,只是方向相反。 

8. 向左移动

function moveLeft() {
    for (let row = 0; row < 4; row++) { // 遍历每一行
        let tempRow = []; // 临时存储非零值
        for (let col = 0; col < 4; col++) {
            if (matrix[row][col] !== 0) {
                tempRow.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempRow = mergeTiles(tempRow); // 合并相同的值
        for (let col = 0; col < 4; col++) {
            matrix[row][col] = tempRow[col] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

 这个函数处理向左移动的操作,与 moveUp 类似,只是方向不同。

  1. 遍历每一行 row
  2. 初始化一个空数组 tempRow,用于存储当前行中的非零值。
  3. 使用内层循环遍历当前行的每一列 col,将非零值推入 tempRow
  4. 调用 mergeTiles 合并 tempRow 中的相同值。
  5. 使用内层循环更新 matrix 中当前行的值,从 tempRow 中取值,如果 tempRow 中没有值则设为 0。
  6. 调用 addRandomTile 添加一个新的方块。
  7. 调用 checkGameOver 检查游戏是否结束。

9. 向右移动

function moveRight() {
    for (let row = 0; row < 4; row++) { // 遍历每一行
        let tempRow = []; // 临时存储非零值
        for (let col = 3; col >= 0; col--) {
            if (matrix[row][col] !== 0) {
                tempRow.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempRow = mergeTiles(tempRow); // 合并相同的值
        for (let col = 3; col >= 0; col--) {
            matrix[row][col] = tempRow[3 - col] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

这个函数处理向右移动的操作,与 moveLeft 类似,只是方向相反。 

10. 合并相同的值

function mergeTiles(tiles) {
    for (let i = 0; i < tiles.length - 1; i++) {
        if (tiles[i] === tiles[i + 1]) { // 如果相邻的两个值相同
            tiles[i] *= 2; // 合并值
            tiles.splice(i + 1, 1); // 删除合并后的值
            score += tiles[i]; // 更新分数
            scoreContainer.textContent = score; // 更新分数显示
            if (tiles[i] === winNumber && !hasWon) { // 如果达到目标值且未赢过
                alert('You Win!'); // 提示胜利
                hasWon = true; // 标记已赢
            }
        }
    }
    while (tiles.length < 4) { // 确保列表长度为 4
        tiles.push(0);
    }
    return tiles;
}

这个函数合并 tiles 列表中的相同值:

  1. 遍历 tiles,如果相邻的两个值相同,则合并它们。
  2. 更新分数和分数显示。
  3. 如果达到目标值 2048 且未赢过,则提示胜利。
  4. 确保 tiles 列表长度为 4。

算法步骤:

  1. 遍历 tiles 数组,检查相邻的两个值是否相同。
  2. 如果相邻的两个值相同:
    • 将第一个值乘以 2。
    • 从数组中删除第二个值。
    • 更新分数 score 并更新分数显示。
    • 如果合并后的值等于 winNumber 且未赢过,提示胜利并标记已赢。
  3. 使用 while 循环确保 tiles 数组的长度为 4,不足的部分用 0 填充。
  4. 返回合并后的 tiles 数组。

 11. 检查游戏是否结束

function checkGameOver() {
    let gameOver = true; // 默认游戏结束
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (matrix[i][j] === 0 || // 如果有空格子
                (i < 3 && matrix[i][j] === matrix[i + 1][j]) || // 或者有相邻的相同值
                (j < 3 && matrix[i][j] === matrix[i][j + 1])) {
                gameOver = false; // 游戏未结束
                break;
            }
        }
        if (!gameOver) break;
    }
    if (gameOver) {
        alert('Game Over!'); // 提示游戏结束
    }
}

这个函数检查游戏是否结束:

  1. 遍历 matrix,检查是否有空格子或相邻的相同值。
  2. 如果有空格子或相邻的相同值,则游戏未结束。
  3. 否则,提示游戏结束。

算法步骤:

  1. 初始化一个布尔变量 gameOver 为 true,默认游戏结束。
  2. 使用两层嵌套循环遍历 matrix,检查每个格子是否为空或有相邻的相同值。
  3. 如果有空格子或有相邻的相同值,将 gameOver 设为 false 并跳出循环。
  4. 如果 gameOver 仍为 true,提示游戏结束。

 12. 重新开始游戏

function restartGame() {
    matrix.forEach(row => row.fill(0)); // 重置矩阵
    score = 0; // 重置分数
    hasWon = false; // 重置胜利标记
    scoreContainer.textContent = score; // 更新分数显示
    addRandomTile(); // 添加初始方块
    addRandomTile(); // 添加初始方块
    updateGrid(); // 更新网格显示
}

这个函数重置游戏:

  1. 重置 matrix
  2. 重置分数和胜利标记。
  3. 更新分数显示。
  4. 添加两个初始方块。
  5. 更新网格显示。

算法步骤:

  1. 使用 forEach 方法遍历 matrix 的每一行,将每一行的值全部设为 0。
  2. 将分数 score 设为 0。
  3. 将胜利标记 hasWon 设为 false
  4. 更新分数显示。
  5. 调用 addRandomTile 两次,添加两个初始方块。
  6. 调用 updateGrid 更新网格显示。

 13. 监听键盘事件

document.addEventListener('keydown', (event) => {
    switch (event.key) {
        case 'ArrowUp': // 上箭头
            moveUp();
            break;
        case 'ArrowDown': // 下箭头
            moveDown();
            break;
        case 'ArrowLeft': // 左箭头
            moveLeft();
            break;
        case 'ArrowRight': // 右箭头
            moveRight();
            break;
    }
});

 这个事件监听器监听键盘事件,根据按键方向调用相应的移动函数

14. 监听重新开始按钮点击事件

restartButton.addEventListener('click', restartGame);

这个事件监听器监听重新开始按钮的点击事件,调用 restartGame 重置游戏。 

15. 初始化游戏

restartGame();

最终代码:

const grid = document.querySelector('.grid-container'); // 获取网格容器
const cells = document.querySelectorAll('.grid-cell'); // 获取所有网格单元
const scoreContainer = document.querySelector('.score-container'); // 获取分数显示区域
const restartButton = document.getElementById('restart-button'); // 获取重新开始按钮

let score = 0; // 初始化分数
let hasWon = false; // 标记是否已经赢得游戏

const matrix = [
    [0, 0, 0, 0], // 初始化 4x4 的矩阵
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
];

const winNumber = 2048; // 赢得游戏的目标数字

// 获取一个随机的空格子
function getRandomEmptyCell() {
    const emptyCells = []; // 存储所有空格子的坐标
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (matrix[i][j] === 0) { // 如果格子为空
                emptyCells.push({ row: i, col: j }); // 将坐标加入空格子列表
            }
        }
    }
    if (emptyCells.length > 0) { // 如果有空格子
        const randomIndex = Math.floor(Math.random() * emptyCells.length); // 随机选择一个空格子
        return emptyCells[randomIndex];
    }
    return null; // 没有空格子返回 null
}

// 在随机选择的空格子中添加一个新方块(2 或 4)
function addRandomTile() {
    const cell = getRandomEmptyCell();
    if (cell) {
        const value = Math.random() < 0.9 ? 2 : 4; // 90% 的概率生成 2,10% 的概率生成 4
        matrix[cell.row][cell.col] = value; // 更新矩阵
        updateGrid(); // 更新网格显示
    }
}

// 更新 HTML 网格中的方块显示
function updateGrid() {
    cells.forEach((cell, index) => {
        const row = Math.floor(index / 4); // 计算当前单元格所在的行
        const col = index % 4; // 计算当前单元格所在的列
        const value = matrix[row][col]; // 获取矩阵中的值
        cell.textContent = value || ''; // 显示值,如果没有值则显示空字符串
        cell.classList.remove('number-2', 'number-4', 'number-8', 'number-16', 'number-32', 'number-64', 'number-128', 'number-256', 'number-512', 'number-1024', 'number-2048'); // 移除所有样式类
        if (value !== 0) { // 如果有值,添加对应的样式类
            cell.classList.add(`number-${value}`);
        }
    });
}

// 向上移动
function moveUp() {
    for (let col = 0; col < 4; col++) { // 遍历每一列
        let tempCol = []; // 临时存储非零值
        for (let row = 0; row < 4; row++) {
            if (matrix[row][col] !== 0) {
                tempCol.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempCol = mergeTiles(tempCol); // 合并相同的值
        for (let row = 0; row < 4; row++) {
            matrix[row][col] = tempCol[row] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

// 向下移动
function moveDown() {
    for (let col = 0; col < 4; col++) { // 遍历每一列
        let tempCol = []; // 临时存储非零值
        for (let row = 3; row >= 0; row--) {
            if (matrix[row][col] !== 0) {
                tempCol.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempCol = mergeTiles(tempCol); // 合并相同的值
        for (let row = 3; row >= 0; row--) {
            matrix[row][col] = tempCol[3 - row] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

// 向左移动
function moveLeft() {
    for (let row = 0; row < 4; row++) { // 遍历每一行
        let tempRow = []; // 临时存储非零值
        for (let col = 0; col < 4; col++) {
            if (matrix[row][col] !== 0) {
                tempRow.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempRow = mergeTiles(tempRow); // 合并相同的值
        for (let col = 0; col < 4; col++) {
            matrix[row][col] = tempRow[col] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

// 向右移动
function moveRight() {
    for (let row = 0; row < 4; row++) { // 遍历每一行
        let tempRow = []; // 临时存储非零值
        for (let col = 3; col >= 0; col--) {
            if (matrix[row][col] !== 0) {
                tempRow.push(matrix[row][col]); // 将非零值加入临时列表
            }
        }
        tempRow = mergeTiles(tempRow); // 合并相同的值
        for (let col = 3; col >= 0; col--) {
            matrix[row][col] = tempRow[3 - col] || 0; // 更新矩阵
        }
    }
    addRandomTile(); // 添加新的方块
    checkGameOver(); // 检查游戏是否结束
}

// 合并相同的值
function mergeTiles(tiles) {
    for (let i = 0; i < tiles.length - 1; i++) {
        if (tiles[i] === tiles[i + 1]) { // 如果相邻的两个值相同
            tiles[i] *= 2; // 合并值
            tiles.splice(i + 1, 1); // 删除合并后的值
            score += tiles[i]; // 更新分数
            scoreContainer.textContent = score; // 更新分数显示
            if (tiles[i] === winNumber && !hasWon) { // 如果达到目标值且未赢过
                alert('You Win!'); // 提示胜利
                hasWon = true; // 标记已赢
            }
        }
    }
    while (tiles.length < 4) { // 确保列表长度为 4
        tiles.push(0);
    }
    return tiles;
}

// 检查游戏是否结束
function checkGameOver() {
    let gameOver = true; // 默认游戏结束
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (matrix[i][j] === 0 || // 如果有空格子
                (i < 3 && matrix[i][j] === matrix[i + 1][j]) || // 或者有相邻的相同值
                (j < 3 && matrix[i][j] === matrix[i][j + 1])) {
                gameOver = false; // 游戏未结束
                break;
            }
        }
        if (!gameOver) break;
    }
    if (gameOver) {
        alert('Game Over!'); // 提示游戏结束
    }
}

// 重新开始游戏
function restartGame() {
    matrix.forEach(row => row.fill(0)); // 重置矩阵
    score = 0; // 重置分数
    hasWon = false; // 重置胜利标记
    scoreContainer.textContent = score; // 更新分数显示
    addRandomTile(); // 添加初始方块
    addRandomTile(); // 添加初始方块
    updateGrid(); // 更新网格显示
}

// 监听键盘事件
document.addEventListener('keydown', (event) => {
    switch (event.key) {
        case 'ArrowUp': // 上箭头
            moveUp();
            break;
        case 'ArrowDown': // 下箭头
            moveDown();
            break;
        case 'ArrowLeft': // 左箭头
            moveLeft();
            break;
        case 'ArrowRight': // 右箭头
            moveRight();
            break;
    }
});

// 监听重新开始按钮点击事件
restartButton.addEventListener('click', restartGame);

// 初始化游戏
restartGame();

 别忘了请点个赞+收藏+关注支持一下博主喵!!!

累了,水一下吧。。。。。。∗︎˚(* ˃̤൬˂̤ *)˚∗︎

gitee:2048-game: html+css+js设计的一个2048游戏(网页)


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

相关文章:

  • Vue计算属性computed
  • Iotop使用
  • 统信UOS开发接口DTK
  • 【C++学习(37)】并发性模式:如生产者-消费者、读写锁等。 架构模式:如MVC、MVVM等。属于23 种设计模式吗? RAII 的关系?
  • 【缺陷检测】Anomaly Detection via Reverse Distillation from One-Class Embedding
  • win11 新建一个批处理,双击查看本机的IP地址
  • 100种算法【Python版】第40篇——卡恩算法
  • 基于springboot信用分析管理系统设计与实现
  • Linux下的 MySQL 中添加用户并设置远程访问
  • 十六:Spring Boot (1)-- spring-boot-starter 应用
  • EHOME视频平台EasyCVR视频融合平台支持哪些摄像机接入?监控摄像头镜头的种类有哪些?
  • 启明云端触觉智能与您相约2024年慕尼黑国际电子元器件博览会,不见不散!
  • 半年总结-还有很多要学习
  • clickhouse自增id的处理
  • JS 循环语句
  • 如何学习C++游戏开发
  • 基于微信小程序的实习管理系统(附源码,文档)
  • 2024-11-5 学习人工智能的Day22 openCV(4)
  • 费舍尔信息矩阵 低秩矩阵 渐近正态性
  • 关键词研究与布局的重要性与实施策略
  • Python Matplotlib 如何绘制股票或金融数据图
  • 使用 PyTorch 实现并测试 AlexNet 模型,并使用 TensorRT 进行推理加速
  • springboot 之 接口数据脱敏
  • 淘淘商城实战高并发分布式项目(有源码)
  • 【死锁处理案例之一】
  • 硬件基础知识补全计划【七】MOS 晶体管