<!DOCTYPE html> <html lang="zh"> <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: 10px; touch-action: manipulation; } h1 { font-size: 24px; margin: 5px 0; color: #776e65; } .game-container { width: 280px; margin: 0 auto; position: relative; } .grid { background-color: #bbada0; border-radius: 5px; padding: 10px; position: relative; } .grid-row { display: flex; margin-bottom: 10px; } .grid-row:last-child { margin-bottom: 0; } .grid-cell { width: 60px; height: 60px; margin-right: 10px; background-color: rgba(238, 228, 218, 0.35); border-radius: 3px; position: relative; /* 添加相对定位 */ } .grid-cell:last-child { margin-right: 0; } .tile { position: absolute; width: 60px; height: 60px; border-radius: 3px; display: flex; justify-content: center; align-items: center; font-weight: bold; font-size: 24px; transition: all 0.1s ease-in-out; z-index: 10; top: 0; /* 确保从顶部开始 */ left: 0; /* 确保从左侧开始 */ } .score-container { display: flex; justify-content: space-between; margin: 10px 0; } .score-box { background-color: #bbada0; color: white; padding: 5px 10px; border-radius: 5px; font-weight: bold; min-width: 60px; font-size: 14px; } .score-title { font-size: 12px; color: #eee4da; } .score-value { font-size: 18px; } .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; justify-content: center; align-items: center; z-index: 100; border-radius: 5px; display: none; } .game-over-text { font-size: 30px; font-weight: bold; color: #776e65; margin-bottom: 10px; } .restart-button { background-color: #8f7a66; color: white; border: none; border-radius: 3px; padding: 8px 15px; font-size: 14px; cursor: pointer; } .decay-effect { animation: decayPulse 0.5s; } @keyframes decayPulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .instructions { margin-top: 10px; color: #776e65; font-size: 12px; line-height: 1.3; } </style> </head> <body> <div class="game-container"> <h1>元素衰变2048</h1> <div class="score-container"> <div class="score-box"> <div class="score-title">分数</div> <div class="score-value" id="score">0</div> </div> <div class="score-box"> <div class="score-title">最高元素</div> <div class="score-value" id="best-element">H</div> </div> </div> <div class="grid"> <div class="grid-row"> <div class="grid-cell" id="cell-0-0"></div> <div class="grid-cell" id="cell-0-1"></div> <div class="grid-cell" id="cell-0-2"></div> <div class="grid-cell" id="cell-0-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-1-0"></div> <div class="grid-cell" id="cell-1-1"></div> <div class="grid-cell" id="cell-1-2"></div> <div class="grid-cell" id="cell-1-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-2-0"></div> <div class="grid-cell" id="cell-2-1"></div> <div class="grid-cell" id="cell-2-2"></div> <div class="grid-cell" id="cell-2-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-3-0"></div> <div class="grid-cell" id="cell-3-1"></div> <div class="grid-cell" id="cell-3-2"></div> <div class="grid-cell" id="cell-3-3"></div> </div> <div class="game-over"> <div class="game-over-text">游戏结束!</div> <button class="restart-button" onclick="startGame()">再来一局</button> </div> </div> <div class="instructions"> <p>方向键/WASD移动,相同元素合并,每次移动可能衰变</p> </div> </div> <script> // 游戏配置 const config = { size: 4, decayChance: 0.0065, chainDecayChance: 0.3 }; // 元素数据 (只显示符号) const elements = [ { value: 2, symbol: "H", color: "#EEE4DA", textColor: "#776e65" }, { value: 4, symbol: "He", color: "#EDE0C8", textColor: "#776e65" }, { value: 8, symbol: "Li", color: "#F2B179", textColor: "#f9f6f2" }, { value: 16, symbol: "Be", color: "#F59563", textColor: "#f9f6f2" }, { value: 32, symbol: "B", color: "#F67C5F", textColor: "#f9f6f2" }, { value: 64, symbol: "C", color: "#F65E3B", textColor: "#f9f6f2" }, { value: 128, symbol: "N", color: "#EDCF72", textColor: "#f9f6f2" }, { value: 256, symbol: "O", color: "#EDCC61", textColor: "#f9f6f2" }, { value: 512, symbol: "F", color: "#EDC850", textColor: "#f9f6f2" }, { value: 1024, symbol: "Ne", color: "#EDC53F", textColor: "#f9f6f2" }, { value: 2048, symbol: "Na", color: "#EDC22E", textColor: "#f9f6f2" } ]; // 获取元素属性 function getElement(value) { if (value <= 2048) { return elements.find(e => e.value === value); } // 高阶元素使用循环颜色 const colors = ["#3C3A32", "#B39379", "#7F7F7F", "#8B4513"]; const index = Math.floor(Math.log2(value) - 11) % colors.length; return { value: value, symbol: "E" + Math.floor(Math.log2(value)), color: colors[index], textColor: "#f9f6f2" }; } // 游戏状态 let grid = []; let score = 0; let bestElement = { value: 2, symbol: "H" }; let gameOver = false; let moving = false; // 初始化游戏 function startGame() { grid = Array(config.size).fill().map(() => Array(config.size).fill(0)); score = 0; bestElement = { value: 2, symbol: "H" }; gameOver = false; document.getElementById("score").textContent = "0"; document.getElementById("best-element").textContent = "H"; document.querySelector(".game-over").style.display = "none"; addRandomTile(); addRandomTile(); updateView(); } // 添加随机元素 function addRandomTile() { const emptyCells = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) { emptyCells.push({ r, c }); } } } if (emptyCells.length > 0) { const { r, c } = emptyCells[Math.floor(Math.random() * emptyCells.length)]; grid[r][c] = Math.random() < 0.9 ? 2 : 4; return true; } return false; } // 更新视图 function updateView() { // 清除所有现有瓦片 document.querySelectorAll(".tile").forEach(tile => tile.remove()); // 添加新瓦片 - 现在直接放入对应的grid-cell中 for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (value !== 0) { const element = getElement(value); const cell = document.getElementById(`cell-${r}-${c}`); const tile = document.createElement("div"); tile.className = "tile"; tile.style.backgroundColor = element.color; tile.style.color = element.textColor; tile.textContent = element.symbol; cell.appendChild(tile); } } } document.getElementById("score").textContent = score; document.getElementById("best-element").textContent = bestElement.symbol; } // 移动处理 function move(direction) { if (gameOver || moving) return; moving = true; let moved = false; switch (direction) { case "up": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, -1) || moved; } break; case "down": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, 1) || moved; } break; case "left": for (let r = 0; r < config.size; r++) { moved = moveRow(r, -1) || moved; } break; case "right": for (let r = 0; r < config.size; r++) { moved = moveRow(r, 1) || moved; } break; } if (moved) { addRandomTile(); updateView(); setTimeout(() => { tryDecay(); updateView(); checkGameOver(); moving = false; }, 150); } else { moving = false; checkGameOver(); } } // 移动行 function moveRow(r, dir) { let moved = false; const row = grid[r].filter(val => val !== 0); if (dir === 1) row.reverse(); for (let i = 0; i < row.length - 1; i++) { if (row[i] === row[i + 1]) { row[i] *= 2; row[i + 1] = 0; score += row[i]; if (row[i] > bestElement.value) { bestElement = getElement(row[i]); } moved = true; } } const newRow = row.filter(val => val !== 0); while (newRow.length < config.size) newRow.push(0); if (dir === 1) newRow.reverse(); if (JSON.stringify(grid[r]) !== JSON.stringify(newRow)) { moved = true; } grid[r] = newRow; return moved; } // 移动列 function moveColumn(c, dir) { let moved = false; let column = []; for (let r = 0; r < config.size; r++) { if (grid[r][c] !== 0) column.push(grid[r][c]); } if (dir === 1) column.reverse(); for (let i = 0; i < column.length - 1; i++) { if (column[i] === column[i + 1]) { column[i] *= 2; column[i + 1] = 0; score += column[i]; if (column[i] > bestElement.value) { bestElement = getElement(column[i]); } moved = true; } } const newColumn = column.filter(val => val !== 0); while (newColumn.length < config.size) newColumn.push(0); if (dir === 1) newColumn.reverse(); for (let r = 0; r < config.size; r++) { if (grid[r][c] !== newColumn[r]) { moved = true; grid[r][c] = newColumn[r]; } } return moved; } // 尝试衰变 function tryDecay() { const decayCandidates = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] > 2) { decayCandidates.push({ r, c, value: grid[r][c] }); } } } if (decayCandidates.length === 0) return; const decayProbabilities = decayCandidates.map(candidate => { return config.decayChance + (Math.log2(candidate.value) - 1) * 0.000025; }); for (let i = 0; i < decayCandidates.length; i++) { const { r, c, value } = decayCandidates[i]; if (Math.random() < decayProbabilities[i]) { decayElement(r, c); // 连锁衰变 const directions = [ { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 } ]; for (const { dr, dc } of directions) { const nr = r + dr; const nc = c + dc; if (nr >= 0 && nr < config.size && nc >= 0 && nc < config.size && grid[nr][nc] === value && Math.random() < config.chainDecayChance) { decayElement(nr, nc); } } } } } // 衰变元素 function decayElement(r, c) { const cell = document.getElementById(`cell-${r}-${c}`); const tile = cell.querySelector(".tile"); if (tile) { tile.classList.add("decay-effect"); setTimeout(() => tile.classList.remove("decay-effect"), 500); } grid[r][c] /= 2; } // 检查游戏结束 function checkGameOver() { for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) return false; } } for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (c < config.size - 1 && grid[r][c + 1] === value) return false; if (r < config.size - 1 && grid[r + 1][c] === value) return false; } } gameOver = true; document.querySelector(".game-over").style.display = "flex"; return true; } // 键盘控制 document.addEventListener("keydown", function(event) { if (gameOver) return; switch (event.key) { case "ArrowUp": case "w": case "W": move("up"); event.preventDefault(); break; case "ArrowDown": case "s": case "S": move("down"); event.preventDefault(); break; case "ArrowLeft": case "a": case "A": move("left"); event.preventDefault(); break; case "ArrowRight": case "d": case "D": move("right"); event.preventDefault(); break; } }); // 触摸控制 let touchStartX = 0; let touchStartY = 0; document.querySelector(".grid").addEventListener("touchstart", function(e) { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; e.preventDefault(); }, { passive: false }); document.querySelector(".grid").addEventListener("touchend", function(e) { if (gameOver) return; const touchEndX = e.changedTouches[0].clientX; const touchEndY = e.changedTouches[0].clientY; const dx = touchEndX - touchStartX; const dy = touchEndY - touchStartY; if (Math.abs(dx) > Math.abs(dy)) { if (dx > 0) move("right"); else move("left"); } else { if (dy > 0) move("down"); else move("up"); } e.preventDefault(); }, { passive: false }); // 开始游戏 startGame(); </script> </body> </html> 、、
<!DOCTYPE html> <html lang="zh"> <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: 10px; touch-action: manipulation; } h1 { font-size: 24px; margin: 5px 0; color: #776e65; } .game-container { width: 280px; margin: 0 auto; position: relative; } .grid { background-color: #bbada0; border-radius: 5px; padding: 10px; position: relative; } .grid-row { display: flex; margin-bottom: 10px; } .grid-row:last-child { margin-bottom: 0; } .grid-cell { width: 60px; height: 60px; margin-right: 10px; background-color: rgba(238, 228, 218, 0.35); border-radius: 3px; position: relative; /* 添加相对定位 */ } .grid-cell:last-child { margin-right: 0; } .tile { position: absolute; width: 60px; height: 60px; border-radius: 3px; display: flex; justify-content: center; align-items: center; font-weight: bold; font-size: 24px; transition: all 0.1s ease-in-out; z-index: 10; top: 0; /* 确保从顶部开始 */ left: 0; /* 确保从左侧开始 */ } .score-container { display: flex; justify-content: space-between; margin: 10px 0; } .score-box { background-color: #bbada0; color: white; padding: 5px 10px; border-radius: 5px; font-weight: bold; min-width: 60px; font-size: 14px; } .score-title { font-size: 12px; color: #eee4da; } .score-value { font-size: 18px; } .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; justify-content: center; align-items: center; z-index: 100; border-radius: 5px; display: none; } .game-over-text { font-size: 30px; font-weight: bold; color: #776e65; margin-bottom: 10px; } .restart-button { background-color: #8f7a66; color: white; border: none; border-radius: 3px; padding: 8px 15px; font-size: 14px; cursor: pointer; } .decay-effect { animation: decayPulse 0.5s; } @keyframes decayPulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .instructions { margin-top: 10px; color: #776e65; font-size: 12px; line-height: 1.3; } </style> </head> <body> <div class="game-container"> <h1>元素衰变2048</h1> <div class="score-container"> <div class="score-box"> <div class="score-title">分数</div> <div class="score-value" id="score">0</div> </div> <div class="score-box"> <div class="score-title">最高元素</div> <div class="score-value" id="best-element">H</div> </div> </div> <div class="grid"> <div class="grid-row"> <div class="grid-cell" id="cell-0-0"></div> <div class="grid-cell" id="cell-0-1"></div> <div class="grid-cell" id="cell-0-2"></div> <div class="grid-cell" id="cell-0-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-1-0"></div> <div class="grid-cell" id="cell-1-1"></div> <div class="grid-cell" id="cell-1-2"></div> <div class="grid-cell" id="cell-1-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-2-0"></div> <div class="grid-cell" id="cell-2-1"></div> <div class="grid-cell" id="cell-2-2"></div> <div class="grid-cell" id="cell-2-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-3-0"></div> <div class="grid-cell" id="cell-3-1"></div> <div class="grid-cell" id="cell-3-2"></div> <div class="grid-cell" id="cell-3-3"></div> </div> <div class="game-over"> <div class="game-over-text">游戏结束!</div> <button class="restart-button" onclick="startGame()">再来一局</button> </div> </div> <div class="instructions"> <p>方向键/WASD移动,相同元素合并,每次移动可能衰变</p> </div> </div> <script> // 游戏配置 const config = { size: 4, decayChance: 0.0065, chainDecayChance: 0.3 }; // 元素数据 (只显示符号) const elements = [ { value: 2, symbol: "H", color: "#EEE4DA", textColor: "#776e65" }, { value: 4, symbol: "He", color: "#EDE0C8", textColor: "#776e65" }, { value: 8, symbol: "Li", color: "#F2B179", textColor: "#f9f6f2" }, { value: 16, symbol: "Be", color: "#F59563", textColor: "#f9f6f2" }, { value: 32, symbol: "B", color: "#F67C5F", textColor: "#f9f6f2" }, { value: 64, symbol: "C", color: "#F65E3B", textColor: "#f9f6f2" }, { value: 128, symbol: "N", color: "#EDCF72", textColor: "#f9f6f2" }, { value: 256, symbol: "O", color: "#EDCC61", textColor: "#f9f6f2" }, { value: 512, symbol: "F", color: "#EDC850", textColor: "#f9f6f2" }, { value: 1024, symbol: "Ne", color: "#EDC53F", textColor: "#f9f6f2" }, { value: 2048, symbol: "Na", color: "#EDC22E", textColor: "#f9f6f2" } ]; // 获取元素属性 function getElement(value) { if (value <= 2048) { return elements.find(e => e.value === value); } // 高阶元素使用循环颜色 const colors = ["#3C3A32", "#B39379", "#7F7F7F", "#8B4513"]; const index = Math.floor(Math.log2(value) - 11) % colors.length; return { value: value, symbol: "E" + Math.floor(Math.log2(value)), color: colors[index], textColor: "#f9f6f2" }; } // 游戏状态 let grid = []; let score = 0; let bestElement = { value: 2, symbol: "H" }; let gameOver = false; let moving = false; // 初始化游戏 function startGame() { grid = Array(config.size).fill().map(() => Array(config.size).fill(0)); score = 0; bestElement = { value: 2, symbol: "H" }; gameOver = false; document.getElementById("score").textContent = "0"; document.getElementById("best-element").textContent = "H"; document.querySelector(".game-over").style.display = "none"; addRandomTile(); addRandomTile(); updateView(); } // 添加随机元素 function addRandomTile() { const emptyCells = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) { emptyCells.push({ r, c }); } } } if (emptyCells.length > 0) { const { r, c } = emptyCells[Math.floor(Math.random() * emptyCells.length)]; grid[r][c] = Math.random() < 0.9 ? 2 : 4; return true; } return false; } // 更新视图 function updateView() { // 清除所有现有瓦片 document.querySelectorAll(".tile").forEach(tile => tile.remove()); // 添加新瓦片 - 现在直接放入对应的grid-cell中 for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (value !== 0) { const element = getElement(value); const cell = document.getElementById(`cell-${r}-${c}`); const tile = document.createElement("div"); tile.className = "tile"; tile.style.backgroundColor = element.color; tile.style.color = element.textColor; tile.textContent = element.symbol; cell.appendChild(tile); } } } document.getElementById("score").textContent = score; document.getElementById("best-element").textContent = bestElement.symbol; } // 移动处理 function move(direction) { if (gameOver || moving) return; moving = true; let moved = false; switch (direction) { case "up": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, -1) || moved; } break; case "down": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, 1) || moved; } break; case "left": for (let r = 0; r < config.size; r++) { moved = moveRow(r, -1) || moved; } break; case "right": for (let r = 0; r < config.size; r++) { moved = moveRow(r, 1) || moved; } break; } if (moved) { addRandomTile(); updateView(); setTimeout(() => { tryDecay(); updateView(); checkGameOver(); moving = false; }, 150); } else { moving = false; checkGameOver(); } } // 移动行 function moveRow(r, dir) { let moved = false; const row = grid[r].filter(val => val !== 0); if (dir === 1) row.reverse(); for (let i = 0; i < row.length - 1; i++) { if (row[i] === row[i + 1]) { row[i] *= 2; row[i + 1] = 0; score += row[i]; if (row[i] > bestElement.value) { bestElement = getElement(row[i]); } moved = true; } } const newRow = row.filter(val => val !== 0); while (newRow.length < config.size) newRow.push(0); if (dir === 1) newRow.reverse(); if (JSON.stringify(grid[r]) !== JSON.stringify(newRow)) { moved = true; } grid[r] = newRow; return moved; } // 移动列 function moveColumn(c, dir) { let moved = false; let column = []; for (let r = 0; r < config.size; r++) { if (grid[r][c] !== 0) column.push(grid[r][c]); } if (dir === 1) column.reverse(); for (let i = 0; i < column.length - 1; i++) { if (column[i] === column[i + 1]) { column[i] *= 2; column[i + 1] = 0; score += column[i]; if (column[i] > bestElement.value) { bestElement = getElement(column[i]); } moved = true; } } const newColumn = column.filter(val => val !== 0); while (newColumn.length < config.size) newColumn.push(0); if (dir === 1) newColumn.reverse(); for (let r = 0; r < config.size; r++) { if (grid[r][c] !== newColumn[r]) { moved = true; grid[r][c] = newColumn[r]; } } return moved; } // 尝试衰变 function tryDecay() { const decayCandidates = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] > 2) { decayCandidates.push({ r, c, value: grid[r][c] }); } } } if (decayCandidates.length === 0) return; const decayProbabilities = decayCandidates.map(candidate => { return config.decayChance + (Math.log2(candidate.value) - 1) * 0.000025; }); for (let i = 0; i < decayCandidates.length; i++) { const { r, c, value } = decayCandidates[i]; if (Math.random() < decayProbabilities[i]) { decayElement(r, c); // 连锁衰变 const directions = [ { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 } ]; for (const { dr, dc } of directions) { const nr = r + dr; const nc = c + dc; if (nr >= 0 && nr < config.size && nc >= 0 && nc < config.size && grid[nr][nc] === value && Math.random() < config.chainDecayChance) { decayElement(nr, nc); } } } } } // 衰变元素 function decayElement(r, c) { const cell = document.getElementById(`cell-${r}-${c}`); const tile = cell.querySelector(".tile"); if (tile) { tile.classList.add("decay-effect"); setTimeout(() => tile.classList.remove("decay-effect"), 500); } grid[r][c] /= 2; } // 检查游戏结束 function checkGameOver() { for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) return false; } } for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (c < config.size - 1 && grid[r][c + 1] === value) return false; if (r < config.size - 1 && grid[r + 1][c] === value) return false; } } gameOver = true; document.querySelector(".game-over").style.display = "flex"; return true; } // 键盘控制 document.addEventListener("keydown", function(event) { if (gameOver) return; switch (event.key) { case "ArrowUp": case "w": case "W": move("up"); event.preventDefault(); break; case "ArrowDown": case "s": case "S": move("down"); event.preventDefault(); break; case "ArrowLeft": case "a": case "A": move("left"); event.preventDefault(); break; case "ArrowRight": case "d": case "D": move("right"); event.preventDefault(); break; } }); // 触摸控制 let touchStartX = 0; let touchStartY = 0; document.querySelector(".grid").addEventListener("touchstart", function(e) { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; e.preventDefault(); }, { passive: false }); document.querySelector(".grid").addEventListener("touchend", function(e) { if (gameOver) return; const touchEndX = e.changedTouches[0].clientX; const touchEndY = e.changedTouches[0].clientY; const dx = touchEndX - touchStartX; const dy = touchEndY - touchStartY; if (Math.abs(dx) > Math.abs(dy)) { if (dx > 0) move("right"); else move("left"); } else { if (dy > 0) move("down"); else move("up"); } e.preventDefault(); }, { passive: false }); // 开始游戏 startGame(); </script> </body> </html>
元素衰变2048小游戏代码 <!DOCTYPE html> <html lang="zh"> <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: 10px; touch-action: manipulation; } h1 { font-size: 24px; margin: 5px 0; color: #776e65; } .game-container { width: 280px; margin: 0 auto; position: relative; } .grid { background-color: #bbada0; border-radius: 5px; padding: 10px; position: relative; } .grid-row { display: flex; margin-bottom: 10px; } .grid-row:last-child { margin-bottom: 0; } .grid-cell { width: 60px; height: 60px; margin-right: 10px; background-color: rgba(238, 228, 218, 0.35); border-radius: 3px; position: relative; /* 添加相对定位 */ } .grid-cell:last-child { margin-right: 0; } .tile { position: absolute; width: 60px; height: 60px; border-radius: 3px; display: flex; justify-content: center; align-items: center; font-weight: bold; font-size: 24px; transition: all 0.1s ease-in-out; z-index: 10; top: 0; /* 确保从顶部开始 */ left: 0; /* 确保从左侧开始 */ } .score-container { display: flex; justify-content: space-between; margin: 10px 0; } .score-box { background-color: #bbada0; color: white; padding: 5px 10px; border-radius: 5px; font-weight: bold; min-width: 60px; font-size: 14px; } .score-title { font-size: 12px; color: #eee4da; } .score-value { font-size: 18px; } .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; justify-content: center; align-items: center; z-index: 100; border-radius: 5px; display: none; } .game-over-text { font-size: 30px; font-weight: bold; color: #776e65; margin-bottom: 10px; } .restart-button { background-color: #8f7a66; color: white; border: none; border-radius: 3px; padding: 8px 15px; font-size: 14px; cursor: pointer; } .decay-effect { animation: decayPulse 0.5s; } @keyframes decayPulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } .instructions { margin-top: 10px; color: #776e65; font-size: 12px; line-height: 1.3; } </style> </head> <body> <div class="game-container"> <h1>元素衰变2048</h1> <div class="score-container"> <div class="score-box"> <div class="score-title">分数</div> <div class="score-value" id="score">0</div> </div> <div class="score-box"> <div class="score-title">最高元素</div> <div class="score-value" id="best-element">H</div> </div> </div> <div class="grid"> <div class="grid-row"> <div class="grid-cell" id="cell-0-0"></div> <div class="grid-cell" id="cell-0-1"></div> <div class="grid-cell" id="cell-0-2"></div> <div class="grid-cell" id="cell-0-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-1-0"></div> <div class="grid-cell" id="cell-1-1"></div> <div class="grid-cell" id="cell-1-2"></div> <div class="grid-cell" id="cell-1-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-2-0"></div> <div class="grid-cell" id="cell-2-1"></div> <div class="grid-cell" id="cell-2-2"></div> <div class="grid-cell" id="cell-2-3"></div> </div> <div class="grid-row"> <div class="grid-cell" id="cell-3-0"></div> <div class="grid-cell" id="cell-3-1"></div> <div class="grid-cell" id="cell-3-2"></div> <div class="grid-cell" id="cell-3-3"></div> </div> <div class="game-over"> <div class="game-over-text">游戏结束!</div> <button class="restart-button" onclick="startGame()">再来一局</button> </div> </div> <div class="instructions"> <p>方向键/WASD移动,相同元素合并,每次移动可能衰变</p> </div> </div> <script> // 游戏配置 const config = { size: 4, decayChance: 0.0065, chainDecayChance: 0.3 }; // 元素数据 (只显示符号) const elements = [ { value: 2, symbol: "H", color: "#EEE4DA", textColor: "#776e65" }, { value: 4, symbol: "He", color: "#EDE0C8", textColor: "#776e65" }, { value: 8, symbol: "Li", color: "#F2B179", textColor: "#f9f6f2" }, { value: 16, symbol: "Be", color: "#F59563", textColor: "#f9f6f2" }, { value: 32, symbol: "B", color: "#F67C5F", textColor: "#f9f6f2" }, { value: 64, symbol: "C", color: "#F65E3B", textColor: "#f9f6f2" }, { value: 128, symbol: "N", color: "#EDCF72", textColor: "#f9f6f2" }, { value: 256, symbol: "O", color: "#EDCC61", textColor: "#f9f6f2" }, { value: 512, symbol: "F", color: "#EDC850", textColor: "#f9f6f2" }, { value: 1024, symbol: "Ne", color: "#EDC53F", textColor: "#f9f6f2" }, { value: 2048, symbol: "Na", color: "#EDC22E", textColor: "#f9f6f2" } ]; // 获取元素属性 function getElement(value) { if (value <= 2048) { return elements.find(e => e.value === value); } // 高阶元素使用循环颜色 const colors = ["#3C3A32", "#B39379", "#7F7F7F", "#8B4513"]; const index = Math.floor(Math.log2(value) - 11) % colors.length; return { value: value, symbol: "E" + Math.floor(Math.log2(value)), color: colors[index], textColor: "#f9f6f2" }; } // 游戏状态 let grid = []; let score = 0; let bestElement = { value: 2, symbol: "H" }; let gameOver = false; let moving = false; // 初始化游戏 function startGame() { grid = Array(config.size).fill().map(() => Array(config.size).fill(0)); score = 0; bestElement = { value: 2, symbol: "H" }; gameOver = false; document.getElementById("score").textContent = "0"; document.getElementById("best-element").textContent = "H"; document.querySelector(".game-over").style.display = "none"; addRandomTile(); addRandomTile(); updateView(); } // 添加随机元素 function addRandomTile() { const emptyCells = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) { emptyCells.push({ r, c }); } } } if (emptyCells.length > 0) { const { r, c } = emptyCells[Math.floor(Math.random() * emptyCells.length)]; grid[r][c] = Math.random() < 0.9 ? 2 : 4; return true; } return false; } // 更新视图 function updateView() { // 清除所有现有瓦片 document.querySelectorAll(".tile").forEach(tile => tile.remove()); // 添加新瓦片 - 现在直接放入对应的grid-cell中 for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (value !== 0) { const element = getElement(value); const cell = document.getElementById(`cell-${r}-${c}`); const tile = document.createElement("div"); tile.className = "tile"; tile.style.backgroundColor = element.color; tile.style.color = element.textColor; tile.textContent = element.symbol; cell.appendChild(tile); } } } document.getElementById("score").textContent = score; document.getElementById("best-element").textContent = bestElement.symbol; } // 移动处理 function move(direction) { if (gameOver || moving) return; moving = true; let moved = false; switch (direction) { case "up": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, -1) || moved; } break; case "down": for (let c = 0; c < config.size; c++) { moved = moveColumn(c, 1) || moved; } break; case "left": for (let r = 0; r < config.size; r++) { moved = moveRow(r, -1) || moved; } break; case "right": for (let r = 0; r < config.size; r++) { moved = moveRow(r, 1) || moved; } break; } if (moved) { addRandomTile(); updateView(); setTimeout(() => { tryDecay(); updateView(); checkGameOver(); moving = false; }, 150); } else { moving = false; checkGameOver(); } } // 移动行 function moveRow(r, dir) { let moved = false; const row = grid[r].filter(val => val !== 0); if (dir === 1) row.reverse(); for (let i = 0; i < row.length - 1; i++) { if (row[i] === row[i + 1]) { row[i] *= 2; row[i + 1] = 0; score += row[i]; if (row[i] > bestElement.value) { bestElement = getElement(row[i]); } moved = true; } } const newRow = row.filter(val => val !== 0); while (newRow.length < config.size) newRow.push(0); if (dir === 1) newRow.reverse(); if (JSON.stringify(grid[r]) !== JSON.stringify(newRow)) { moved = true; } grid[r] = newRow; return moved; } // 移动列 function moveColumn(c, dir) { let moved = false; let column = []; for (let r = 0; r < config.size; r++) { if (grid[r][c] !== 0) column.push(grid[r][c]); } if (dir === 1) column.reverse(); for (let i = 0; i < column.length - 1; i++) { if (column[i] === column[i + 1]) { column[i] *= 2; column[i + 1] = 0; score += column[i]; if (column[i] > bestElement.value) { bestElement = getElement(column[i]); } moved = true; } } const newColumn = column.filter(val => val !== 0); while (newColumn.length < config.size) newColumn.push(0); if (dir === 1) newColumn.reverse(); for (let r = 0; r < config.size; r++) { if (grid[r][c] !== newColumn[r]) { moved = true; grid[r][c] = newColumn[r]; } } return moved; } // 尝试衰变 function tryDecay() { const decayCandidates = []; for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] > 2) { decayCandidates.push({ r, c, value: grid[r][c] }); } } } if (decayCandidates.length === 0) return; const decayProbabilities = decayCandidates.map(candidate => { return config.decayChance + (Math.log2(candidate.value) - 1) * 0.000025; }); for (let i = 0; i < decayCandidates.length; i++) { const { r, c, value } = decayCandidates[i]; if (Math.random() < decayProbabilities[i]) { decayElement(r, c); // 连锁衰变 const directions = [ { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 }, { dr: 0, dc: 0 } ]; for (const { dr, dc } of directions) { const nr = r + dr; const nc = c + dc; if (nr >= 0 && nr < config.size && nc >= 0 && nc < config.size && grid[nr][nc] === value && Math.random() < config.chainDecayChance) { decayElement(nr, nc); } } } } } // 衰变元素 function decayElement(r, c) { const cell = document.getElementById(`cell-${r}-${c}`); const tile = cell.querySelector(".tile"); if (tile) { tile.classList.add("decay-effect"); setTimeout(() => tile.classList.remove("decay-effect"), 500); } grid[r][c] /= 2; } // 检查游戏结束 function checkGameOver() { for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { if (grid[r][c] === 0) return false; } } for (let r = 0; r < config.size; r++) { for (let c = 0; c < config.size; c++) { const value = grid[r][c]; if (c < config.size - 1 && grid[r][c + 1] === value) return false; if (r < config.size - 1 && grid[r + 1][c] === value) return false; } } gameOver = true; document.querySelector(".game-over").style.display = "flex"; return true; } // 键盘控制 document.addEventListener("keydown", function(event) { if (gameOver) return; switch (event.key) { case "ArrowUp": case "w": case "W": move("up"); event.preventDefault(); break; case "ArrowDown": case "s": case "S": move("down"); event.preventDefault(); break; case "ArrowLeft": case "a": case "A": move("left"); event.preventDefault(); break; case "ArrowRight": case "d": case "D": move("right"); event.preventDefault(); break; } }); // 触摸控制 let touchStartX = 0; let touchStartY = 0; document.querySelector(".grid").addEventListener("touchstart", function(e) { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; e.preventDefault(); }, { passive: false }); document.querySelector(".grid").addEventListener("touchend", function(e) { if (gameOver) return; const touchEndX = e.changedTouches[0].clientX; const touchEndY = e.changedTouches[0].clientY; const dx = touchEndX - touchStartX; const dy = touchEndY - touchStartY; if (Math.abs(dx) > Math.abs(dy)) { if (dx > 0) move("right"); else move("left"); } else { if (dy > 0) move("down"); else move("up"); } e.preventDefault(); }, { passive: false }); // 开始游戏 startGame(); </script> </body> </html>


