diff --git a/app/luca/Luca.css b/app/luca/Luca.css index 3e6bd4c..3ba4f37 100644 --- a/app/luca/Luca.css +++ b/app/luca/Luca.css @@ -1,4 +1,4 @@ -/* Luca.css */ +/* Don't mess with that styling please */ .programmer-space { padding: 20px; margin: 10px; @@ -10,22 +10,108 @@ background-color: #4a90e2; /* Blue */ } -.click-button { - padding: 10px 20px; - margin-top: 10px; +/* Snake game container */ +.snake-game-container { + display: flex; + flex-direction: column; /* Stack score and game area vertically */ + align-items: center; /* Center content horizontally */ + background-color: #f5f5f5; /* Light background for contrast */ + border-radius: 12px; /* Rounded corners for a modern touch */ + padding: 20px; +} + +/* Snake game area */ +.snake-game { + position: relative; + width: 400px; /* 20 cells * 20px */ + height: 400px; /* 20 cells * 20px */ + border: 3px solid #4a90e2; /* Accent color border */ + background-color: #222; /* Dark background for the game area */ + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); /* Enhanced shadow for better depth */ + border-radius: 8px; /* Rounded corners for the game board */ + margin-top: 20px; /* Space between score and game */ +} + +/* Snake segments */ +.snake-segment { + position: absolute; + width: 20px; + height: 20px; + background-color: #4caf50; /* Modern green */ + border-radius: 6px; /* Rounded corners for the snake segments */ +} + +/* Food */ +.food { + position: absolute; + width: 20px; + height: 20px; + background-color: #f44336; /* Modern red */ + border-radius: 6px; /* Rounded corners for the food */ +} + +/* Game Over message */ +.game-over { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: rgba(0, 0, 0, 0.8); /* Slightly darker overlay for better readability */ + color: #fff; + padding: 20px; + border-radius: 10px; + font-size: 22px; + text-align: center; + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4); /* Enhanced shadow for visibility */ +} + +/* Score display */ +.score { + font-size: 26px; + font-weight: bold; + color: #4a90e2; /* Accent color */ +} + +/* Reload Game Button */ +.button { + background-color: #4CAF50; /* Green background */ border: none; - border-radius: 4px; - background-color: #fff; - color: #4a90e2; - cursor: pointer; - font-size: 16px; -} - -.click-button:hover { - background-color: #e3e3e3; -} - -.lorem-ipsum { + color: white; + padding: 14px 28px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 18px; margin-top: 20px; - font-size: 14px; + cursor: pointer; + border-radius: 8px; + transition: background-color 0.3s ease; +} + +.button:hover { + background-color: #388E3C; /* Darker green for hover effect */ +} + +/* Game Explanation Section */ +.game-explanation { + margin-top: 30px; + padding: 20px; + background-color: #fff; /* Light background for readability */ + border-radius: 8px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ + color: #333; +} + +.game-explanation h3 { + margin-bottom: 15px; + font-size: 1.5rem; + color: #4a90e2; /* Accent color */ +} + +.game-explanation p { + margin-bottom: 15px; +} + +.game-explanation ul { + margin-left: 20px; } diff --git a/app/luca/Luca.tsx b/app/luca/Luca.tsx index 3c5c8a9..6d851a7 100644 --- a/app/luca/Luca.tsx +++ b/app/luca/Luca.tsx @@ -1,33 +1,205 @@ -// Luca.tsx "use client"; -import React, { useState } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import './Luca.css'; // Import specific styles for Luca +const GRID_WIDTH = 20; +const GRID_HEIGHT = 20; +const CELL_SIZE = 20; + const Luca = () => { - // State to keep track of the number of clicks + // State for tracking clicks const [clickCount, setClickCount] = useState(0); - // Function to handle button click - const handleClick = () => { - setClickCount(clickCount + 1); + // State for Snake game + const [snake, setSnake] = useState([{ x: 5, y: 5 }]); + const [food, setFood] = useState({ x: 10, y: 10 }); + const [direction, setDirection] = useState('RIGHT'); + const [gameOver, setGameOver] = useState(false); + const [gameStarted, setGameStarted] = useState(false); + const [score, setScore] = useState(0); + + // Resets the game to its initial state + const resetGame = () => { + setSnake([{ x: 5, y: 5 }]); + setFood(generateRandomFood()); + setDirection('RIGHT'); + setScore(0); + setGameOver(false); }; + // Generates a random position for the food + const generateRandomFood = () => ({ + x: Math.floor(Math.random() * GRID_WIDTH), + y: Math.floor(Math.random() * GRID_HEIGHT), + }); + + // Moves the snake based on the current direction + const moveSnake = useCallback(() => { + if (gameOver) return; + + let newSnake = [...snake]; + let head = { ...newSnake[0] }; + + // Update head position based on direction + switch (direction) { + case 'UP': head.y -= 1; break; + case 'DOWN': head.y += 1; break; + case 'LEFT': head.x -= 1; break; + case 'RIGHT': head.x += 1; break; + default: break; + } + + // Check if the new head position is the food + const hasEatenFood = head.x === food.x && head.y === food.y; + + newSnake = [head, ...newSnake]; + + if (hasEatenFood) { + setFood(generateRandomFood()); + setScore(prevScore => prevScore + 1); + } else { + newSnake.pop(); + } + + // Check for collisions + if ( + head.x < 0 || head.x >= GRID_WIDTH || + head.y < 0 || head.y >= GRID_HEIGHT || + newSnake.slice(1).some(seg => seg.x === head.x && seg.y === head.y) + ) { + setGameOver(true); + return; + } + + setSnake(newSnake); + }, [direction, snake, food, gameOver]); + + // Set up interval to move the snake if the game is started + useEffect(() => { + if (gameStarted && !gameOver) { + const interval = setInterval(moveSnake, 200); + return () => clearInterval(interval); + } + }, [moveSnake, gameStarted, gameOver]); + + // Handle key presses to change the snake's direction + const handleKeyDown = (e: KeyboardEvent) => { + if (['KeyW', 'KeyA', 'KeyS', 'KeyD'].includes(e.code)) { + e.preventDefault(); // Prevent default behavior for movement keys + } + + switch (e.code) { + case 'KeyW': if (direction !== 'DOWN') setDirection('UP'); break; + case 'KeyS': if (direction !== 'UP') setDirection('DOWN'); break; + case 'KeyA': if (direction !== 'RIGHT') setDirection('LEFT'); break; + case 'KeyD': if (direction !== 'LEFT') setDirection('RIGHT'); break; + default: break; + } + }; + + useEffect(() => { + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [direction]); + return (

Luca's Space

Welcome, Luca! This is your programming space.

{/* Button to count clicks */} -

You've clicked the button {clickCount} times!

- {/* Lorem Ipsum text */} -
+ {/* Start Game Button */} + {!gameStarted && !gameOver && ( + + )} + + {/* Snake game container */} + {gameStarted && ( +
+ {/* Score display */} +
+

Score: {score}

+
+ + {/* Snake game */} +
+ {snake.map((segment, index) => ( +
+ ))} +
+ {gameOver && ( +
+ Game Over + +
+ )} +
+
+ )} + + {/* Explanation section */} +
+

Game Explanation

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Disclaimer: The game controls can be sensitive to rapid direction changes. If you press two directional keys in quick succession (e.g., moving right and then quickly pressing up or left), the snake may change direction instantly. This can sometimes lead to unintended behavior, including the possibility of the snake colliding with itself or the walls and causing an immediate game over. Please be mindful of this issue while playing. +

+

+ How the Game Works: +
+ - Use the W key to move the snake up, the S key to move it down, the{' '} + A key to move it left, and the D key to move it right. +
+ - The snake will grow longer each time it eats the red food that appears on the game board. +
+ - The game ends if the snake runs into the walls of the game area or into itself. +

+

+ Code Structure: +
+ - State Management: +
+ - `useState`: Manages the snake's position, food position, direction, score, and game status. +
+ - Movement Logic: +
+ - `moveSnake`: Updates the snake's position, checks for food consumption, and handles collisions. +
+ - Collision Detection: +
+ - Within `moveSnake`, checks if the snake's head collides with walls or itself. +
+ - Event Handling: +
+ - `handleKeyDown`: Listens for key presses to change the snake's direction and prevents reversing. +
+ - Game Start and Restart: +
+ - Start Game Button: Starts the game loop. +
+ - Game Over and Restart Button: Resets the game state for a new game.

diff --git a/app/patrick/Patrick.css b/app/patrick/Patrick.css index 101f408..f1d5d25 100644 --- a/app/patrick/Patrick.css +++ b/app/patrick/Patrick.css @@ -1,4 +1,5 @@ /* Patrick.css */ +/* Don't mess with that styling please */ .programmer-space { padding: 20px; margin: 10px; diff --git a/app/yasin/Yasin.css b/app/yasin/Yasin.css index f6d48df..58c8c5e 100644 --- a/app/yasin/Yasin.css +++ b/app/yasin/Yasin.css @@ -1,4 +1,5 @@ /* Yasin.css */ +/* Don't mess with that styling please */ .programmer-space { padding: 20px; margin: 10px;