class Game { constructor() { this.grid = Array(4).fill().map(() => Array(4).fill(0)); this.score = 0; this.init(); } init() { this.addNewTile(); this.addNewTile(); this.updateDisplay(); } addNewTile() { const emptyCells = []; for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { if (this.grid[i][j] === 0) { emptyCells.push({x: i, y: j}); } } } if (emptyCells.length > 0) { const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]; this.grid[randomCell.x][randomCell.y] = Math.random() < 0.9 ? 2 : 4; } } updateDisplay() { for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { const cell = document.getElementById(`cell-${i}-${j}`); const value = this.grid[i][j]; cell.className = 'grid-cell' + (value ? ` tile tile-${value}` : ''); cell.textContent = value || ''; } } document.getElementById('score').textContent = this.score; } move(direction) { let moved = false; const oldGrid = JSON.stringify(this.grid); switch(direction) { case 'left': moved = this.moveLeft(); break; case 'right': moved = this.moveRight(); break; case 'up': moved = this.moveUp(); break; case 'down': moved = this.moveDown(); break; } if (moved) { this.addNewTile(); this.updateDisplay(); if (this.isGameOver()) { alert('Game Over!'); } } } moveLeft() { let moved = false; for (let i = 0; i < 4; i++) { let row = this.grid[i].filter(cell => cell !== 0); for (let j = 0; j < row.length - 1; j++) { if (row[j] === row[j + 1]) { row[j] *= 2; this.score += row[j]; row.splice(j + 1, 1); moved = true; } } while (row.length < 4) { row.push(0); } if (row.join(',') !== this.grid[i].join(',')) { moved = true; } this.grid[i] = row; } return moved; } moveRight() { let moved = false; for (let i = 0; i < 4; i++) { let row = this.grid[i].filter(cell => cell !== 0); for (let j = row.length - 1; j > 0; j--) { if (row[j] === row[j - 1]) { row[j] *= 2; this.score += row[j]; row.splice(j - 1, 1); row.unshift(0); moved = true; } } while (row.length < 4) { row.unshift(0); } if (row.join(',') !== this.grid[i].join(',')) { moved = true; } this.grid[i] = row; } return moved; } moveUp() { let moved = false; for (let j = 0; j < 4; j++) { let column = []; for (let i = 0; i < 4; i++) { column.push(this.grid[i][j]); } column = column.filter(cell => cell !== 0); for (let i = 0; i < column.length - 1; i++) { if (column[i] === column[i + 1]) { column[i] *= 2; this.score += column[i]; column.splice(i + 1, 1); moved = true; } } while (column.length < 4) { column.push(0); } for (let i = 0; i < 4; i++) { if (this.grid[i][j] !== column[i]) { moved = true; } this.grid[i][j] = column[i]; } } return moved; } moveDown() { let moved = false; for (let j = 0; j < 4; j++) { let column = []; for (let i = 0; i < 4; i++) { column.push(this.grid[i][j]); } column = column.filter(cell => cell !== 0); for (let i = column.length - 1; i > 0; i--) { if (column[i] === column[i - 1]) { column[i] *= 2; this.score += column[i]; column.splice(i - 1, 1); column.unshift(0); moved = true; } } while (column.length < 4) { column.unshift(0); } for (let i = 0; i < 4; i++) { if (this.grid[i][j] !== column[i]) { moved = true; } this.grid[i][j] = column[i]; } } return moved; } isGameOver() { // Check for empty cells for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { if (this.grid[i][j] === 0) { return false; } } } // Check for possible merges for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { if (j < 3 && this.grid[i][j] === this.grid[i][j + 1]) return false; if (i < 3 && this.grid[i][j] === this.grid[i + 1][j]) return false; } } return true; } } // Initialize game let game = new Game(); // Event listeners document.addEventListener('keydown', (event) => { switch(event.key) { case 'ArrowLeft': game.move('left'); break; case 'ArrowRight': game.move('right'); break; case 'ArrowUp': game.move('up'); break; case 'ArrowDown': game.move('down'); break; } }); document.getElementById('new-game').addEventListener('click', () => { game = new Game(); });