Spaces:
Running
Running
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(); | |
}); |