diff --git a/Projects/Maze-Game/README.md b/Projects/Maze-Game/README.md new file mode 100644 index 000000000..892f65ad0 --- /dev/null +++ b/Projects/Maze-Game/README.md @@ -0,0 +1,24 @@ +# Maze Game + +A simple **Maze Game** built with HTML, CSS, and JavaScript. Navigate from start to finish using arrow keys. + +## Live Demo +Play it here: [Dragon Maze](https://ayresgaia.github.io/Dragon-Maze/) + +## How to Play +- Use **arrow keys** to move the player. +- Reach the **end point** to win the game. +- Avoid walls and dead ends! + +## Features +- Responsive and simple UI +- Works in modern browsers +- Fun and easy to customize + +## Technologies Used +- HTML +- CSS +- JavaScript + +## File Structure + diff --git a/Projects/Maze-Game/index.html b/Projects/Maze-Game/index.html new file mode 100644 index 000000000..8c24881bb --- /dev/null +++ b/Projects/Maze-Game/index.html @@ -0,0 +1,32 @@ + + + + + + Dragon Cloud Maze + + + + + + +

🐉 Dragon Cloud Maze

+

Use arrow keys to guide your baby dragon to the mountaintop!

+ +
+
⏱ Time Left: 30s
+ +
+ +
+ + + + + diff --git a/Projects/Maze-Game/script.js b/Projects/Maze-Game/script.js new file mode 100644 index 000000000..e61237ff6 --- /dev/null +++ b/Projects/Maze-Game/script.js @@ -0,0 +1,197 @@ +function generateMazeGrid(width, height) { + // Maze generator class inside function + class MazeGrid { + constructor(w, h) { + this.width = w; + this.height = h; + this.grid = []; + for (let y = 0; y < h; y++) { + this.grid[y] = []; + for (let x = 0; x < w; x++) { + this.grid[y][x] = { visited: false, walls: [true, true, true, true] }; + } + } + } + + getUnvisitedNeighbors(x, y) { + const neighbors = []; + if (y > 0 && !this.grid[y - 1][x].visited) neighbors.push({ x, y: y - 1, dir: 0 }); + if (x < this.width - 1 && !this.grid[y][x + 1].visited) neighbors.push({ x: x + 1, y, dir: 1 }); + if (y < this.height - 1 && !this.grid[y + 1][x].visited) neighbors.push({ x, y: y + 1, dir: 2 }); + if (x > 0 && !this.grid[y][x - 1].visited) neighbors.push({ x: x - 1, y, dir: 3 }); + return neighbors; + } + + removeWalls(x, y, nx, ny, dir) { + this.grid[y][x].walls[dir] = false; + this.grid[ny][nx].walls[(dir + 2) % 4] = false; + } + + generateMaze(x = 0, y = 0) { + this.grid[y][x].visited = true; + let neighbors = this.getUnvisitedNeighbors(x, y); + while (neighbors.length > 0) { + const rand = Math.floor(Math.random() * neighbors.length); + const { x: nx, y: ny, dir } = neighbors[rand]; + if (!this.grid[ny][nx].visited) { + this.removeWalls(x, y, nx, ny, dir); + this.generateMaze(nx, ny); + } + neighbors.splice(rand, 1); + } + } + + toOutputGrid() { + const outWidth = this.width * 2 + 1; + const outHeight = this.height * 2 + 1; + const output = Array.from({ length: outHeight }, () => Array(outWidth).fill(1)); + + for (let y = 0; y < this.height; y++) { + for (let x = 0; x < this.width; x++) { + const outY = y * 2 + 1; + const outX = x * 2 + 1; + output[outY][outX] = 0; + + const cell = this.grid[y][x]; + if (!cell.walls[0]) output[outY - 1][outX] = 0; + if (!cell.walls[1]) output[outY][outX + 1] = 0; + if (!cell.walls[2]) output[outY + 1][outX] = 0; + if (!cell.walls[3]) output[outY][outX - 1] = 0; + } + } + + // Mark goal at bottom-right open cell + output[outHeight - 2][outWidth - 2] = 'G'; + + return output; + } + } + + const maze = new MazeGrid(width, height); + maze.generateMaze(); + return maze.toOutputGrid(); +} + +// Example: +const mazeArray = generateMazeGrid(7, 10); // This is your 2D array +console.log(mazeArray); + + + +const mazeData = mazeArray; + +const grid = document.getElementById('grid'); +const popup = document.getElementById('popup'); +const popupClose = document.getElementById('popup-close'); +const resetBtn = document.getElementById('resetBtn'); +const timerDisplay = document.getElementById('timer'); + +const ROWS = mazeData.length; +const COLS = mazeData[0].length; + +let dragonPos = { row: 1, col: 1 }; +let timer = 60; +let timerInterval; + +function drawMaze() { + grid.innerHTML = ''; + for (let r = 0; r < ROWS; r++) { + for (let c = 0; c < COLS; c++) { + const tile = document.createElement('div'); + tile.classList.add('tile'); + + if (mazeData[r][c] === 1) tile.classList.add('wall'); + if (mazeData[r][c] === 'G') tile.classList.add('goal'); + if (r === dragonPos.row && c === dragonPos.col) { + tile.classList.add('dragon'); + tile.innerHTML = '🐉'; + } + + grid.appendChild(tile); + } + } +} + +function canMove(row, col) { + return ( + row >= 0 && + col >= 0 && + row < ROWS && + col < COLS && + mazeData[row][col] !== 1 + ); +} + +function moveDragon(dr, dc) { + const newRow = dragonPos.row + dr; + const newCol = dragonPos.col + dc; + + if (!canMove(newRow, newCol)) return; + + dragonPos = { row: newRow, col: newCol }; + drawMaze(); + + if (mazeData[newRow][newCol] === 'G') { + clearInterval(timerInterval); + let score=timer*10; + showPopup(`🎉 You reached the mountaintop!
Score: ${score}`); + window.removeEventListener('keydown', handleKey); + } +} + +function handleKey(e) { + if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) { + e.preventDefault(); + switch (e.key) { + case 'ArrowUp': moveDragon(-1, 0); break; + case 'ArrowDown': moveDragon(1, 0); break; + case 'ArrowLeft': moveDragon(0, -1); break; + case 'ArrowRight': moveDragon(0, 1); break; + } + } +} + +function showPopup(message) { + console.log("Popup triggered with message:", message); + document.getElementById('popup-message').innerHTML = message; + popup.classList.remove('hidden'); +} + + +function updateTimerDisplay() { + timerDisplay.textContent = `⏱ Time Left: ${timer}s`; +} + +function startTimer() { + clearInterval(timerInterval); + timer = 30; + updateTimerDisplay(); + + timerInterval = setInterval(() => { + timer--; + updateTimerDisplay(); + if (timer <= 0) { + clearInterval(timerInterval); + showPopup("⏰ Time's up! The dragon got lost in the clouds!"); + window.removeEventListener('keydown', handleKey); + } + }, 1000); +} + +resetBtn.addEventListener('click', () => { + dragonPos = { row: 1, col: 1 }; + drawMaze(); + popup.classList.add('hidden'); + window.addEventListener('keydown', handleKey); + startTimer(); +}); + +popupClose.addEventListener('click', () => { + popup.classList.add('hidden'); +}); + +window.addEventListener('keydown', handleKey); + +// Start game +drawMaze(); +startTimer(); diff --git a/Projects/Maze-Game/style.css b/Projects/Maze-Game/style.css new file mode 100644 index 000000000..8215a755f --- /dev/null +++ b/Projects/Maze-Game/style.css @@ -0,0 +1,115 @@ +body { + font-family: 'Comic Sans MS', cursive; + background-color: #eaf6ff; + text-align: center; + padding: 20px; +} + +#game-ui { + display: flex; + justify-content: center; + align-items: center; + gap: 20px; + margin-top: 20px; +} + +#timer { + font-size: 18px; + font-weight: bold; + color: #333; +} + +#resetBtn { + background-color: #ff6961; + color: white; + padding: 8px 16px; + font-size: 16px; + border: none; + border-radius: 8px; + cursor: pointer; +} + +#resetBtn:hover { + background-color: #e60000; +} + + +#grid { + display: grid; + grid-template-columns: repeat(15, 60px); + gap: 5px; + justify-content: center; + margin: 20px auto; +} + +.tile { + width: 60px; + height: 60px; + border: 2px solid #ccc; + display: flex; + justify-content: center; + align-items: center; + background-color: #fffdf0; + font-size: 36px; +} + +.wall { + background-color: #cce0ff; + border-radius: 10px; + box-shadow: inset 0 0 10px #7bb0f7; +} + +.dragon { + font-size: 36px; + animation: flap 0.5s infinite alternate; +} + +@keyframes flap { + 0% { transform: translateY(0); } + 100% { transform: translateY(-5px); } +} + +.goal { + background-color: gold; + border-radius: 50%; + box-shadow: 0 0 12px 3px #ffdf00; +} + +#popup { + position: fixed; + top: 0; left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.6); + display: flex; + justify-content: center; + align-items: center; + z-index: 999; +} + +.popup-content { + background: white; + padding: 30px; + border-radius: 12px; + font-size: 20px; + box-shadow: 0 4px 10px rgba(0,0,0,0.3); +} + +.hidden { + display: none !important; +} + +#popup-close { + margin-top: 15px; + padding: 10px 20px; + font-size: 16px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 8px; + cursor: pointer; +} + +#popup-close:hover { + background-color: #388e3c; +} \ No newline at end of file