Skip to content

Commit d0629f5

Browse files
authored
Merge pull request #1184 from Drotum/Fibonacci-Game-Drotum-branch
Fibonacci Game for interactive learning
2 parents cb0c846 + 2d4936a commit d0629f5

File tree

7 files changed

+569
-0
lines changed

7 files changed

+569
-0
lines changed

FibonacciGame/Drotum/Readme.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Fibonacci Game
2+
3+
Welcome to the **Fibonacci Game**, an interactive and fun way to learn about the Fibonacci sequence! This game is designed to teach players the fundamentals of the Fibonacci sequence through engaging gameplay, suitable for all ages.
4+
5+
## Table of Contents
6+
- [About the Game](#about-the-game)
7+
- [How to Play](#how-to-play)
8+
- [Features](#features)
9+
- [Installation](#installation)
10+
- [Technologies Used](#technologies-used)
11+
- [Contributing](#contributing)
12+
- [License](#license)
13+
14+
## About the Game
15+
The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones, starting from 0 and 1. This game introduces players to the sequence through:
16+
- Interactive puzzles
17+
- Challenges that involve identifying or calculating Fibonacci numbers
18+
- Levels that progressively increase in difficulty
19+
20+
The goal is to make learning math concepts both fun and intuitive!
21+
22+
## How to Play
23+
1. **Start the Game**: Launch the game and choose a difficulty level to begin.
24+
2. **Understand the Task**: Click on the Fibonacci numbers in the correct order as they appear on the screen to advance to the next level.
25+
3. **Solve the Challenge**: Use your knowledge of the Fibonacci sequence to select the correct numbers before time runs out.
26+
4. **Progress**: Advance to higher levels as you successfully complete each challenge.
27+
5. **Restart Anytime**: Use the "Restart Game" button to reset and start over.
28+
29+
## Features
30+
- **Educational Gameplay**: Learn the Fibonacci sequence through practical and engaging challenges.
31+
- **Levels and Rewards**: Progress through levels with increasing complexity.
32+
- **User-Friendly Interface**: Simple and intuitive design for players of all ages.
33+
- **Difficulty Settings**: Choose from Easy, Medium, or Hard difficulty levels.
34+
- **Timer and Score Tracking**: Track your performance with a timer and score system.
35+
36+
## Technologies Used
37+
- **Frontend**: HTML, CSS, JavaScript
38+
- **Framework**: React
39+
- **Other Tools**: Node.js
40+
41+
42+
43+
---
44+
45+
Enjoy learning and mastering the Fibonacci sequence with our game! If you have any questions or feedback, feel free to reach out.
46+
47+
Happy Gaming! 🎮

FibonacciGame/Drotum/game.js

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
// Memoization for Fibonacci calculation
2+
const fibCache = {};
3+
function fibonacci(n) {
4+
if (n <= 1) return n;
5+
if (fibCache[n]) return fibCache[n];
6+
fibCache[n] = fibonacci(n - 1) + fibonacci(n - 2);
7+
return fibCache[n];
8+
}
9+
10+
let level = 1;
11+
let currentSequence = [];
12+
let clickedNumbers = [];
13+
let correctFibIndex = 0;
14+
let gameActive = true;
15+
let timerInterval;
16+
let timeLeft = 60; // Default time in seconds
17+
let gamePaused = false;
18+
const numbers = [];
19+
let startFromIndex = 5; // Will be randomized per level
20+
21+
// Difficulty settings
22+
const difficultySettings = {
23+
easy: { distractors: 5, time: 90 },
24+
medium: { distractors: 10, time: 60 },
25+
hard: { distractors: 20, time: 30 }
26+
};
27+
28+
// HTML Elements
29+
const gameBoard = document.getElementById('gameBoard');
30+
const levelDisplay = document.getElementById('levelDisplay');
31+
const messageDisplay = document.getElementById('message');
32+
const correctSequenceDisplay = document.getElementById('correctSequence');
33+
const timerDisplay = document.getElementById('timerDisplay');
34+
const pauseButton = document.getElementById('pauseButton');
35+
const difficultySelect = document.getElementById('difficulty');
36+
const leaderboardList = document.getElementById('leaderboardList');
37+
const restartButton = document.getElementById('restartButton');
38+
39+
// Sound Elements
40+
const correctSound = document.getElementById('correctSound');
41+
const incorrectSound = document.getElementById('incorrectSound');
42+
const levelUpSound = document.getElementById('levelUpSound');
43+
44+
// Leaderboard
45+
let leaderboard = JSON.parse(localStorage.getItem('fibLeaderboard')) || [];
46+
47+
// Function to update the leaderboard display
48+
function updateLeaderboard() {
49+
leaderboardList.innerHTML = '';
50+
leaderboard.forEach(entry => {
51+
const li = document.createElement('li');
52+
li.textContent = `Level ${entry.level} - Time: ${entry.time}s`;
53+
leaderboardList.appendChild(li);
54+
});
55+
}
56+
57+
// Function to add a new score to the leaderboard
58+
function addToLeaderboard(levelAchieved, timeTaken) {
59+
leaderboard.push({ level: levelAchieved, time: timeTaken });
60+
leaderboard.sort((a, b) => {
61+
if (b.level === a.level) return a.time - b.time;
62+
return b.level - a.level;
63+
});
64+
leaderboard = leaderboard.slice(0, 10);
65+
localStorage.setItem('fibLeaderboard', JSON.stringify(leaderboard));
66+
updateLeaderboard();
67+
}
68+
69+
// Function to generate a Fibonacci sequence for the level, starting from a specified number
70+
function generateFibonacciSequence(level, startFromIndex) {
71+
const sequence = [];
72+
for (let i = startFromIndex; i < startFromIndex + level + 5; i++) {
73+
sequence.push(fibonacci(i));
74+
}
75+
return sequence;
76+
}
77+
78+
// Function to generate non-Fibonacci numbers close to the Fibonacci sequence
79+
function generateNonFibonacciNumbers(count, fibNumbers) {
80+
const nonFib = [];
81+
while (nonFib.length < count) {
82+
const randomFib = fibNumbers[Math.floor(Math.random() * fibNumbers.length)];
83+
const offset = Math.floor(Math.random() * 10) - 5; // Random offset close to Fibonacci numbers
84+
const candidate = randomFib + offset;
85+
if (!fibNumbers.includes(candidate) && candidate > 0 && !nonFib.includes(candidate)) {
86+
nonFib.push(candidate);
87+
}
88+
}
89+
return nonFib;
90+
}
91+
92+
// Function to create number elements (static and non-overlapping)
93+
function createNumberElement(number, isFib = true, usedPositions) {
94+
const numberElement = document.createElement('div');
95+
numberElement.classList.add('number');
96+
numberElement.textContent = number;
97+
98+
const size = isFib ? (50 + Math.random() * 50) : (30 + Math.random() * 30);
99+
numberElement.style.width = `${size}px`;
100+
numberElement.style.height = numberElement.style.width;
101+
102+
let validPosition = false;
103+
let x, y;
104+
105+
// Find a position that doesn't overlap with others
106+
while (!validPosition) {
107+
x = Math.random() * 80; // 80% width of the game board
108+
y = Math.random() * 80; // 80% height of the game board
109+
validPosition = !usedPositions.some(pos => {
110+
const dx = pos.x - x;
111+
const dy = pos.y - y;
112+
return Math.sqrt(dx * dx + dy * dy) < 10; // Minimum distance of 10% to avoid overlap
113+
});
114+
}
115+
116+
numberElement.style.position = 'absolute';
117+
numberElement.style.left = `${x}%`;
118+
numberElement.style.top = `${y}%`;
119+
usedPositions.push({ x, y }); // Save the position
120+
121+
return numberElement;
122+
}
123+
124+
// Function to display Fibonacci and distractor numbers
125+
function displayNumbers() {
126+
const fibNumbers = currentSequence;
127+
const difficulty = difficultySelect.value;
128+
const distractors = generateNonFibonacciNumbers(difficultySettings[difficulty].distractors, fibNumbers);
129+
const usedPositions = [];
130+
131+
// Clear any existing numbers
132+
gameBoard.innerHTML = '';
133+
134+
// Generate Fibonacci numbers
135+
fibNumbers.forEach((number) => {
136+
const element = createNumberElement(number, true, usedPositions);
137+
element.addEventListener('click', () => handleNumberClick(number, element));
138+
gameBoard.appendChild(element);
139+
});
140+
141+
// Generate distractor numbers
142+
distractors.forEach((number) => {
143+
const element = createNumberElement(number, false, usedPositions);
144+
gameBoard.appendChild(element);
145+
});
146+
}
147+
148+
// Handle click on numbers
149+
function handleNumberClick(number, element) {
150+
if (!gameActive) return;
151+
152+
if (number === currentSequence[correctFibIndex]) {
153+
clickedNumbers.push(number);
154+
correctFibIndex++;
155+
correctSound.currentTime = 0;
156+
correctSound.play();
157+
correctSequenceDisplay.textContent = `Correct Sequence: ${clickedNumbers.join(', ')}`;
158+
gameBoard.removeChild(element);
159+
160+
if (clickedNumbers.length === currentSequence.length) {
161+
gameActive = false;
162+
clearInterval(timerInterval);
163+
levelUpSound.play();
164+
setTimeout(() => nextLevel(), 1000);
165+
}
166+
} else {
167+
incorrectSound.currentTime = 0;
168+
incorrectSound.play();
169+
messageDisplay.textContent = "Incorrect, try again!";
170+
}
171+
}
172+
173+
// Move to the next level
174+
function nextLevel() {
175+
addToLeaderboard(level, timeLeft);
176+
level++;
177+
levelDisplay.textContent = `Level: ${level}`;
178+
clickedNumbers = [];
179+
correctFibIndex = 0;
180+
const difficulty = difficultySelect.value;
181+
timeLeft = difficultySettings[difficulty].time;
182+
183+
// Randomize starting Fibonacci numbers for the sequence
184+
startFromIndex = Math.floor(Math.random() * 10) + 3; // Randomize between index 3 and 12
185+
currentSequence = generateFibonacciSequence(level, startFromIndex);
186+
187+
gameActive = true;
188+
correctSequenceDisplay.textContent = `Correct Sequence: ${currentSequence[0]}, ${currentSequence[1]}`;
189+
displayNumbers();
190+
resetTimer();
191+
}
192+
193+
// Timer functions
194+
function startTimer() {
195+
timerDisplay.textContent = `Time: ${timeLeft}s`;
196+
timerInterval = setInterval(() => {
197+
if (!gameActive || gamePaused) return;
198+
timeLeft--;
199+
timerDisplay.textContent = `Time: ${timeLeft}s`;
200+
if (timeLeft <= 0) {
201+
clearInterval(timerInterval);
202+
endGame();
203+
}
204+
}, 1000);
205+
}
206+
207+
function resetTimer() {
208+
clearInterval(timerInterval);
209+
startTimer();
210+
}
211+
212+
// Handle Pause/Resume Button
213+
pauseButton.addEventListener('click', () => {
214+
if (!gameActive) return;
215+
if (gamePaused) {
216+
gamePaused = false;
217+
pauseButton.textContent = "Pause";
218+
resetTimer();
219+
} else {
220+
gamePaused = true;
221+
pauseButton.textContent = "Resume";
222+
clearInterval(timerInterval);
223+
}
224+
});
225+
226+
// Handle Difficulty Change
227+
difficultySelect.addEventListener('change', () => {
228+
const difficulty = difficultySelect.value;
229+
timeLeft = difficultySettings[difficulty].time;
230+
if (gameActive && !gamePaused) {
231+
resetTimer();
232+
}
233+
});
234+
235+
// Handle game end
236+
function endGame() {
237+
gameActive = false;
238+
messageDisplay.textContent = "Time's up! Game Over.";
239+
restartButton.style.display = "block"; // Show the restart button
240+
}
241+
242+
// Handle restart button click
243+
restartButton.addEventListener('click', () => {
244+
restartButton.style.display = "none";
245+
startGame(true);
246+
updateLeaderboard();
247+
});
248+
249+
// Start the game
250+
function startGame(isRestart = false) {
251+
// Reset level and other state variables
252+
level = 1;
253+
const difficulty = difficultySelect.value;
254+
timeLeft = difficultySettings[difficulty].time;
255+
clickedNumbers = [];
256+
correctFibIndex = 0;
257+
gameActive = true;
258+
259+
// Randomize the Fibonacci sequence's start index and generate a new sequence
260+
startFromIndex = Math.floor(Math.random() * 10) + 3; // Randomize starting point
261+
currentSequence = generateFibonacciSequence(level, startFromIndex);
262+
263+
correctSequenceDisplay.textContent = `Correct Sequence: ${currentSequence[0]}, ${currentSequence[1]}`;
264+
displayNumbers();
265+
266+
if (isRestart) {
267+
resetTimer();
268+
}
269+
270+
if (!isRestart) {
271+
addToLeaderboard(level, timeLeft);
272+
}
273+
}
274+
275+
startGame();

FibonacciGame/Drotum/index.html

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Fibonacci Click Challenge</title>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
<!-- Game container -->
11+
<div class="game-container">
12+
<h1>Fibonacci Click Challenge</h1>
13+
<p>Click the Fibonacci numbers in the correct order to advance to the next stage!</p>
14+
15+
<div class="controls">
16+
<div id="levelDisplay" class="level-display">Level: 1</div>
17+
<div id="timerDisplay" class="timer-display">Time: 60s</div>
18+
<button id="pauseButton">Pause</button>
19+
<div class="difficulty-settings">
20+
<label for="difficulty">Difficulty:</label>
21+
<select id="difficulty">
22+
<option value="easy">Easy</option>
23+
<option value="medium" selected>Medium</option>
24+
<option value="hard">Hard</option>
25+
</select>
26+
</div>
27+
</div>
28+
29+
<div id="gameBoard" class="game-board">
30+
<!-- Floating numbers will appear here -->
31+
</div>
32+
33+
<div id="message" class="message"></div>
34+
35+
<div id="correctSequence" class="correct-sequence">Correct Sequence: </div>
36+
37+
<!-- Restart Button moved between Correct Sequence and Leaderboard -->
38+
<button id="restartButton" style="display: block; margin: 20px auto; padding: 10px 20px; font-size: 18px; background-color: #0097e6; color: white; border: none; border-radius: 5px; cursor: pointer;">
39+
Restart Game
40+
</button>
41+
42+
<div class="leaderboard">
43+
<h2>Leaderboard</h2>
44+
<ol id="leaderboardList">
45+
<!-- Leaderboard entries will be added here -->
46+
</ol>
47+
</div>
48+
</div>
49+
50+
<!-- Sound Effects -->
51+
<audio id="correctSound" src="sounds/correct.mp3"></audio>
52+
<audio id="incorrectSound" src="sounds/incorrect.mp3"></audio>
53+
<audio id="levelUpSound" src="sounds/levelup.mp3"></audio>
54+
55+
<script src="game.js"></script>
56+
</body>
57+
</html>
18.3 KB
Binary file not shown.
7.74 KB
Binary file not shown.
33.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)