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>
游戏功能说明
-
核心玩法:
- 使用方向键(或触摸滑动)移动方块
- 相同数字的方块碰撞后会合并
- 每次移动后随机生成一个 2 或 4 的新方块
-
特色实现:
- 响应式设计,支持键盘和触摸操作
- 动态分数计算
- 游戏结束检测
- 不同数字的方块有不同的颜色样式
-
技术要点:
- 纯 DOM 操作实现,无第三方依赖
- 二维数组管理游戏状态
- 移动逻辑处理(包括合并和移动动画)
使用方法
- 将代码保存为
2048.html
文件 - 用浏览器打开即可开始游戏
- 键盘方向键控制移动,或触摸屏滑动操作
您可以根据需要修改样式或添加新功能,如最高分记录、动画效果等。