main #4
1 changed files with 155 additions and 5 deletions
|
@ -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 (
|
||||
<div className="programmer-space luca">
|
||||
<h2>Luca's Space</h2>
|
||||
<p>Welcome, Luca! This is your programming space.</p>
|
||||
|
||||
{/* Button to count clicks */}
|
||||
<button onClick={handleClick} className="click-button">
|
||||
<button onClick={() => setClickCount(clickCount + 1)} className="click-button">
|
||||
Click me
|
||||
</button>
|
||||
<p>You've clicked the button {clickCount} times!</p>
|
||||
|
@ -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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Snake game */}
|
||||
<div
|
||||
className="snake-game"
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: WIDTH * CELL_SIZE,
|
||||
height: HEIGHT * CELL_SIZE,
|
||||
border: '1px solid black',
|
||||
marginTop: '20px',
|
||||
}}
|
||||
>
|
||||
{snake.map((segment, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: segment.x * CELL_SIZE,
|
||||
top: segment.y * CELL_SIZE,
|
||||
width: CELL_SIZE,
|
||||
height: CELL_SIZE,
|
||||
backgroundColor: 'green',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: food.x * CELL_SIZE,
|
||||
top: food.y * CELL_SIZE,
|
||||
width: CELL_SIZE,
|
||||
height: CELL_SIZE,
|
||||
backgroundColor: 'red',
|
||||
}}
|
||||
/>
|
||||
{gameOver && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
color: 'white',
|
||||
padding: '10px',
|
||||
borderRadius: '5px',
|
||||
}}
|
||||
>
|
||||
Game Over
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Score display */}
|
||||
<div className="score" style={{ marginTop: '20px', fontSize: '18px' }}>
|
||||
<p>Score: {score}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue