const SIZE = 4; const NEW_VALUES = [2, 4]; const TILE_SIZE = 100; const GRID_PADDING = 10; const { createCanvas } = require('canvas'); class Game2048 { constructor() { this.board = Array.from({ length: SIZE }, () => Array(SIZE).fill(0)); this.addNewTile(); this.addNewTile(); } addNewTile() { const emptyCells = []; for (let r = 0; r < SIZE; r++) { for (let c = 0; c < SIZE; c++) { if (this.board[r][c] === 0) { emptyCells.push([r, c]); } } } if (emptyCells.length > 0) { const [row, col] = emptyCells[Math.floor(Math.random() * emptyCells.length)]; this.board[row][col] = NEW_VALUES[Math.floor(Math.random() * NEW_VALUES.length)]; } } moveLeft() { let moved = false; for (let row = 0; row < SIZE; row++) { let newRow = this.board[row].filter(val => val !== 0); for (let col = 0; col < newRow.length - 1; col++) { if (newRow[col] === newRow[col + 1]) { newRow[col] *= 2; newRow.splice(col + 1, 1); moved = true; } } while (newRow.length < SIZE) { newRow.push(0); } if (this.board[row].toString() !== newRow.toString()) { moved = true; this.board[row] = newRow; } } return moved; } rotateBoard() { const newBoard = Array.from({ length: SIZE }, () => Array(SIZE).fill(0)); for (let row = 0; row < SIZE; row++) { for (let col = 0; col < SIZE; col++) { newBoard[col][SIZE - row - 1] = this.board[row][col]; } } this.board = newBoard; } move(direction) { let moved = false; for (let i = 0; i < direction; i++) { this.rotateBoard(); } moved = this.moveLeft(); for (let i = direction; i < 4; i++) { this.rotateBoard(); } if (moved) { this.addNewTile(); } return moved; } isGameOver() { for (let row = 0; row < SIZE; row++) { for (let col = 0; col < SIZE; col++) { if (this.board[row][col] === 0) return false; if (col < SIZE - 1 && this.board[row][col] === this.board[row][col + 1]) return false; if (row < SIZE - 1 && this.board[row][col] === this.board[row + 1][col]) return false; } } return true; } drawBoard() { const canvas = createCanvas(SIZE * (TILE_SIZE + GRID_PADDING) + GRID_PADDING, SIZE * (TILE_SIZE + GRID_PADDING) + GRID_PADDING); const ctx = canvas.getContext('2d'); ctx.fillStyle = '#bbada0'; ctx.fillRect(0, 0, canvas.width, canvas.height); for (let row = 0; row < SIZE; row++) { for (let col = 0; col < SIZE; col++) { const value = this.board[row][col]; const x = col * (TILE_SIZE + GRID_PADDING) + GRID_PADDING; const y = row * (TILE_SIZE + GRID_PADDING) + GRID_PADDING; ctx.fillStyle = value ? '#eee4da' : '#cdc1b4'; ctx.fillRect(x, y, TILE_SIZE, TILE_SIZE); if (value) { ctx.font = 'bold 40px Arial'; ctx.fillStyle = '#776e65'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(value, x + TILE_SIZE / 2, y + TILE_SIZE / 2); } } } return canvas.toBuffer(); } } module.exports = Game2048;