以下是一个纯HTML实现的2048游戏代码,包含CSS和JavaScript:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>2048 Game</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
background-color: #faf8ef;
}
.container {
width: 450px;
margin: 0 auto;
}
.header {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
h1 {
font-size: 80px;
margin: 0;
color: #776e65;
}
.score-container {
background: #bbada0;
padding: 15px 25px;
border-radius: 6px;
color: white;
font-weight: bold;
text-align: center;
}
.score-title {
font-size: 13px;
display: block;
}
.score-value {
font-size: 25px;
}
.game-container {
background: #bbada0;
border-radius: 6px;
width: 450px;
height: 450px;
padding: 15px;
position: relative;
margin: 0 auto;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 15px;
width: 100%;
height: 100%;
}
.cell {
background: rgba(238, 228, 218, 0.35);
border-radius: 3px;
display: flex;
justify-content: center;
align-items: center;
font-size: 45px;
font-weight: bold;
color: #776e65;
position: relative;
}
.tile-2 {
background: #eee4da;
}
.tile-4 {
background: #ede0c8;
}
.tile-8 {
background: #f2b179;
color: white;
}
.tile-16 {
background: #f59563;
color: white;
}
.tile-32 {
background: #f67c5f;
color: white;
}
.tile-64 {
background: #f65e3b;
color: white;
}
.tile-128 {
background: #edcf72;
color: white;
font-size: 40px;
}
.tile-256 {
background: #edcc61;
color: white;
font-size: 40px;
}
.tile-512 {
background: #edc850;
color: white;
font-size: 40px;
}
.tile-1024 {
background: #edc53f;
color: white;
font-size: 35px;
}
.tile-2048 {
background: #edc22e;
color: white;
font-size: 35px;
}
.game-message {
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(238, 228, 218, 0.73);
z-index: 100;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 6px;
}
.game-message.game-won {
background: rgba(237, 194, 46, 0.5);
color: white;
}
.game-message.game-over {
background: rgba(238, 228, 218, 0.73);
color: #776e65;
}
.game-message p {
font-size: 60px;
font-weight: bold;
margin: 0;
}
.game-message .lower {
margin-top: 30px;
}
.game-message button {
background: #8f7a66;
color: white;
border: none;
border-radius: 3px;
padding: 10px 20px;
font-size: 18px;
cursor: pointer;
}
.game-message button:hover {
background: #9f8b77;
}
.instructions {
margin-top: 30px;
color: #776e65;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>2048</h1>
<div class="score-container">
<span class="score-title">SCORE</span>
<span class="score-value" id="score">0</span>
</div>
</div>
<div class="game-container">
<div class="grid" id="grid"></div>
<div class="game-message" id="game-message">
<p id="message-text"></p>
<div class="lower">
<button id="keep-going-button">Keep going</button>
<button id="retry-button">Try again</button>
</div>
</div>
</div>
<div class="instructions">
<p>Join the numbers and get to the <strong>2048 tile!</strong></p>
<p>Use <strong>arrow keys</strong> to move the tiles.</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const grid = document.getElementById('grid');
const scoreDisplay = document.getElementById('score');
const gameMessage = document.getElementById('game-message');
const messageText = document.getElementById('message-text');
const retryButton = document.getElementById('retry-button');
const keepGoingButton = document.getElementById('keep-going-button');
let board = [];
let score = 0;
let gameWon = false;
// Initialize the game
function initGame() {
// Create empty board
board = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
score = 0;
gameWon = false;
updateScore();
// Clear the grid
grid.innerHTML = '';
// Create cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.id = `cell-${i}-${j}`;
grid.appendChild(cell);
}
}
// Hide game message
gameMessage.style.display = 'none';
// Add two initial tiles
addRandomTile();
addRandomTile();
// Render the board
renderBoard();
}
// Add a random tile (2 or 4) to an empty cell
function addRandomTile() {
const emptyCells = [];
// Find all empty cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (board[i][j] === 0) {
emptyCells.push({row: i, col: j});
}
}
}
// If there are empty cells, add a new tile
if (emptyCells.length > 0) {
const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
board[randomCell.row][randomCell.col] = Math.random() < 0.9 ? 2 : 4;
return true;
}
return false;
}
// Render the board
function renderBoard() {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const cell = document.getElementById(`cell-${i}-${j}`);
const value = board[i][j];
// Clear the cell
cell.className = 'cell';
cell.textContent = '';
// If the cell has a value, add the appropriate class and content
if (value > 0) {
cell.textContent = value;
cell.classList.add(`tile-${value}`);
}
}
}
}
// Update the score display
function updateScore() {
scoreDisplay.textContent = score;
}
// Check if the game is over
function isGameOver() {
// Check if there are any empty cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (board[i][j] === 0) {
return false;
}
}
}
// Check if any adjacent cells have the same value
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (j < 3 && board[i][j] === board[i][j + 1]) {
return false;
}
if (i < 3 && board[i][j] === board[i + 1][j]) {
return false;
}
}
}
return true;
}
// Check if the player has won (reached 2048)
function checkWin() {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (board[i][j] === 2048) {
return true;
}
}
}
return false;
}
// Show game message (win or lose)
function showGameMessage(won) {
if (won) {
messageText.textContent = 'You Win!';
gameMessage.classList.add('game-won');
gameMessage.classList.remove('game-over');
keepGoingButton.style.display = 'inline-block';
} else {
messageText.textContent = 'Game Over!';
gameMessage.classList.add('game-over');
gameMessage.classList.remove('game-won');
keepGoingButton.style.display = 'none';
}
gameMessage.style.display = 'flex';
}
// Move tiles left
function moveLeft() {
let moved = false;
for (let i = 0; i < 4; i++) {
// Remove zeros
let row = board[i].filter(val => val !== 0);
// Merge adjacent equal values
for (let j = 0; j < row.length - 1; j++) {
if (row[j] === row[j + 1]) {
row[j] *= 2;
score += row[j];
row[j + 1] = 0;
moved = true;
if (row[j] === 2048) {
gameWon = true;
}
}
}
// Remove zeros again after merging
row = row.filter(val => val !== 0);
// Add zeros to the end
while (row.length < 4) {
row.push(0);
}
// Check if the row has changed
if (JSON.stringify(board[i]) !== JSON.stringify(row)) {
moved = true;
}
board[i] = row;
}
return moved;
}
// Move tiles right
function moveRight() {
let moved = false;
for (let i = 0; i < 4; i++) {
// Remove zeros
let row = board[i].filter(val => val !== 0);
// Merge adjacent equal values (from right)
for (let j = row.length - 1; j > 0; j--) {
if (row[j] === row[j - 1]) {
row[j] *= 2;
score += row[j];
row[j - 1] = 0;
moved = true;
if (row[j] === 2048) {
gameWon = true;
}
}
}
// Remove zeros again after merging
row = row.filter(val => val !== 0);
// Add zeros to the beginning
while (row.length < 4) {
row.unshift(0);
}
// Check if the row has changed
if (JSON.stringify(board[i]) !== JSON.stringify(row)) {
moved = true;
}
board[i] = row;
}
return moved;
}
// Move tiles up
function moveUp() {
let moved = false;
for (let j = 0; j < 4; j++) {
// Get column
let column = [board[0][j], board[1][j], board[2][j], board[3][j]];
// Remove zeros
column = column.filter(val => val !== 0);
// Merge adjacent equal values
for (let i = 0; i < column.length - 1; i++) {
if (column[i] === column[i + 1]) {
column[i] *= 2;
score += column[i];
column[i + 1] = 0;
moved = true;
if (column[i] === 2048) {
gameWon = true;
}
}
}
// Remove zeros again after merging
column = column.filter(val => val !== 0);
// Add zeros to the end
while (column.length < 4) {
column.push(0);
}
// Check if the column has changed
for (let i = 0; i < 4; i++) {
if (board[i][j] !== column[i]) {
moved = true;
board[i][j] = column[i];
}
}
}
return moved;
}
// Move tiles down
function moveDown() {
let moved = false;
for (let j = 0; j < 4; j++) {
// Get column
let column = [board[0][j], board[1][j], board[2][j], board[3][j]];
// Remove zeros
column = column.filter(val => val !== 0);
// Merge adjacent equal values (from bottom)
for (let i = column.length - 1; i > 0; i--) {
if (column[i] === column[i - 1]) {
column[i] *= 2;
score += column[i];
column[i - 1] = 0;
moved = true;
if (column[i] === 2048) {
gameWon = true;
}
}
}
// Remove zeros again after merging
column = column.filter(val => val !== 0);
// Add zeros to the beginning
while (column.length < 4) {
column.unshift(0);
}
// Check if the column has changed
for (let i = 0; i < 4; i++) {
if (board[i][j] !== column[i]) {
moved = true;
board[i][j] = column[i];
}
}
}
return moved;
}
// Handle keyboard events
function handleKeyPress(event) {
if (gameMessage.style.display === 'flex' && !gameWon) {
return;
}
let moved = false;
switch (event.key) {
case 'ArrowLeft':
moved = moveLeft();
break;
case 'ArrowRight':
moved = moveRight();
break;
case 'ArrowUp':
moved = moveUp();
break;
case 'ArrowDown':
moved = moveDown();
break;
default:
return;
}
if (moved) {
addRandomTile();
renderBoard();
updateScore();
if (gameWon) {
showGameMessage(true);
} else if (isGameOver()) {
showGameMessage(false);
}
}
}
// Event listeners
document.addEventListener('keydown', handleKeyPress);
retryButton.addEventListener('click', initGame);
keepGoingButton.addEventListener('click', () => {
gameMessage.style.display = 'none';
gameWon = false;
});
// Start the game
initGame();
});
</script>
</body>
</html>
功能说明
这个2048游戏实现包含以下功能:
- 4×4的游戏棋盘
- 使用箭头键控制方块移动
- 分数计算和显示
- 游戏胜利检测(达到2048方块)
- 游戏结束检测(无法移动)
- 重新开始游戏选项
- 达到2048后可以选择继续游戏
- 响应式设计,适应不同屏幕
使用方法
- 将上述代码复制到一个HTML文件中
- 用浏览器打开该文件即可开始游戏
- 使用键盘方向键(↑↓←→)移动方块
- 相同数字的方块碰撞时会合并
- 目标是得到2048方块