Skip to content
Open

Maze-2D #2058

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Projects/Maze-Game/README.md
Original file line number Diff line number Diff line change
@@ -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

32 changes: 32 additions & 0 deletions Projects/Maze-Game/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Dragon Cloud Maze</title>
<link rel="stylesheet" href="style.css">
<style></style>
</head>
<body>

<div id="popup" class="hidden">
<div class="popup-content">
<p id="popup-message">🎉 You reached the mountaintop! Your firestone awaits! 🔥
<br></p>
<button id="popup-close">OK</button>
</div>
</div>
<h2>🐉 Dragon Cloud Maze</h2>
<p>Use arrow keys to guide your baby dragon to the mountaintop!</p>

<div id="game-ui">
<div id="timer">⏱ Time Left: 30s</div>
<button id="resetBtn">🔄 Reset</button>
</div>

<div id="grid"></div>

<script src="script.js"></script>

</body>
</html>
197 changes: 197 additions & 0 deletions Projects/Maze-Game/script.js
Original file line number Diff line number Diff line change
@@ -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!<br>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();
115 changes: 115 additions & 0 deletions Projects/Maze-Game/style.css
Original file line number Diff line number Diff line change
@@ -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;
}