const gameContainerWrapper = document.getElementById('game-container-wrapper'); const gameContainer = document.getElementById('game-container'); const scoreElement = document.getElementById('score'); const bestScoreElement = document.getElementById('best-score'); const newGameButton = document.getElementById('new-game-button'); const modal = document.getElementById('modal'); const closeModal = document.getElementById('close'); const startButton = document.getElementById('start-button'); const movesElement = document.getElementById('moves'); const toggleImagesButton = document.getElementById('toggle-images-button'); let tilesPerRow = 4; let tiles = []; let score = 0; let moves = 0; let bestScore = localStorage.getItem('bestScore') || 0; let imagesVisible = false; // Initialize the imagesVisible variable bestScoreElement.textContent = bestScore; class Tile { constructor(value, x, y) { this.value = value; this.x = x; this.y = y; this.createElement(); } createElement() { this.tileElement = document.createElement('div'); this.tileElement.classList.add('tile', `tile-${this.value}`); this.updateSize(); gameContainer.appendChild(this.tileElement); } updateSize() { const containerSize = gameContainer.clientWidth; const tileSize = (containerSize - (tilesPerRow - 1) * 5) / tilesPerRow; this.tileElement.style.width = `${tileSize}px`; this.tileElement.style.height = `${tileSize}px`; this.tileElement.style.lineHeight = `${tileSize}px`; this.tileElement.style.transform = `translate(${this.x * (tileSize + 5)}px, ${this.y * (tileSize + 5)}px)`; this.tileElement.style.fontSize = `${tileSize / 2}px`; if (imagesVisible) { this.tileElement.innerHTML = ``; } else { this.tileElement.textContent = this.value; } } updatePosition() { this.updateSize(); } remove() { this.tileElement.remove(); } } const setupBorders = () => { gameContainer.innerHTML = ''; gameContainer.style.gridTemplateColumns = `repeat(${tilesPerRow}, 1fr)`; gameContainer.style.gridTemplateRows = `repeat(${tilesPerRow}, 1fr)`; for (let i = 0; i < tilesPerRow * tilesPerRow; i++) { const borderTile = document.createElement('div'); borderTile.classList.add('border-tile'); gameContainer.appendChild(borderTile); } } const addTile = (value, x, y) => { const tile = new Tile(value, x, y); tiles.push(tile); } const removeTile = (tile) => { tiles = tiles.filter(t => t !== tile); tile.remove(); } const updateTiles = () => { tiles.forEach(tile => tile.updatePosition()); } const generateRandomTile = () => { let emptyCells = []; for (let x = 0; x < tilesPerRow; x++) { for (let y = 0; y < tilesPerRow; y++) { if (!tiles.some(tile => tile.x === x && tile.y === y)) { emptyCells.push({ x, y }); } } } if (emptyCells.length === 0) return; const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]; addTile(Math.random() < 0.9 ? 2 : 4, randomCell.x, randomCell.y); } const resetGame = () => { tiles.forEach(tile => tile.remove()); tiles = []; score = 0; moves = 0; scoreElement.textContent = score; movesElement.textContent = `/ Move [${moves}]`; generateRandomTile(); generateRandomTile(); } const updateScore = (points) => { score += points; scoreElement.textContent = score; if (score > bestScore) { bestScore = score; bestScoreElement.textContent = bestScore; localStorage.setItem('bestScore', bestScore); } } const moveTiles = (direction) => { let moved = false; const getSortedTiles = () => { return tiles.sort((a, b) => { if (direction === 'up' || direction === 'down') { return a.x === b.x ? (direction === 'up' ? a.y - b.y : b.y - a.y) : a.x - b.x; } else { return a.y === b.y ? (direction === 'left' ? a.x - b.x : b.x - a.x) : a.y - b.y; } }); } const mergeTiles = (tile1, tile2) => { updateScore(tile1.value * 2); removeTile(tile1); tile2.value *= 2; tile2.tileElement.className = `tile tile-${tile2.value}`; tile2.updateSize(); moved = true; } const moveTile = (tile, newX, newY) => { tile.x = newX; tile.y = newY; moved = true; } getSortedTiles().forEach(tile => { let nextX = tile.x; let nextY = tile.y; while (true) { const newX = nextX + (direction === 'left' ? -1 : direction === 'right' ? 1 : 0); const newY = nextY + (direction === 'up' ? -1 : direction === 'down' ? 1 : 0); if (newX < 0 || newX >= tilesPerRow || newY < 0 || newY >= tilesPerRow) break; const nextTile = tiles.find(t => t.x === newX && t.y === newY); if (nextTile) { if (nextTile.value === tile.value) { mergeTiles(tile, nextTile); } break; } nextX = newX; nextY = newY; } if (nextX !== tile.x || nextY !== tile.y) moveTile(tile, nextX, nextY); }); if (moved) { updateTiles(); generateRandomTile(); moves++; movesElement.textContent = `/ Move [${moves}]`; if (isGameOver()) { alert('Game Over'); } } } const isGameOver = () => { for (let x = 0; x < tilesPerRow; x++) { for (let y = 0; y < tilesPerRow; y++) { if (!tiles.some(tile => tile.x === x && tile.y === y)) { return false; } const tile = tiles.find(tile => tile.x === x && tile.y === y); if (tiles.some(t => t !== tile && t.value === tile.value && (t.x === x && (t.y === y - 1 || t.y === y + 1) || t.y === y && (t.x === x - 1 || t.x === x + 1)))) { return false; } } } return true; } const handleKeyDown = (event) => { switch (event.key) { case 'ArrowUp': moveTiles('up'); break; case 'ArrowDown': moveTiles('down'); break; case 'ArrowLeft': moveTiles('left'); break; case 'ArrowRight': moveTiles('right'); break; } } let touchStartX = 0; let touchStartY = 0; let hasMoved = false; const handleTouchStart = (event) => { if (event.touches.length !== 1) return; touchStartX = event.touches[0].clientX; touchStartY = event.touches[0].clientY; hasMoved = false; } const handleTouchMove = (event) => { if (event.touches.length !== 1 || hasMoved) return; event.preventDefault(); const touchEndX = event.touches[0].clientX; const touchEndY = event.touches[0].clientY; const diffX = touchEndX - touchStartX; const diffY = touchEndY - touchStartY; if (Math.abs(diffX) > Math.abs(diffY)) { if (diffX > 0) { moveTiles('right'); } else { moveTiles('left'); } } else { if (diffY > 0) { moveTiles('down'); } else { moveTiles('up'); } } hasMoved = true; } newGameButton.addEventListener('click', () => modal.style.display = 'block'); closeModal.addEventListener('click', () => modal.style.display = 'none'); startButton.addEventListener('click', () => { tilesPerRow = parseInt(document.getElementById('grid-size').value); modal.style.display = 'none'; setupBorders(); resetGame(); }); document.addEventListener('keydown', handleKeyDown); gameContainerWrapper.addEventListener('touchstart', handleTouchStart); gameContainerWrapper.addEventListener('touchmove', handleTouchMove); toggleImagesButton.addEventListener('click', () => { imagesVisible = !imagesVisible; updateTiles(); }); window.addEventListener('resize', updateTiles); setupBorders(); resetGame(); function helpshowhide() { var x = document.getElementById("help_img"); if (x.style.display === "block") { x.style.display = "none"; } else { x.style.display = "block"; } }