AIGreenPath / game.js
Zayeemk's picture
Upload 26 files
18935fc verified
document.addEventListener('DOMContentLoaded', () => {
const gridContainer = document.querySelector('.grid-container');
const scoreElement = document.getElementById('score');
const bestScoreElement = document.getElementById('best-score');
const newGameButton = document.getElementById('new-game');
const tryAgainButton = document.getElementById('try-again');
const keepGoingButton = document.getElementById('keep-going');
const gameOverScreen = document.querySelector('.game-over');
const gameWonScreen = document.querySelector('.game-won');
let grid = [];
let score = 0;
let bestScore = localStorage.getItem('bestScore') || 0;
let gameOver = false;
let gameWon = false;
// Initialize the game
function initGame() {
// Clear the grid
grid = Array(4).fill().map(() => Array(4).fill(0));
score = 0;
gameOver = false;
gameWon = false;
// Clear the grid container
gridContainer.innerHTML = '';
// Create the grid cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
const cell = document.createElement('div');
cell.className = 'grid-cell';
gridContainer.appendChild(cell);
}
}
// Add initial tiles
addRandomTile();
addRandomTile();
// Update the score display
updateScore();
// Hide game over/win screens
gameOverScreen.style.display = 'none';
gameWonScreen.style.display = 'none';
}
// 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 (grid[i][j] === 0) {
emptyCells.push({x: i, y: j});
}
}
}
if (emptyCells.length > 0) {
// Choose a random empty cell
const {x, y} = emptyCells[Math.floor(Math.random() * emptyCells.length)];
// 90% chance for 2, 10% chance for 4
grid[x][y] = Math.random() < 0.9 ? 2 : 4;
// Create and animate the new tile
createTile(x, y, grid[x][y], true);
}
}
// Create a tile element at the specified position
function createTile(x, y, value, isNew = false) {
const tile = document.createElement('div');
tile.className = `tile tile-${value} ${isNew ? 'new-tile' : ''}`;
tile.textContent = value;
// Position the tile
const posX = y * 25 + (y * 15);
const posY = x * 25 + (x * 15);
tile.style.left = `${posX}%`;
tile.style.top = `${posY}%`;
// Add data attributes for tracking position
tile.dataset.x = x;
tile.dataset.y = y;
tile.dataset.value = value;
gridContainer.appendChild(tile);
return tile;
}
// Update the score display
function updateScore() {
scoreElement.textContent = score;
bestScore = Math.max(score, bestScore);
bestScoreElement.textContent = bestScore;
localStorage.setItem('bestScore', bestScore);
}
// Check if there are any moves left
function hasMovesLeft() {
// Check for any empty cells
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (grid[i][j] === 0) return true;
// Check adjacent cells for possible merges
if (i < 3 && grid[i][j] === grid[i + 1][j]) return true;
if (j < 3 && grid[i][j] === grid[i][j + 1]) return true;
}
}
return false;
}
// Move tiles in the specified direction
function moveTiles(direction) {
if (gameOver || gameWon) return false;
let moved = false;
const oldGrid = JSON.parse(JSON.stringify(grid));
// Remove all tiles from the DOM (we'll recreate them after moving)
const tiles = document.querySelectorAll('.tile');
const tilesData = Array.from(tiles).map(tile => ({
x: parseInt(tile.dataset.x),
y: parseInt(tile.dataset.y),
value: parseInt(tile.dataset.value),
element: tile
}));
tiles.forEach(tile => tile.remove());
// Process the move based on direction
switch (direction) {
case 'up':
moved = moveUp();
break;
case 'right':
moved = moveRight();
break;
case 'down':
moved = moveDown();
break;
case 'left':
moved = moveLeft();
break;
}
// If the grid changed, add a new random tile
if (moved) {
addRandomTile();
updateScore();
// Check for win condition
if (!gameWon && checkWin()) {
gameWon = true;
gameWonScreen.style.display = 'flex';
}
// Check for game over
else if (!hasMovesLeft()) {
gameOver = true;
gameOverScreen.style.display = 'flex';
}
}
// Recreate tiles with new positions
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (grid[i][j] !== 0) {
createTile(i, j, grid[i][j]);
}
}
}
return moved;
}
// Move tiles up
function moveUp() {
let moved = false;
for (let j = 0; j < 4; j++) {
// Move all tiles up as much as possible
for (let i = 1; i < 4; i++) {
if (grid[i][j] !== 0) {
let row = i;
while (row > 0 && grid[row - 1][j] === 0) {
grid[row - 1][j] = grid[row][j];
grid[row][j] = 0;
row--;
moved = true;
}
// Check for merge with the tile above
if (row > 0 && grid[row - 1][j] === grid[row][j] &&
!document.querySelector(`.tile[data-x="${row-1}"][data-y="${j}"].merged`)) {
grid[row - 1][j] *= 2;
score += grid[row - 1][j];
grid[row][j] = 0;
moved = true;
}
}
}
}
return moved;
}
// Move tiles right
function moveRight() {
let moved = false;
for (let i = 0; i < 4; i++) {
for (let j = 2; j >= 0; j--) {
if (grid[i][j] !== 0) {
let col = j;
while (col < 3 && grid[i][col + 1] === 0) {
grid[i][col + 1] = grid[i][col];
grid[i][col] = 0;
col++;
moved = true;
}
// Check for merge with the tile to the right
if (col < 3 && grid[i][col + 1] === grid[i][col] &&
!document.querySelector(`.tile[data-x="${i}"][data-y="${col+1}"].merged`)) {
grid[i][col + 1] *= 2;
score += grid[i][col + 1];
grid[i][col] = 0;
moved = true;
}
}
}
}
return moved;
}
// Move tiles down
function moveDown() {
let moved = false;
for (let j = 0; j < 4; j++) {
for (let i = 2; i >= 0; i--) {
if (grid[i][j] !== 0) {
let row = i;
while (row < 3 && grid[row + 1][j] === 0) {
grid[row + 1][j] = grid[row][j];
grid[row][j] = 0;
row++;
moved = true;
}
// Check for merge with the tile below
if (row < 3 && grid[row + 1][j] === grid[row][j] &&
!document.querySelector(`.tile[data-x="${row+1}"][data-y="${j}"].merged`)) {
grid[row + 1][j] *= 2;
score += grid[row + 1][j];
grid[row][j] = 0;
moved = true;
}
}
}
}
return moved;
}
// Move tiles left
function moveLeft() {
let moved = false;
for (let i = 0; i < 4; i++) {
for (let j = 1; j < 4; j++) {
if (grid[i][j] !== 0) {
let col = j;
while (col > 0 && grid[i][col - 1] === 0) {
grid[i][col - 1] = grid[i][col];
grid[i][col] = 0;
col--;
moved = true;
}
// Check for merge with the tile to the left
if (col > 0 && grid[i][col - 1] === grid[i][col] &&
!document.querySelector(`.tile[data-x="${i}"][data-y="${col-1}"].merged`)) {
grid[i][col - 1] *= 2;
score += grid[i][col - 1];
grid[i][col] = 0;
moved = true;
}
}
}
}
return moved;
}
// 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 (grid[i][j] === 2048) {
return true;
}
}
}
return false;
}
// Event listeners
document.addEventListener('keydown', (e) => {
switch (e.key) {
case 'ArrowUp':
e.preventDefault();
moveTiles('up');
break;
case 'ArrowRight':
e.preventDefault();
moveTiles('right');
break;
case 'ArrowDown':
e.preventDefault();
moveTiles('down');
break;
case 'ArrowLeft':
e.preventDefault();
moveTiles('left');
break;
}
});
// Touch support for mobile devices
let touchStartX = 0;
let touchStartY = 0;
let touchEndX = 0;
let touchEndY = 0;
document.addEventListener('touchstart', (e) => {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
}, false);
document.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].clientX;
touchEndY = e.changedTouches[0].clientY;
handleSwipe();
}, false);
function handleSwipe() {
const dx = touchEndX - touchStartX;
const dy = touchEndY - touchStartY;
// Determine if the swipe was more horizontal or vertical
if (Math.abs(dx) > Math.abs(dy)) {
// Horizontal swipe
if (dx > 0) {
moveTiles('right');
} else {
moveTiles('left');
}
} else {
// Vertical swipe
if (dy > 0) {
moveTiles('down');
} else {
moveTiles('up');
}
}
}
// Button event listeners
newGameButton.addEventListener('click', initGame);
tryAgainButton.addEventListener('click', initGame);
keepGoingButton.addEventListener('click', () => {
gameWonScreen.style.display = 'none';
gameWon = false;
});
// Initialize the game
initGame();
});