init: initialize project - 2 games
This commit is contained in:
commit
4740d0003b
7 changed files with 1784 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.vscode/
|
||||
215
find-and-write/index.html
Normal file
215
find-and-write/index.html
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Classroom Word Search Game</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.23.5/babel.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="text/babel">
|
||||
const { useState, useEffect } = React;
|
||||
|
||||
function WordSearchGame() {
|
||||
const wordLists = {
|
||||
animals: ['elephant', 'giraffe', 'penguin', 'dolphin', 'kangaroo', 'octopus', 'butterfly', 'zebra'],
|
||||
colors: ['purple', 'orange', 'yellow', 'green', 'blue', 'red', 'brown', 'pink'],
|
||||
food: ['pizza', 'banana', 'cookie', 'apple', 'sandwich', 'pasta', 'carrot', 'burger'],
|
||||
school: ['pencil', 'eraser', 'notebook', 'teacher', 'student', 'library', 'classroom', 'homework'],
|
||||
// Arabic categories for beginners
|
||||
arabicAnimals: ['فيل', 'أسد', 'قطة', 'كلب', 'زرافة', 'فأر', 'سمكة', 'طائر'],
|
||||
arabicColors: ['أحمر', 'أزرق', 'أخضر', 'أصفر', 'أسود', 'أبيض', 'بني', 'برتقالي'],
|
||||
arabicNumbers: ['واحد', 'اثنان', 'ثلاثة', 'أربعة', 'خمسة', 'ستة', 'سبعة', 'ثمانية'],
|
||||
arabicGreetings: ['مرحبا', 'صباح الخير', 'مساء الخير', 'شكرا', 'عفوا', 'مع السلامة', 'كيف حالك', 'أنا بخير']
|
||||
};
|
||||
|
||||
const [category, setCategory] = useState('animals');
|
||||
const [isArabic, setIsArabic] = useState(false);
|
||||
const [displayedWords, setDisplayedWords] = useState([]);
|
||||
const [timer, setTimer] = useState(300);
|
||||
|
||||
const randomPosition = () => ({
|
||||
left: `${Math.random() * 70 + 15}%`,
|
||||
top: `${Math.random() * 50 + 20}%`, // Reduced vertical range to avoid bottom section
|
||||
transform: `rotate(${Math.random() * 360}deg)`
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// When language is toggled, update to appropriate category
|
||||
if (isArabic && !category.startsWith('arabic')) {
|
||||
setCategory('arabicAnimals');
|
||||
} else if (!isArabic && category.startsWith('arabic')) {
|
||||
setCategory('animals');
|
||||
}
|
||||
}, [isArabic]);
|
||||
|
||||
useEffect(() => {
|
||||
const words = wordLists[category].map((word, index) => ({
|
||||
id: index,
|
||||
text: word,
|
||||
...randomPosition()
|
||||
}));
|
||||
setDisplayedWords(words);
|
||||
}, [category]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setTimer((prev) => (prev > 0 ? prev - 1 : 0));
|
||||
}, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
// Reset timer when language changes
|
||||
useEffect(() => {
|
||||
setTimer(300);
|
||||
}, [isArabic]);
|
||||
|
||||
const changeCategory = () => {
|
||||
// Filter categories based on language selection
|
||||
const categories = Object.keys(wordLists).filter(cat =>
|
||||
isArabic ? cat.startsWith('arabic') : !cat.startsWith('arabic')
|
||||
);
|
||||
const currentIndex = categories.indexOf(category);
|
||||
const nextIndex = (currentIndex + 1) % categories.length;
|
||||
setCategory(categories[nextIndex]);
|
||||
setTimer(300);
|
||||
};
|
||||
|
||||
const toggleLanguage = () => {
|
||||
setIsArabic(!isArabic);
|
||||
// Set to first category of the selected language
|
||||
const categories = Object.keys(wordLists).filter(cat =>
|
||||
!isArabic ? cat.startsWith('arabic') : !cat.startsWith('arabic')
|
||||
);
|
||||
setCategory(categories[0]);
|
||||
setTimer(300);
|
||||
};
|
||||
|
||||
// Format category name for display
|
||||
const formatCategoryName = (cat) => {
|
||||
if (cat.startsWith('arabic')) {
|
||||
// Convert arabicAnimals to "Arabic Animals"
|
||||
return cat.replace('arabic', 'Arabic ').replace(/([A-Z])/g, ' $1').trim();
|
||||
}
|
||||
return cat;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-screen bg-gray-100 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 p-4 bg-white shadow-md flex justify-between items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-2xl">📚</span>
|
||||
<span className="text-2xl font-bold">Find and Write: {formatCategoryName(category)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={toggleLanguage}
|
||||
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
|
||||
>
|
||||
{isArabic ? "Switch to English" : "Switch to Arabic"}
|
||||
</button>
|
||||
<button
|
||||
onClick={changeCategory}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
Change Category
|
||||
</button>
|
||||
<div className="text-xl">
|
||||
Words to find: {wordLists[category].length}
|
||||
</div>
|
||||
<div className="text-xl">
|
||||
Time: {Math.floor(timer / 60)}:{(timer % 60).toString().padStart(2, '0')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-20 left-4 right-4 bg-yellow-100 p-4 rounded-lg shadow">
|
||||
<p className="text-lg">
|
||||
🤫 Silently find and write down as many {formatCategoryName(category)} as you can!
|
||||
Look carefully - words might be rotated!
|
||||
{isArabic && (
|
||||
<span className="block mt-2 text-gray-700">
|
||||
<strong>Beginner tip:</strong> Try to find and memorize these Arabic words. Check the help section at the bottom for learning tips!
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-32 relative w-full h-full">
|
||||
{displayedWords.map((word) => (
|
||||
<div
|
||||
key={word.id}
|
||||
className={`absolute font-bold select-none ${isArabic ? 'text-3xl' : 'text-4xl'} text-gray-700`}
|
||||
style={{
|
||||
left: word.left,
|
||||
top: word.top,
|
||||
transform: word.transform,
|
||||
direction: isArabic ? 'rtl' : 'ltr',
|
||||
fontFamily: isArabic ? "'Arial', 'Tahoma', sans-serif" : 'inherit'
|
||||
}}
|
||||
>
|
||||
{word.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{isArabic && (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-blue-100 p-2 shadow" style={{ maxHeight: '25vh', overflowY: 'auto' }}>
|
||||
<button
|
||||
className="absolute top-1 right-2 bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center text-xs"
|
||||
onClick={() => document.querySelector('.help-section').classList.toggle('hidden')}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<h3 className="text-lg font-bold text-center">Arabic Learning Guide</h3>
|
||||
<div className="help-section grid grid-cols-1 md:grid-cols-4 gap-2 text-sm mt-1">
|
||||
<div>
|
||||
<strong>Animals (الحيوانات):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>فيل - elephant</li>
|
||||
<li>أسد - lion</li>
|
||||
<li>قطة - cat</li>
|
||||
<li>كلب - dog</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Colors (الألوان):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>أحمر - red</li>
|
||||
<li>أزرق - blue</li>
|
||||
<li>أخضر - green</li>
|
||||
<li>أصفر - yellow</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Numbers (الأرقام):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>واحد - one</li>
|
||||
<li>اثنان - two</li>
|
||||
<li>ثلاثة - three</li>
|
||||
<li>أربعة - four</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Greetings (التحيات):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>مرحبا - hello</li>
|
||||
<li>شكرا - thank you</li>
|
||||
<li>مع السلامة - goodbye</li>
|
||||
<li>كيف حالك - how are you</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<WordSearchGame />, document.getElementById('root'));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
70
tictactoe/README.md
Normal file
70
tictactoe/README.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Educational Tic Tac Toe
|
||||
|
||||
A Tic Tac Toe game with an educational twist! Players must correctly answer questions to make their moves.
|
||||
|
||||
## Features
|
||||
|
||||
- Classic Tic Tac Toe gameplay
|
||||
- Educational questions that must be answered correctly to make a move
|
||||
- Support for both True/False and Multiple Choice questions
|
||||
- Full support for Arabic language
|
||||
- Different question categories: General Knowledge, Math, Science, and Language
|
||||
- Score tracking for multiple games
|
||||
- Responsive design that works on all devices
|
||||
|
||||
## How to Play
|
||||
|
||||
1. Open `index.html` in a web browser
|
||||
2. Players take turns clicking on empty cells
|
||||
3. When a cell is clicked, a question appears
|
||||
4. If the player answers correctly, they get to place their mark (X or O)
|
||||
5. If the player answers incorrectly, their turn is skipped
|
||||
6. The first player to get three marks in a row (horizontally, vertically, or diagonally) wins
|
||||
7. If all cells are filled without a winner, the game is a draw
|
||||
|
||||
## Game Settings
|
||||
|
||||
You can customize the game experience using the settings panel:
|
||||
|
||||
### Question Type
|
||||
- **True/False**: Simple true or false questions
|
||||
- **Multiple Choice**: Questions with multiple options
|
||||
|
||||
### Language
|
||||
- **English**: Questions and interface in English
|
||||
- **Arabic**: Questions and interface in Arabic (with RTL support)
|
||||
|
||||
### Category
|
||||
- **General Knowledge**: Various general knowledge questions
|
||||
- **Math**: Mathematical questions and problems
|
||||
- **Science**: Science-related questions
|
||||
- **Language**: Questions about language and vocabulary
|
||||
|
||||
## Running the Game
|
||||
|
||||
Simply open the `index.html` file in any modern web browser:
|
||||
|
||||
```
|
||||
firefox index.html
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
google-chrome index.html
|
||||
```
|
||||
|
||||
## Customizing Questions
|
||||
|
||||
You can add or modify questions by editing the `questions.js` file. The questions are organized by:
|
||||
- Language (english, arabic)
|
||||
- Category (general, math, science, language)
|
||||
- Type (truefalse, multiplechoice)
|
||||
|
||||
## Browser Compatibility
|
||||
|
||||
This game works in all modern browsers:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Safari
|
||||
- Edge
|
||||
598
tictactoe/game.js
Normal file
598
tictactoe/game.js
Normal file
|
|
@ -0,0 +1,598 @@
|
|||
// Educational Tic Tac Toe Game
|
||||
|
||||
// Game variables
|
||||
let currentPlayer = 'X';
|
||||
let gameBoard = ['', '', '', '', '', '', '', '', ''];
|
||||
let gameActive = true;
|
||||
let scores = { X: 0, O: 0 };
|
||||
let gameSettings = {
|
||||
questionType: 'multiplechoice',
|
||||
language: 'arabic',
|
||||
category: 'beginners', // Changed to beginners for new users
|
||||
timerSeconds: 5 // 5 seconds timer
|
||||
};
|
||||
|
||||
// Timer variables
|
||||
let timerInterval = null;
|
||||
let timeLeft = 0;
|
||||
|
||||
// DOM Elements
|
||||
const cells = document.querySelectorAll('.cell');
|
||||
const player1Element = document.getElementById('player1');
|
||||
const player2Element = document.getElementById('player2');
|
||||
const resetButton = document.getElementById('resetBtn');
|
||||
const newGameButton = document.getElementById('newGameBtn');
|
||||
const questionModal = document.getElementById('questionModal');
|
||||
const questionText = document.getElementById('questionText');
|
||||
const answerOptions = document.getElementById('answerOptions');
|
||||
const feedback = document.getElementById('feedback');
|
||||
const gameOverModal = document.getElementById('gameOverModal');
|
||||
const gameResult = document.getElementById('gameResult');
|
||||
const playAgainButton = document.getElementById('playAgainBtn');
|
||||
const applySettingsButton = document.getElementById('applySettingsBtn');
|
||||
|
||||
// Timer elements
|
||||
const timerContainer = document.getElementById('timerContainer');
|
||||
const timerBar = document.getElementById('timerBar');
|
||||
const timerText = document.getElementById('timerText');
|
||||
|
||||
// Settings elements
|
||||
const questionTypeSelect = document.getElementById('questionType');
|
||||
const questionLanguageSelect = document.getElementById('questionLanguage');
|
||||
const questionCategorySelect = document.getElementById('questionCategory');
|
||||
const questionTimerSelect = document.getElementById('questionTimer');
|
||||
|
||||
// Current question and selected cell
|
||||
let currentQuestion = null;
|
||||
let selectedCellIndex = null;
|
||||
let questionPlayer = null; // Track which player clicked the cell
|
||||
|
||||
// Initialize the game
|
||||
function initGame() {
|
||||
// Add event listeners to cells
|
||||
cells.forEach(cell => {
|
||||
cell.addEventListener('click', () => handleCellClick(parseInt(cell.dataset.index)));
|
||||
});
|
||||
|
||||
// Add event listeners to buttons
|
||||
resetButton.addEventListener('click', resetGame);
|
||||
newGameButton.addEventListener('click', newGame);
|
||||
playAgainButton.addEventListener('click', newGame);
|
||||
applySettingsButton.addEventListener('click', applySettings);
|
||||
|
||||
// Add event listener to language select to update categories
|
||||
questionLanguageSelect.addEventListener('change', updateCategoryOptions);
|
||||
|
||||
// Initialize settings from selects
|
||||
questionTypeSelect.value = gameSettings.questionType;
|
||||
questionLanguageSelect.value = gameSettings.language;
|
||||
questionCategorySelect.value = gameSettings.category;
|
||||
questionTimerSelect.value = gameSettings.timerSeconds;
|
||||
|
||||
// Update category options based on selected language
|
||||
updateCategoryOptions();
|
||||
|
||||
// Set up the initial game state
|
||||
updateGameDisplay();
|
||||
|
||||
// Update UI language immediately based on default settings
|
||||
updateUILanguage();
|
||||
|
||||
// Set document direction for Arabic
|
||||
if (gameSettings.language === 'arabic') {
|
||||
document.documentElement.dir = 'rtl';
|
||||
}
|
||||
}
|
||||
|
||||
// Update category options based on selected language
|
||||
function updateCategoryOptions() {
|
||||
const language = questionLanguageSelect.value;
|
||||
|
||||
// Clear existing options
|
||||
questionCategorySelect.innerHTML = '';
|
||||
|
||||
if (language === 'english') {
|
||||
// Add English categories
|
||||
const mathOption = document.createElement('option');
|
||||
mathOption.value = 'math';
|
||||
mathOption.textContent = 'Mathematics';
|
||||
questionCategorySelect.appendChild(mathOption);
|
||||
|
||||
// Set default for English
|
||||
questionCategorySelect.value = 'math';
|
||||
} else if (language === 'arabic') {
|
||||
// Add Arabic categories
|
||||
const islamicOption = document.createElement('option');
|
||||
islamicOption.value = 'islamic';
|
||||
islamicOption.textContent = 'Islamic';
|
||||
questionCategorySelect.appendChild(islamicOption);
|
||||
|
||||
const beginnersOption = document.createElement('option');
|
||||
beginnersOption.value = 'beginners';
|
||||
beginnersOption.textContent = 'Beginners Arabic';
|
||||
questionCategorySelect.appendChild(beginnersOption);
|
||||
|
||||
// Set default for Arabic
|
||||
questionCategorySelect.value = 'beginners';
|
||||
}
|
||||
}
|
||||
|
||||
// Handle cell click
|
||||
function handleCellClick(index) {
|
||||
// Ignore clicks if game is not active or cell is already filled
|
||||
if (!gameActive || gameBoard[index] !== '') return;
|
||||
|
||||
// Store the selected cell index and current player
|
||||
selectedCellIndex = index;
|
||||
questionPlayer = currentPlayer; // Store which player clicked the cell
|
||||
|
||||
// Get a random question based on current settings
|
||||
currentQuestion = getRandomQuestion(
|
||||
gameSettings.language,
|
||||
gameSettings.category,
|
||||
gameSettings.questionType
|
||||
);
|
||||
|
||||
// Display the question
|
||||
showQuestion(currentQuestion);
|
||||
}
|
||||
|
||||
// Show question modal
|
||||
function showQuestion(question) {
|
||||
// Set the question text with appropriate language attribute
|
||||
questionText.textContent = question.question;
|
||||
if (gameSettings.language === 'arabic') {
|
||||
questionText.setAttribute('lang', 'ar');
|
||||
} else {
|
||||
questionText.removeAttribute('lang');
|
||||
}
|
||||
|
||||
// Clear previous answer options and feedback
|
||||
answerOptions.innerHTML = '';
|
||||
feedback.textContent = '';
|
||||
feedback.className = 'feedback';
|
||||
|
||||
// Create answer options based on question type
|
||||
if (gameSettings.questionType === 'truefalse') {
|
||||
// True/False question
|
||||
const trueOption = document.createElement('div');
|
||||
trueOption.className = 'answer-option';
|
||||
trueOption.textContent = gameSettings.language === 'arabic' ? 'صحيح' : 'True';
|
||||
trueOption.addEventListener('click', () => checkAnswer(true));
|
||||
|
||||
const falseOption = document.createElement('div');
|
||||
falseOption.className = 'answer-option';
|
||||
falseOption.textContent = gameSettings.language === 'arabic' ? 'خطأ' : 'False';
|
||||
falseOption.addEventListener('click', () => checkAnswer(false));
|
||||
|
||||
answerOptions.appendChild(trueOption);
|
||||
answerOptions.appendChild(falseOption);
|
||||
} else {
|
||||
// Multiple choice question
|
||||
|
||||
// Create a shuffled array of indices
|
||||
const originalAnswer = question.answer;
|
||||
const indices = Array.from({ length: question.options.length }, (_, i) => i);
|
||||
const shuffledIndices = shuffleArray([...indices]);
|
||||
|
||||
// Create a mapping from shuffled positions to original positions
|
||||
const shuffleMap = {};
|
||||
shuffledIndices.forEach((originalIndex, newIndex) => {
|
||||
shuffleMap[newIndex] = originalIndex;
|
||||
});
|
||||
|
||||
// Display options in shuffled order
|
||||
shuffledIndices.forEach((originalIndex, newIndex) => {
|
||||
const optionElement = document.createElement('div');
|
||||
optionElement.className = 'answer-option';
|
||||
optionElement.textContent = question.options[originalIndex];
|
||||
if (gameSettings.language === 'arabic') {
|
||||
optionElement.setAttribute('lang', 'ar');
|
||||
}
|
||||
// When clicked, map back to the original index for checking
|
||||
optionElement.addEventListener('click', () => checkAnswer(originalIndex, shuffleMap));
|
||||
answerOptions.appendChild(optionElement);
|
||||
});
|
||||
}
|
||||
|
||||
// Show the modal
|
||||
questionModal.classList.add('show');
|
||||
|
||||
// Setup timer if enabled
|
||||
if (gameSettings.timerSeconds > 0) {
|
||||
// Show timer container
|
||||
timerContainer.style.display = 'block';
|
||||
|
||||
// Reset timer
|
||||
timeLeft = gameSettings.timerSeconds;
|
||||
updateTimerDisplay();
|
||||
|
||||
// Clear any existing timer
|
||||
if (timerInterval) {
|
||||
clearInterval(timerInterval);
|
||||
}
|
||||
|
||||
// Start the timer
|
||||
timerInterval = setInterval(() => {
|
||||
timeLeft--;
|
||||
updateTimerDisplay();
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
// Time's up
|
||||
clearInterval(timerInterval);
|
||||
timeOut();
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
// Hide timer if disabled
|
||||
timerContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Update the timer display
|
||||
function updateTimerDisplay() {
|
||||
// Update text
|
||||
timerText.textContent = `${timeLeft}s`;
|
||||
|
||||
// Update progress bar
|
||||
const percentage = (timeLeft / gameSettings.timerSeconds) * 100;
|
||||
timerBar.style.width = `${percentage}%`;
|
||||
|
||||
// Change color based on time left
|
||||
timerBar.className = 'timer-bar';
|
||||
if (timeLeft <= Math.floor(gameSettings.timerSeconds / 3)) {
|
||||
timerBar.classList.add('danger');
|
||||
} else if (timeLeft <= Math.floor(gameSettings.timerSeconds / 2)) {
|
||||
timerBar.classList.add('warning');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle time out
|
||||
function timeOut() {
|
||||
// Show feedback
|
||||
feedback.textContent = gameSettings.language === 'arabic'
|
||||
? 'انتهى الوقت!'
|
||||
: 'Time\'s up!';
|
||||
feedback.classList.add('incorrect');
|
||||
|
||||
// Switch players after a delay
|
||||
setTimeout(() => {
|
||||
hideQuestionModal();
|
||||
switchPlayer();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
// Check the answer
|
||||
function checkAnswer(userAnswer, shuffleMap = null) {
|
||||
// Clear the timer if it's running
|
||||
if (timerInterval) {
|
||||
clearInterval(timerInterval);
|
||||
timerInterval = null;
|
||||
}
|
||||
|
||||
// Get all answer options
|
||||
const options = document.querySelectorAll('.answer-option');
|
||||
|
||||
// Determine if the answer is correct
|
||||
let isCorrect = false;
|
||||
|
||||
if (gameSettings.questionType === 'truefalse') {
|
||||
isCorrect = userAnswer === currentQuestion.answer;
|
||||
|
||||
// Highlight the selected option
|
||||
options[userAnswer ? 0 : 1].classList.add('selected');
|
||||
|
||||
// Highlight the correct option
|
||||
options[currentQuestion.answer ? 0 : 1].classList.add('correct');
|
||||
|
||||
// If wrong, highlight as incorrect
|
||||
if (!isCorrect) {
|
||||
options[userAnswer ? 0 : 1].classList.add('incorrect');
|
||||
}
|
||||
} else {
|
||||
isCorrect = userAnswer === currentQuestion.answer;
|
||||
|
||||
// Find the positions in the shuffled array
|
||||
let selectedPosition = -1;
|
||||
let correctPosition = -1;
|
||||
|
||||
if (shuffleMap) {
|
||||
// Find the position of the selected answer in the shuffled array
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if (shuffleMap[i] === userAnswer) {
|
||||
selectedPosition = i;
|
||||
}
|
||||
if (shuffleMap[i] === currentQuestion.answer) {
|
||||
correctPosition = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no shuffle map (shouldn't happen), use original positions
|
||||
selectedPosition = userAnswer;
|
||||
correctPosition = currentQuestion.answer;
|
||||
}
|
||||
|
||||
// Highlight the selected option
|
||||
if (selectedPosition >= 0 && selectedPosition < options.length) {
|
||||
options[selectedPosition].classList.add('selected');
|
||||
}
|
||||
|
||||
// Highlight the correct option
|
||||
if (correctPosition >= 0 && correctPosition < options.length) {
|
||||
options[correctPosition].classList.add('correct');
|
||||
}
|
||||
|
||||
// If wrong, highlight as incorrect
|
||||
if (!isCorrect && selectedPosition >= 0 && selectedPosition < options.length) {
|
||||
options[selectedPosition].classList.add('incorrect');
|
||||
}
|
||||
}
|
||||
|
||||
// Show feedback
|
||||
feedback.textContent = isCorrect
|
||||
? (gameSettings.language === 'arabic' ? 'إجابة صحيحة!' : 'Correct!')
|
||||
: (gameSettings.language === 'arabic' ? 'إجابة خاطئة!' : 'Incorrect!');
|
||||
feedback.classList.add(isCorrect ? 'correct' : 'incorrect');
|
||||
|
||||
// Show explanation if available
|
||||
if (currentQuestion.explanation) {
|
||||
setTimeout(() => {
|
||||
feedback.textContent += ' ' + currentQuestion.explanation;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// If correct, make the move after a short delay
|
||||
if (isCorrect) {
|
||||
setTimeout(() => {
|
||||
// Make sure we're using the player who clicked the cell
|
||||
if (currentPlayer !== questionPlayer) {
|
||||
// If the player has changed, switch back to the original player
|
||||
currentPlayer = questionPlayer;
|
||||
|
||||
// Update the active player display
|
||||
player1Element.classList.toggle('active', currentPlayer === 'X');
|
||||
player2Element.classList.toggle('active', currentPlayer === 'O');
|
||||
}
|
||||
|
||||
makeMove(selectedCellIndex);
|
||||
hideQuestionModal();
|
||||
}, 1500);
|
||||
} else {
|
||||
// If incorrect, close the modal after a delay and switch players
|
||||
setTimeout(() => {
|
||||
hideQuestionModal();
|
||||
|
||||
// Only switch if the current player is still the one who clicked
|
||||
if (currentPlayer === questionPlayer) {
|
||||
switchPlayer();
|
||||
}
|
||||
|
||||
// Reset the question player
|
||||
questionPlayer = null;
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the question modal
|
||||
function hideQuestionModal() {
|
||||
// Clear the timer if it's running
|
||||
if (timerInterval) {
|
||||
clearInterval(timerInterval);
|
||||
timerInterval = null;
|
||||
}
|
||||
|
||||
questionModal.classList.remove('show');
|
||||
}
|
||||
|
||||
// Make a move on the board
|
||||
function makeMove(index) {
|
||||
// Update the game board
|
||||
gameBoard[index] = currentPlayer;
|
||||
|
||||
// Update the cell display
|
||||
cells[index].textContent = currentPlayer;
|
||||
cells[index].classList.add(currentPlayer.toLowerCase());
|
||||
|
||||
// Check for win or draw
|
||||
if (checkWin()) {
|
||||
endGame(false);
|
||||
} else if (checkDraw()) {
|
||||
endGame(true);
|
||||
} else {
|
||||
// Switch players
|
||||
switchPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
// Switch the current player
|
||||
function switchPlayer() {
|
||||
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
|
||||
|
||||
// Update the active player display
|
||||
player1Element.classList.toggle('active');
|
||||
player2Element.classList.toggle('active');
|
||||
}
|
||||
|
||||
// Check if the current player has won
|
||||
function checkWin() {
|
||||
const winPatterns = [
|
||||
[0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
|
||||
[0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
|
||||
[0, 4, 8], [2, 4, 6] // Diagonals
|
||||
];
|
||||
|
||||
for (const pattern of winPatterns) {
|
||||
const [a, b, c] = pattern;
|
||||
if (gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c]) {
|
||||
// Highlight the winning cells
|
||||
cells[a].classList.add('highlight');
|
||||
cells[b].classList.add('highlight');
|
||||
cells[c].classList.add('highlight');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the game is a draw
|
||||
function checkDraw() {
|
||||
return gameBoard.every(cell => cell !== '');
|
||||
}
|
||||
|
||||
// End the game
|
||||
function endGame(isDraw) {
|
||||
gameActive = false;
|
||||
|
||||
if (!isDraw) {
|
||||
// Update scores
|
||||
scores[currentPlayer]++;
|
||||
document.querySelector(`#player${currentPlayer === 'X' ? '1' : '2'} .player-score`).textContent = scores[currentPlayer];
|
||||
|
||||
// Show game over message
|
||||
gameResult.textContent = gameSettings.language === 'arabic'
|
||||
? `اللاعب ${currentPlayer} فاز!`
|
||||
: `Player ${currentPlayer} wins!`;
|
||||
} else {
|
||||
// Show draw message
|
||||
gameResult.textContent = gameSettings.language === 'arabic' ? 'تعادل!' : 'It\'s a draw!';
|
||||
}
|
||||
|
||||
// Show game over modal
|
||||
setTimeout(() => {
|
||||
gameOverModal.classList.add('show');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Reset the current game
|
||||
function resetGame() {
|
||||
// Clear the board
|
||||
gameBoard = ['', '', '', '', '', '', '', '', ''];
|
||||
gameActive = true;
|
||||
currentPlayer = 'X';
|
||||
|
||||
// Reset the UI
|
||||
cells.forEach(cell => {
|
||||
cell.textContent = '';
|
||||
cell.className = 'cell';
|
||||
});
|
||||
|
||||
player1Element.classList.add('active');
|
||||
player2Element.classList.remove('active');
|
||||
|
||||
// Clear any active timers
|
||||
if (timerInterval) {
|
||||
clearInterval(timerInterval);
|
||||
timerInterval = null;
|
||||
}
|
||||
|
||||
// Hide modals
|
||||
questionModal.classList.remove('show');
|
||||
gameOverModal.classList.remove('show');
|
||||
}
|
||||
|
||||
// Start a new game (reset game and scores)
|
||||
function newGame() {
|
||||
// Reset scores
|
||||
scores = { X: 0, O: 0 };
|
||||
document.querySelector('#player1 .player-score').textContent = '0';
|
||||
document.querySelector('#player2 .player-score').textContent = '0';
|
||||
|
||||
// Reset the game
|
||||
resetGame();
|
||||
}
|
||||
|
||||
// Apply new settings
|
||||
function applySettings() {
|
||||
gameSettings.questionType = questionTypeSelect.value;
|
||||
gameSettings.language = questionLanguageSelect.value;
|
||||
gameSettings.category = questionCategorySelect.value;
|
||||
gameSettings.timerSeconds = parseInt(questionTimerSelect.value);
|
||||
|
||||
// Validate language-category combination
|
||||
// Make sure the selected category exists for the selected language
|
||||
if (gameSettings.language === 'english' && gameSettings.category !== 'math') {
|
||||
// For English, only math category is available
|
||||
gameSettings.category = 'math';
|
||||
questionCategorySelect.value = 'math';
|
||||
} else if (gameSettings.language === 'arabic' &&
|
||||
(gameSettings.category !== 'islamic' && gameSettings.category !== 'beginners')) {
|
||||
// For Arabic, only islamic and beginners categories are available
|
||||
gameSettings.category = 'beginners';
|
||||
questionCategorySelect.value = 'beginners';
|
||||
}
|
||||
|
||||
// Update UI language if needed
|
||||
updateUILanguage();
|
||||
|
||||
// Start a new game with new settings
|
||||
newGame();
|
||||
}
|
||||
|
||||
// Update UI language based on selected language
|
||||
function updateUILanguage() {
|
||||
const isArabic = gameSettings.language === 'arabic';
|
||||
|
||||
// Update document direction
|
||||
document.documentElement.dir = isArabic ? 'rtl' : 'ltr';
|
||||
|
||||
// Update button texts
|
||||
resetButton.textContent = isArabic ? 'إعادة اللعبة' : 'Reset Game';
|
||||
newGameButton.textContent = isArabic ? 'لعبة جديدة' : 'New Game';
|
||||
playAgainButton.textContent = isArabic ? 'العب مرة أخرى' : 'Play Again';
|
||||
applySettingsButton.textContent = isArabic ? 'تطبيق الإعدادات' : 'Apply Settings';
|
||||
|
||||
// Update headings
|
||||
document.querySelector('h1').textContent = isArabic ? 'لعبة تيك تاك تو التعليمية' : 'Educational Tic Tac Toe';
|
||||
document.querySelector('.settings h3').textContent = isArabic ? 'إعدادات اللعبة' : 'Game Settings';
|
||||
document.querySelector('.used-words-container h3').textContent = isArabic ? 'الكلمات المستخدمة:' : 'Selected Words:';
|
||||
|
||||
// Update player names
|
||||
document.querySelector('#player1 .player-name').textContent = isArabic ? 'اللاعب 1' : 'Player 1';
|
||||
document.querySelector('#player2 .player-name').textContent = isArabic ? 'اللاعب 2' : 'Player 2';
|
||||
|
||||
// Update settings labels
|
||||
const labels = document.querySelectorAll('.setting-group label');
|
||||
if (isArabic) {
|
||||
labels[0].textContent = 'نوع السؤال:';
|
||||
labels[1].textContent = 'اللغة:';
|
||||
labels[2].textContent = 'الفئة:';
|
||||
labels[3].textContent = 'الوقت المحدد (ثواني):';
|
||||
} else {
|
||||
labels[0].textContent = 'Question Type:';
|
||||
labels[1].textContent = 'Language:';
|
||||
labels[2].textContent = 'Category:';
|
||||
labels[3].textContent = 'Time Limit (seconds):';
|
||||
}
|
||||
|
||||
// Update modal texts
|
||||
document.querySelector('#questionModal h2').textContent = isArabic
|
||||
? 'أجب على السؤال لإجراء حركتك'
|
||||
: 'Answer the question to make your move';
|
||||
}
|
||||
|
||||
// Update the game display
|
||||
function updateGameDisplay() {
|
||||
// Update UI language
|
||||
updateUILanguage();
|
||||
|
||||
// Update player scores
|
||||
document.querySelector('#player1 .player-score').textContent = scores.X;
|
||||
document.querySelector('#player2 .player-score').textContent = scores.O;
|
||||
|
||||
// Update active player
|
||||
player1Element.classList.toggle('active', currentPlayer === 'X');
|
||||
player2Element.classList.toggle('active', currentPlayer === 'O');
|
||||
}
|
||||
|
||||
// Utility function to shuffle an array (Fisher-Yates algorithm)
|
||||
function shuffleArray(array) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Initialize the game when the page loads
|
||||
window.addEventListener('load', initGame);
|
||||
109
tictactoe/index.html
Normal file
109
tictactoe/index.html
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Educational Tic Tac Toe</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Educational Tic Tac Toe</h1>
|
||||
|
||||
<div class="game-info">
|
||||
<div class="player-info">
|
||||
<div id="player1" class="player active">
|
||||
<span class="player-symbol">X</span>
|
||||
<span class="player-name">Player 1</span>
|
||||
<span class="player-score">0</span>
|
||||
</div>
|
||||
<div id="player2" class="player">
|
||||
<span class="player-symbol">O</span>
|
||||
<span class="player-name">Player 2</span>
|
||||
<span class="player-score">0</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="game-controls">
|
||||
<button id="resetBtn">Reset Game</button>
|
||||
<button id="newGameBtn">New Game</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="game-board" id="gameBoard">
|
||||
<div class="cell" data-index="0"></div>
|
||||
<div class="cell" data-index="1"></div>
|
||||
<div class="cell" data-index="2"></div>
|
||||
<div class="cell" data-index="3"></div>
|
||||
<div class="cell" data-index="4"></div>
|
||||
<div class="cell" data-index="5"></div>
|
||||
<div class="cell" data-index="6"></div>
|
||||
<div class="cell" data-index="7"></div>
|
||||
<div class="cell" data-index="8"></div>
|
||||
</div>
|
||||
|
||||
<div id="questionModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h2>Answer the question to make your move</h2>
|
||||
<div id="timerContainer" class="timer-container">
|
||||
<div id="timerBar" class="timer-bar"></div>
|
||||
<div id="timerText" class="timer-text"></div>
|
||||
</div>
|
||||
<div id="questionText" class="question-text"></div>
|
||||
|
||||
<div id="answerOptions" class="answer-options">
|
||||
<!-- Answer options will be inserted here dynamically -->
|
||||
</div>
|
||||
|
||||
<div id="feedback" class="feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="gameOverModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<h2 id="gameResult">Game Over</h2>
|
||||
<button id="playAgainBtn">Play Again</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings">
|
||||
<h3>Game Settings</h3>
|
||||
<div class="setting-group">
|
||||
<label for="questionType">Question Type:</label>
|
||||
<select id="questionType">
|
||||
<option value="truefalse">True/False</option>
|
||||
<option value="multiplechoice" selected>Multiple Choice</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="setting-group">
|
||||
<label for="questionLanguage">Language:</label>
|
||||
<select id="questionLanguage">
|
||||
<option value="english">English</option>
|
||||
<option value="arabic" selected>Arabic</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="setting-group">
|
||||
<label for="questionCategory">Category:</label>
|
||||
<select id="questionCategory">
|
||||
<option value="math">Mathematics</option>
|
||||
<option value="islamic" selected>Islamic</option>
|
||||
<option value="beginners">Beginners Arabic</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="setting-group">
|
||||
<label for="questionTimer">Time Limit (seconds):</label>
|
||||
<select id="questionTimer">
|
||||
<option value="0">No Limit</option>
|
||||
<option value="5" selected>5 Seconds</option>
|
||||
<option value="10">10 Seconds</option>
|
||||
<option value="15">15 Seconds</option>
|
||||
<option value="30">30 Seconds</option>
|
||||
</select>
|
||||
</div>
|
||||
<button id="applySettingsBtn">Apply Settings</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="questions.js"></script>
|
||||
<script src="game.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
439
tictactoe/questions.js
Normal file
439
tictactoe/questions.js
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
// Questions database for the Educational Tic Tac Toe game
|
||||
// Organized by language, category, and question type
|
||||
|
||||
const questionsDB = {
|
||||
english: {
|
||||
math: {
|
||||
truefalse: [
|
||||
{
|
||||
question: "The sum of angles in a triangle is 180 degrees.",
|
||||
answer: true,
|
||||
explanation: "In Euclidean geometry, the sum of the angles in any triangle is 180 degrees."
|
||||
},
|
||||
{
|
||||
question: "Pi (π) is exactly equal to 22/7.",
|
||||
answer: false,
|
||||
explanation: "22/7 is just an approximation of pi. Pi is an irrational number."
|
||||
},
|
||||
{
|
||||
question: "Any number raised to the power of 0 equals 1.",
|
||||
answer: true,
|
||||
explanation: "By definition, any non-zero number raised to the power of 0 equals 1."
|
||||
},
|
||||
{
|
||||
question: "The square root of 4 is 2.",
|
||||
answer: true,
|
||||
explanation: "The square root of 4 is 2 because 2 × 2 = 4."
|
||||
},
|
||||
{
|
||||
question: "There are 13 prime numbers less than 40.",
|
||||
answer: false,
|
||||
explanation: "There are 12 prime numbers less than 40: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, and 37."
|
||||
}
|
||||
],
|
||||
multiplechoice: [
|
||||
{
|
||||
question: "What is 7 × 8?",
|
||||
options: ["54", "56", "64", "72"],
|
||||
answer: 1,
|
||||
explanation: "7 × 8 = 56"
|
||||
},
|
||||
{
|
||||
question: "Which of these is a prime number?",
|
||||
options: ["15", "21", "27", "29"],
|
||||
answer: 3,
|
||||
explanation: "29 is a prime number because it is only divisible by 1 and itself."
|
||||
},
|
||||
{
|
||||
question: "What is the area of a square with sides of length 5?",
|
||||
options: ["10", "20", "25", "30"],
|
||||
answer: 2,
|
||||
explanation: "The area of a square is side length squared: 5² = 25"
|
||||
},
|
||||
{
|
||||
question: "If x + 5 = 12, what is x?",
|
||||
options: ["5", "7", "12", "17"],
|
||||
answer: 1,
|
||||
explanation: "x + 5 = 12, so x = 12 - 5 = 7"
|
||||
},
|
||||
{
|
||||
question: "What is the next number in the sequence: 2, 4, 8, 16, ...?",
|
||||
options: ["24", "32", "36", "64"],
|
||||
answer: 1,
|
||||
explanation: "Each number is doubled to get the next number. 16 × 2 = 32"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
arabic: {
|
||||
islamic: {
|
||||
multiplechoice: [
|
||||
{
|
||||
question: "س: من هو النبي محمد ﷺ؟",
|
||||
options: [
|
||||
"هو محمد بن عبد الله بن عبد المطلب، آخر الأنبياء والمرسلين",
|
||||
"هو عيسى بن مريم، نبي من أنبياء الله",
|
||||
"هو موسى بن عمران، كليم الله",
|
||||
"هو إبراهيم الخليل، أبو الأنبياء"
|
||||
],
|
||||
answer: 0,
|
||||
explanation: "ج: هو محمد بن عبد الله بن عبد المطلب، آخر الأنبياء والمرسلين"
|
||||
},
|
||||
{
|
||||
question: "س: متى ولد النبي ﷺ؟",
|
||||
options: [
|
||||
"ولد يوم الاثنين 12 ربيع الأول في عام الفيل (حوالي سنة 571 ميلادية)",
|
||||
"ولد يوم الجمعة 17 رمضان (حوالي سنة 570 ميلادية)",
|
||||
"ولد يوم الأربعاء 10 محرم (حوالي سنة 569 ميلادية)",
|
||||
"ولد يوم السبت 25 شوال (حوالي سنة 572 ميلادية)"
|
||||
],
|
||||
answer: 0,
|
||||
explanation: "ج: ولد يوم الاثنين 12 ربيع الأول في عام الفيل (حوالي سنة 571 ميلادية)"
|
||||
},
|
||||
{
|
||||
question: "س: لماذا سمي النبي ﷺ بالصادق الأمين؟",
|
||||
options: [
|
||||
"لأنه كان معروفًا بالصدق والأمانة بين الناس قبل البعثة",
|
||||
"لأنه كان يحب الصدق ويكره الكذب",
|
||||
"لأن قريش أطلقت عليه هذا اللقب بعد الهجرة",
|
||||
"لأنه كان يأمر الناس بالصدق والأمانة"
|
||||
],
|
||||
answer: 0,
|
||||
explanation: "ج: لأنه كان معروفًا بالصدق والأمانة بين الناس قبل البعثة."
|
||||
},
|
||||
{
|
||||
question: "س: كم كان عمر النبي ﷺ عندما نزل عليه الوحي؟",
|
||||
options: [
|
||||
"30 سنة",
|
||||
"35 سنة",
|
||||
"40 سنة",
|
||||
"45 سنة"
|
||||
],
|
||||
answer: 2,
|
||||
explanation: "ج: كان عمره 40 سنة"
|
||||
},
|
||||
{
|
||||
question: "س: أين نزل أول وحي على النبي ﷺ؟",
|
||||
options: [
|
||||
"في المسجد الحرام",
|
||||
"في غار حراء بمكة",
|
||||
"في بيته",
|
||||
"في المدينة المنورة"
|
||||
],
|
||||
answer: 1,
|
||||
explanation: "ج: في غار حراء بمكة"
|
||||
},
|
||||
{
|
||||
question: "س: ما هي أول آية نزلت على النبي ﷺ؟",
|
||||
options: [
|
||||
"﴿اقْرَأْ بِاسْمِ رَبِّكَ الَّذِي خَلَقَ﴾",
|
||||
"﴿بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ﴾",
|
||||
"﴿الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ﴾",
|
||||
"﴿يَا أَيُّهَا الْمُدَّثِّرُ﴾"
|
||||
],
|
||||
answer: 0,
|
||||
explanation: "ج: ﴿اقْرَأْ بِاسْمِ رَبِّكَ الَّذِي خَلَقَ﴾ (سورة العلق:1)."
|
||||
}
|
||||
]
|
||||
},
|
||||
beginners: {
|
||||
truefalse: [
|
||||
{
|
||||
question: "كتاب = boek (Nederlands) / book (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! كتاب betekent 'boek' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "قلم = tafel (Nederlands) / table (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, قلم betekent 'pen' in het Nederlands. 'Tafel' is طاولة in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "باب = deur (Nederlands) / door (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! باب betekent 'deur' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "ماء = vuur (Nederlands) / fire (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, ماء betekent 'water' in het Nederlands. 'Vuur' is نار in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "شمس = zon (Nederlands) / sun (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! شمس betekent 'zon' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "طعام = eten (Nederlands) / food (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! طعام betekent 'eten' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "يد = voet (Nederlands) / foot (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, يد betekent 'hand' in het Nederlands. 'Voet' is قدم in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "قطة = kat (Nederlands) / cat (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! قطة betekent 'kat' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "عين = oog (Nederlands) / eye (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! عين betekent 'oog' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "أنف = oor (Nederlands) / ear (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, أنف betekent 'neus' in het Nederlands. 'Oor' is أذن in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "فم = mond (Nederlands) / mouth (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! فم betekent 'mond' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "رأس = haar (Nederlands) / hair (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, رأس betekent 'hoofd' in het Nederlands. 'Haar' is شعر in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "قدم = voet (Nederlands) / foot (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! قدم betekent 'voet' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "أب = moeder (Nederlands) / mother (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, أب betekent 'vader' in het Nederlands. 'Moeder' is أم in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "أخ = broer (Nederlands) / brother (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! أخ betekent 'broer' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "جد = opa (Nederlands) / grandfather (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! جد betekent 'opa' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "جدة = tante (Nederlands) / aunt (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, جدة betekent 'oma' in het Nederlands. 'Tante' is عمة of خالة in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "صديق = vriend (Nederlands) / friend (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! صديق betekent 'vriend' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "مطبخ = badkamer (Nederlands) / bathroom (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, مطبخ betekent 'keuken' in het Nederlands. 'Badkamer' is حمام in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "غرفة = kamer (Nederlands) / room (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! غرفة betekent 'kamer' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "سرير = stoel (Nederlands) / chair (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, سرير betekent 'bed' in het Nederlands. 'Stoel' is كرسي in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "طاولة = tafel (Nederlands) / table (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! طاولة betekent 'tafel' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "حليب = melk (Nederlands) / milk (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! حليب betekent 'melk' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "بيضة = kaas (Nederlands) / cheese (English)",
|
||||
answer: false,
|
||||
explanation: "Nee, بيضة betekent 'ei' in het Nederlands. 'Kaas' is جبن in het Arabisch"
|
||||
},
|
||||
{
|
||||
question: "لحم = vlees (Nederlands) / meat (English)",
|
||||
answer: true,
|
||||
explanation: "Correct! لحم betekent 'vlees' in het Nederlands"
|
||||
}
|
||||
],
|
||||
multiplechoice: [
|
||||
{
|
||||
question: "بيت",
|
||||
options: ["Auto / Car", "Huis / House", "School / School", "Boom / Tree"],
|
||||
answer: 1,
|
||||
explanation: "Correct! بيت betekent 'huis' in het Nederlands (house in English)"
|
||||
},
|
||||
{
|
||||
question: "مدرسة",
|
||||
options: ["Ziekenhuis / Hospital", "Markt / Market", "School / School", "Bibliotheek / Library"],
|
||||
answer: 2,
|
||||
explanation: "Correct! مدرسة betekent 'school' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "سيارة",
|
||||
options: ["Auto / Car", "Bus / Bus", "Fiets / Bicycle", "Trein / Train"],
|
||||
answer: 0,
|
||||
explanation: "Correct! سيارة betekent 'auto' in het Nederlands (car in English)"
|
||||
},
|
||||
{
|
||||
question: "قمر",
|
||||
options: ["Ster / Star", "Zon / Sun", "Maan / Moon", "Planeet / Planet"],
|
||||
answer: 2,
|
||||
explanation: "Correct! قمر betekent 'maan' in het Nederlands (moon in English)"
|
||||
},
|
||||
{
|
||||
question: "كلب",
|
||||
options: ["Kat / Cat", "Hond / Dog", "Vogel / Bird", "Vis / Fish"],
|
||||
answer: 1,
|
||||
explanation: "Correct! كلب betekent 'hond' in het Nederlands (dog in English)"
|
||||
},
|
||||
{
|
||||
question: "طفل",
|
||||
options: ["Man / Man", "Vrouw / Woman", "Kind / Child", "Opa / Grandfather"],
|
||||
answer: 2,
|
||||
explanation: "Correct! طفل betekent 'kind' in het Nederlands (child in English)"
|
||||
},
|
||||
{
|
||||
question: "فاكهة",
|
||||
options: ["Fruit / Fruit", "Groente / Vegetable", "Vlees / Meat", "Brood / Bread"],
|
||||
answer: 0,
|
||||
explanation: "Correct! فاكهة betekent 'fruit' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "نافذة",
|
||||
options: ["Deur / Door", "Raam / Window", "Muur / Wall", "Vloer / Floor"],
|
||||
answer: 1,
|
||||
explanation: "Correct! نافذة betekent 'raam' in het Nederlands (window in English)"
|
||||
},
|
||||
{
|
||||
question: "شعر",
|
||||
options: ["Haar / Hair", "Oog / Eye", "Neus / Nose", "Oor / Ear"],
|
||||
answer: 0,
|
||||
explanation: "Correct! شعر betekent 'haar' in het Nederlands (hair in English)"
|
||||
},
|
||||
{
|
||||
question: "أذن",
|
||||
options: ["Neus / Nose", "Mond / Mouth", "Oor / Ear", "Tand / Tooth"],
|
||||
answer: 2,
|
||||
explanation: "Correct! أذن betekent 'oor' in het Nederlands (ear in English)"
|
||||
},
|
||||
{
|
||||
question: "أم",
|
||||
options: ["Vader / Father", "Moeder / Mother", "Zus / Sister", "Broer / Brother"],
|
||||
answer: 1,
|
||||
explanation: "Correct! أم betekent 'moeder' in het Nederlands (mother in English)"
|
||||
},
|
||||
{
|
||||
question: "أخت",
|
||||
options: ["Oom / Uncle", "Tante / Aunt", "Broer / Brother", "Zus / Sister"],
|
||||
answer: 3,
|
||||
explanation: "Correct! أخت betekent 'zus' in het Nederlands (sister in English)"
|
||||
},
|
||||
{
|
||||
question: "خبز",
|
||||
options: ["Brood / Bread", "Kaas / Cheese", "Melk / Milk", "Ei / Egg"],
|
||||
answer: 0,
|
||||
explanation: "Correct! خبز betekent 'brood' in het Nederlands (bread in English)"
|
||||
},
|
||||
{
|
||||
question: "ماء",
|
||||
options: ["Koffie / Coffee", "Thee / Tea", "Water / Water", "Sap / Juice"],
|
||||
answer: 2,
|
||||
explanation: "Correct! ماء betekent 'water' in het Nederlands"
|
||||
},
|
||||
{
|
||||
question: "تفاحة",
|
||||
options: ["Banaan / Banana", "Appel / Apple", "Sinaasappel / Orange", "Aardbei / Strawberry"],
|
||||
answer: 1,
|
||||
explanation: "Correct! تفاحة betekent 'appel' in het Nederlands (apple in English)"
|
||||
},
|
||||
{
|
||||
question: "موز",
|
||||
options: ["Appel / Apple", "Peer / Pear", "Banaan / Banana", "Druif / Grape"],
|
||||
answer: 2,
|
||||
explanation: "Correct! موز betekent 'banaan' in het Nederlands (banana in English)"
|
||||
},
|
||||
{
|
||||
question: "برتقال",
|
||||
options: ["Aardbei / Strawberry", "Sinaasappel / Orange", "Citroen / Lemon", "Kiwi / Kiwi"],
|
||||
answer: 1,
|
||||
explanation: "Correct! برتقال betekent 'sinaasappel' in het Nederlands (orange in English)"
|
||||
},
|
||||
{
|
||||
question: "دجاج",
|
||||
options: ["Vlees / Meat", "Vis / Fish", "Kip / Chicken", "Varken / Pork"],
|
||||
answer: 2,
|
||||
explanation: "Correct! دجاج betekent 'kip' in het Nederlands (chicken in English)"
|
||||
},
|
||||
{
|
||||
question: "سمك",
|
||||
options: ["Kip / Chicken", "Vlees / Meat", "Varken / Pork", "Vis / Fish"],
|
||||
answer: 3,
|
||||
explanation: "Correct! سمك betekent 'vis' in het Nederlands (fish in English)"
|
||||
},
|
||||
{
|
||||
question: "جبن",
|
||||
options: ["Kaas / Cheese", "Boter / Butter", "Yoghurt / Yogurt", "Room / Cream"],
|
||||
answer: 0,
|
||||
explanation: "Correct! جبن betekent 'kaas' in het Nederlands (cheese in English)"
|
||||
},
|
||||
{
|
||||
question: "بيضة",
|
||||
options: ["Melk / Milk", "Ei / Egg", "Boter / Butter", "Suiker / Sugar"],
|
||||
answer: 1,
|
||||
explanation: "Correct! بيضة betekent 'ei' in het Nederlands (egg in English)"
|
||||
},
|
||||
{
|
||||
question: "كرسي",
|
||||
options: ["Tafel / Table", "Stoel / Chair", "Kast / Cabinet", "Bed / Bed"],
|
||||
answer: 1,
|
||||
explanation: "Correct! كرسي betekent 'stoel' in het Nederlands (chair in English)"
|
||||
},
|
||||
{
|
||||
question: "سرير",
|
||||
options: ["Kast / Cabinet", "Tafel / Table", "Stoel / Chair", "Bed / Bed"],
|
||||
answer: 3,
|
||||
explanation: "Correct! سرير betekent 'bed' in het Nederlands (bed in English)"
|
||||
},
|
||||
{
|
||||
question: "مطبخ",
|
||||
options: ["Keuken / Kitchen", "Badkamer / Bathroom", "Slaapkamer / Bedroom", "Woonkamer / Living room"],
|
||||
answer: 0,
|
||||
explanation: "Correct! مطبخ betekent 'keuken' in het Nederlands (kitchen in English)"
|
||||
},
|
||||
{
|
||||
question: "حمام",
|
||||
options: ["Slaapkamer / Bedroom", "Woonkamer / Living room", "Badkamer / Bathroom", "Keuken / Kitchen"],
|
||||
answer: 2,
|
||||
explanation: "Correct! حمام betekent 'badkamer' in het Nederlands (bathroom in English)"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get a random question based on settings
|
||||
function getRandomQuestion(language, category, type) {
|
||||
// Validate parameters
|
||||
if (!questionsDB[language] || !questionsDB[language][category] || !questionsDB[language][category][type]) {
|
||||
console.error(`Invalid question parameters: ${language}, ${category}, ${type}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the questions array
|
||||
const questions = questionsDB[language][category][type];
|
||||
|
||||
// Return a random question
|
||||
return questions[Math.floor(Math.random() * questions.length)];
|
||||
}
|
||||
|
||||
// Export the function for use in other files
|
||||
window.getRandomQuestion = getRandomQuestion;
|
||||
352
tictactoe/styles.css
Normal file
352
tictactoe/styles.css
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Game Info Styles */
|
||||
.game-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.player-info {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.player {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
opacity: 0.7;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.player.active {
|
||||
background-color: #e3f2fd;
|
||||
opacity: 1;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.player-symbol {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.player-name {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.player-score {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.game-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 15px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
#resetBtn {
|
||||
background-color: #f44336;
|
||||
}
|
||||
|
||||
#resetBtn:hover {
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
|
||||
/* Game Board Styles */
|
||||
.game-board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 10px;
|
||||
margin: 0 auto 30px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.cell {
|
||||
aspect-ratio: 1/1;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.cell:hover {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
|
||||
.cell.x {
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.cell.o {
|
||||
color: #2196F3;
|
||||
}
|
||||
|
||||
.cell.highlight {
|
||||
background-color: #ffeb3b;
|
||||
}
|
||||
|
||||
/* Modal Styles */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.modal h2 {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.timer-container {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.timer-bar {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #4CAF50;
|
||||
border-radius: 15px;
|
||||
transition: width 1s linear;
|
||||
}
|
||||
|
||||
.timer-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.timer-bar.warning {
|
||||
background-color: #FFC107;
|
||||
}
|
||||
|
||||
.timer-bar.danger {
|
||||
background-color: #F44336;
|
||||
}
|
||||
|
||||
.question-text {
|
||||
font-size: 28px;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.answer-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.answer-option {
|
||||
padding: 20px;
|
||||
border: 3px solid #ddd;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.answer-option:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-color: #bbb;
|
||||
}
|
||||
|
||||
.answer-option.selected {
|
||||
border-color: #2196F3;
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
|
||||
.answer-option.correct {
|
||||
border-color: #4CAF50;
|
||||
background-color: #e8f5e9;
|
||||
}
|
||||
|
||||
.answer-option.incorrect {
|
||||
border-color: #f44336;
|
||||
background-color: #ffebee;
|
||||
}
|
||||
|
||||
.feedback {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-top: 25px;
|
||||
min-height: 30px;
|
||||
font-size: 24px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.feedback.correct {
|
||||
color: #4CAF50;
|
||||
background-color: #e8f5e9;
|
||||
border: 3px solid #4CAF50;
|
||||
}
|
||||
|
||||
.feedback.incorrect {
|
||||
color: #f44336;
|
||||
background-color: #ffebee;
|
||||
border: 3px solid #f44336;
|
||||
}
|
||||
|
||||
/* Settings Styles */
|
||||
.settings {
|
||||
margin-top: 30px;
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.settings h3 {
|
||||
margin-bottom: 15px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.setting-group label {
|
||||
width: 120px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.setting-group select {
|
||||
flex: 1;
|
||||
padding: 8px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #ddd;
|
||||
font-size: 16px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#applySettingsBtn {
|
||||
margin-top: 10px;
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
#applySettingsBtn:hover {
|
||||
background-color: #1976D2;
|
||||
}
|
||||
|
||||
/* RTL Support for Arabic */
|
||||
[lang="ar"] {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Responsive Styles */
|
||||
@media (max-width: 600px) {
|
||||
.game-info {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.cell {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.setting-group {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.setting-group label {
|
||||
margin-bottom: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.setting-group select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue