diff --git a/app/luca/Luca.tsx b/app/luca/Luca.tsx index 3c5c8a9..170e930 100644 --- a/app/luca/Luca.tsx +++ b/app/luca/Luca.tsx @@ -1,25 +1,118 @@ // 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 WIDTH = 20; +const HEIGHT = 20; +const CELL_SIZE = 20; + const Luca = () => { // State to keep track of the number of clicks const [clickCount, setClickCount] = useState(0); - // Function to handle button click - const handleClick = () => { - setClickCount(clickCount + 1); + // State and logic for the Snake game + const [snake, setSnake] = useState([{ x: 5, y: 5 }]); + const [food, setFood] = useState({ x: 10, y: 10 }); + const [direction, setDirection] = useState('RIGHT'); + const [score, setScore] = useState(0); + const [gameOver, setGameOver] = useState(false); + + 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; + } + + // Check if the new head position is the food + const hasEatenFood = head.x === food.x && head.y === food.y; + + // Update the snake's body + newSnake = [head, ...newSnake]; + + if (hasEatenFood) { + // Generate new food position + setFood({ + x: Math.floor(Math.random() * WIDTH), + y: Math.floor(Math.random() * HEIGHT), + }); + setScore(score + 1); // Increase the score + } else { + // Remove the tail segment if not eating food + newSnake.pop(); + } + + // Check for collisions + if ( + head.x < 0 || + head.x >= WIDTH || + head.y < 0 || + head.y >= HEIGHT || + newSnake.slice(1).some(seg => seg.x === head.x && seg.y === head.y) + ) { + setGameOver(true); + return; + } + + setSnake(newSnake); + }, [direction, snake, food, gameOver, score]); + + useEffect(() => { + const interval = setInterval(moveSnake, 200); + return () => clearInterval(interval); + }, [moveSnake]); + + const handleKeyDown = (e: KeyboardEvent) => { + // Prevent default behavior for 'W', 'A', 'S', 'D' to avoid scrolling + if (['KeyW', 'KeyA', 'KeyS', 'KeyD'].includes(e.code)) { + e.preventDefault(); + } + + 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; + } }; + 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!

@@ -30,6 +123,63 @@ const Luca = () => { 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.

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

Score: {score}

+
); };