Тема 3. React.js Memory Game App
Створення Memory Game React.js додатку
- Новий додаток
- Форматування
- Файли та папки
Створення Memory Game React.js додатку, введення команд в консоль
D: або C: - переключення між дисками
cd - переходимо в необхідну вам папку
npx create-react-app memory-game- створення нового React.js проєкту
npx create-react-app - сама команда створення
memory-game- назва папки в якій буде додаток
cd memory-game - переходимо в створену папку
Видаляємо непотрібні файли, чистимо index.js та App.js від непотрібних команд
Видаляємо файли: setupTests.js,repor,WebVitals.js,logo.svg,index.css,App.test.js
З файлу index.js видаляємо такі рядки
import './index.css'; import reportWebVitals from './reportWebVitals'; reportWebVitals();
Та коментарі: // If you want...
З файлу App.js видаляємо import logo from './logo.svg';
Тег <div className="app"> і все що всередині нього
В папці src залишаємо лише такі файли:
App.js, App.css, index.js
Скопіюйте стилізацію нижче та замініть її в файлі App.css
- Інформація
Робимо заміну всієї стилізації в файлі App.css на свою, яку копіювали вище
Заготовки файлів для додатку
- Файл index.js
- Файл App.js
Створення змінних стану та функцій
- Інформація про змінні
- Інформація про функції
currentLevel
: Зберігає обраний рівень складності гри (легкий, середній, важкий).cards
: Масив карток, який містить змішані картки для поточного рівня.flippedIndices
: Масив індексів карток, які вже були перевернуті (відкриті).matchedPairs
: Масив індексів пар карток, які знайдені.moves
: Лічильник кількості ходів гравця.gameOver
: Змінна, яка вказує, чи завершена гра.
Функція
initializeGame
ініціалізує гру. Вона перемішує карти, скидає всі індекси перевернутих та зіграних пар, а також скидає лічильник ходів та встановлюєgameOver
наfalse
.Ви використовуєте
useEffect
, щоб викликатиinitializeGame
при змініcurrentLevel
. Це означає, що гра буде ініціалізуватися знову, коли гравець змінює рівень гри.Функція
shuffle
перемішує переданий масив, використовуючи алгоритм "Fisher-Yates". Вона створює копію масиву, перемішує його елементи і повертає перемішаний масив.
Рендеринг компонентів
- Інформація
return():
- У рендері відображається заголовок гри, кількість ходів, поточний рівень складності та повідомлення про перемогу, якщо гра завершилася.
- Кнопки для вибору рівня складності відображаються на сторінці.
- Картки відображаються у вигляді блоків з емодзі, і їх стан залежить від того, чи вони були перевернуті або знайдені.
- Є кнопка "Розпочати нову гру", яка дозволяє перезапустити гру.
Група легких завдань
- Завдання 1
- Завдання 2
- Завдання 3
- Завдання 4
Розбиття коду на компоненти
Зазвичай, розбиття коду на компоненти робить його більш читабельним та обслуговуваним. У вашому коді можна виділити кілька компонентів:
Game (Гра):
Містить весь код гри, включаючи стани та функції для ініціалізації гри, перемішування карток та обробки кліків на картках.
Levels :
Містить об'єкт із рівнями та картинками для них
App:
Містить стани рівня гри та інших глобальних аспектів.
Включає компонент Game та передає йому відповідні стани і функції.
Добавлення нових рівнів
Для додавання нових рівнів у гру «Мемографія» на React ми створюємо різні набори зображень і рівня складності. Додати два нових рівня складності: "Легкий" і "Середній". Легкий рівень містить менше карток, а середній - більше. Ви можете легко розширити цей шаблон для створення ще більш складних рівнів.
Замінити картки(іконки) на картинки
Для додавання нових рівнів у гру «Мемографія» на React ми створюємо різні набори зображень і рівня складності. Додати два нових рівня складності: "Легкий" і "Середній". Легкий рівень містить менше карток, а середній - більше. Ви можете легко розширити цей шаблон для створення ще більш складних рівнів.
Добавити таймер гри
Додавання таймера до цього коду вимагає створення та оновлення змінної, яка відстежує час, і відображення цього часу в компоненті.
Завдання 5
- Завдання 5
Створення локалізації гри з різними мовами
Завдання може показатись важким, нехай вчитель його вам пояснить
Посилання на Тему 9. Введення в React.js з попереднього курсу
Посилання на Тему 1. Створення React.js, проєкт ToDoList
Посилання на Тему 2. Створення React.js Quiz, Temperature App's
Завдання 1 та 2. Розбиття коду на компоненти та добавлення нових рівнів
function Game({ currentLevel, cards, flippedIndices, matchedPairs, moves, gameOver, setCurrentLevel, initializeGame, handleCardClick }) {
return (
<div className="App">
<h1>Мемографія</h1>
<p>Кількість ходів: {moves}</p>
<p>Обраний рівень: {levels[currentLevel].name}</p>
{gameOver && <p>Ви виграли! Вітаємо!</p>}
<div className="level-buttons">
{Object.keys(levels).map((level) => (
<button key={level} onClick={() => setCurrentLevel(level)}>{levels[level].name}</button>
))}
</div>
<div className="card-container">
{cards.map((card, index) => (
<div
key={index}
className={`card ${flippedIndices.includes(index) || matchedPairs.includes(index) ? 'flipped' : ''}`}
onClick={() => handleCardClick(index)}
>
{flippedIndices.includes(index) || matchedPairs.includes(index) ? card : '❓'}
</div>
))}
</div>
<button onClick={initializeGame}>Розпочати нову гру</button>
</div>
);
}
function App() {
const [currentLevel, setCurrentLevel] = useState('hard');
const [cards, setCards] = useState([]);
const [flippedIndices, setFlippedIndices] = useState([]);
const [matchedPairs, setMatchedPairs] = useState([]);
const [moves, setMoves] = useState(0);
const [gameOver, setGameOver] = useState(false);
const initializeGame = () => {
// ...
};
useEffect(() => {
initializeGame();
}, [currentLevel]);
const handleCardClick = (index) => {
// ...
};
return (
<Game
currentLevel={currentLevel}
cards={cards}
flippedIndices={flippedIndices}
matchedPairs={matchedPairs}
moves={moves}
gameOver={gameOver}
setCurrentLevel={setCurrentLevel}
initializeGame={initializeGame}
handleCardClick={handleCardClick}
/>
);
}
export default App;
Код із цих файлів необхідно доповнити вже готовими функціями
Завдання 3. Заміна іконок на картинки із відповідністю
const levels = { easy: { name: 'Легкий', cards: [ 'https://example.com/image1.png', 'https://example.com/image2.png', 'https://example.com/image3.png', 'https://example.com/image4.png', 'https://example.com/image5.png', 'https://example.com/image6.png', 'https://example.com/image7.png', 'https://example.com/image8.png', ], },
medium: { name: 'Середній', cards: [ 'https://example.com/image9.png', 'https://example.com/image10.png', 'https://example.com/image11.png', 'https://example.com/image12.png', 'https://example.com/image13.png', 'https://example.com/image14.png', 'https://example.com/image15.png', 'https://example.com/image16.png', 'https://example.com/image17.png', 'https://example.com/image18.png', 'https://example.com/image19.png', 'https://example.com/image20.png', ], },
};
Завдання 4. Добавлення таймеру гри
Додавання таймера до цього коду вимагає створення та оновлення змінної, яка відстежує час, і відображення цього часу в компоненті. Ось приклад, як ви можете додати таймер до вашого коду:
- Створіть новий стан для зберігання часу гри:
const [time, setTime] = useState(0);
- Створіть функцію для запуску та зупинки таймера:
const startTimer = () => {
const timerInterval = setInterval(() => {
setTime((prevTime) => prevTime + 1);
}, 1000);
return timerInterval;
};
const stopTimer = (timerInterval) => {
clearInterval(timerInterval);
};
- Додайте таймер у функцію
initializeGame
, щоб почати відлік часу після ініціалізації гри:
const initializeGame = () => {
// Останній код ініціалізації гри
// Почнемо таймер
const timerInterval = startTimer();
// Збережемо інтервал таймера у стані
setTimerInterval(timerInterval);
};
- Додайте відображення часу в компоненті:
<p>Час гри: {formatTime(time)}</p>
- Створіть функцію для форматування часу в годинах, хвилинах та секундах:
const formatTime = (timeInSeconds) => {
const hours = Math.floor(timeInSeconds / 3600);
const minutes = Math.floor((timeInSeconds % 3600) / 60);
const seconds = timeInSeconds % 60;
return `${hours}:${minutes}:${seconds}`;
};
- Не забудьте створити стан для збереження інтервалу таймера:
const [timerInterval, setTimerInterval] = useState(null);
- Зупиняйте таймер при завершенні гри:
if (matchedPairs.length + 2 === cards.length) {
setGameOver(true);
stopTimer(timerInterval); // Зупинити таймер при завершенні гри
}
Це додасть таймер до вашої гри, який буде відображати час гри у форматі годин:хвилини:секунди. Таймер запускатиметься при ініціалізації гри і зупинятиметься при завершенні гри.
Завдання 5. Добавлення локалізації гри
Для додавання локалізації в чистий код React вам спочатку потрібно налаштувати бібліотеку для локалізації. Однією з популярних бібліотек для локалізації є i18next
. Ось як ви можете налаштувати локалізацію і використовувати її в вашому коді:
- Встановіть
i18next
таreact-i18next
за допомогою npm або yarn:
npm install i18next react-i18next
- Створіть теку
locales
у кореневому каталозі вашого проекту і додайте файли локалізації для кожної мови, наприклад,en.json
іuk.json
:
// locales/en.json
{
"gameTitle": "Memory Game",
"selectSet": "Select Set",
"moves": "Moves",
"level": "Level",
"youWin": "You Win",
// Додайте інші ключі локалізації для англійської мови
}
// locales/uk.json
{
"gameTitle": "Мемографія",
"selectSet": "Оберіть набір",
"moves": "Ходи",
"level": "Рівень",
"youWin": "Ви виграли",
// Додайте інші ключі локалізації для української мови
}
- Створіть файл
i18n.js
для налаштуванняi18next
у кореневому каталозі вашого проекту:
// i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enTranslation from './locales/en.json';
import ukTranslation from './locales/uk.json';
i18n
.use(initReactI18next)
.init({
resources: {
en: {
translation: enTranslation,
},
uk: {
translation: ukTranslation,
},
},
lng: 'en', // Початкова мова (англійська)
fallbackLng: 'en', // Мова за умовчанням, якщо вказана неіснуюча мова
interpolation: {
escapeValue: false, // Не потрібно екранувати спеціальні символи
},
});
export default i18n;
- В вашому компоненті
App.js
імпортуйтеuseTranslation
і використовуйте його для отримання перекладу тексту:
import React, { useState, useEffect } from 'react';
import './App.css';
import { useTranslation } from 'react-i18next'; // Імпортуйте useTranslation
// ...
function App() {
const { t } = useTranslation(); // Ініціалізуйте переклад
return (
<div className="App">
<h1>{t('gameTitle')}</h1>
<p>{t('moves')}: {moves}</p>
<p>{t('level')}: {levels[currentLevel].name}</p>
{gameOver && <p>{t('youWin')}</p>}
{/* Решта вашого коду ... */}
</div>
);
}
export default App;
Це дозволить вам використовувати локалізований текст у вашому компоненті. При зміні мови ви можете змінити значення lng
у файлі i18n.js
, і бібліотека i18next
автоматично вибере потрібну локалізацію.