From 5d326c8fd1327477557266a9b8b522fd22d029f2 Mon Sep 17 00:00:00 2001 From: HydroponKing Date: Sun, 15 Sep 2024 03:44:00 +0500 Subject: [PATCH 1/6] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83=20=D1=82=D1=80=D0=B5?= =?UTF-8?q?=D1=85=20=D0=B6=D0=B8=D0=B7=D0=BD=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Cards/Cards.jsx | 143 ++++++++++++++++---------- src/components/Cards/Cards.module.css | 6 ++ 2 files changed, 94 insertions(+), 55 deletions(-) diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 7526a56c8..9f54a4dea 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -1,3 +1,5 @@ +// src/components/Cards/Cards.jsx + import { shuffle } from "lodash"; import { useEffect, useState } from "react"; import { generateDeck } from "../../utils/cards"; @@ -6,12 +8,10 @@ import { EndGameModal } from "../../components/EndGameModal/EndGameModal"; import { Button } from "../../components/Button/Button"; import { Card } from "../../components/Card/Card"; -// Игра закончилась +// Константы статусов игры const STATUS_LOST = "STATUS_LOST"; const STATUS_WON = "STATUS_WON"; -// Идет игра: карты закрыты, игрок может их открыть const STATUS_IN_PROGRESS = "STATUS_IN_PROGRESS"; -// Начало игры: игрок видит все карты в течении нескольких секунд const STATUS_PREVIEW = "STATUS_PREVIEW"; function getTimerValue(startDate, endDate) { @@ -26,9 +26,9 @@ function getTimerValue(startDate, endDate) { endDate = new Date(); } - const diffInSecconds = Math.floor((endDate.getTime() - startDate.getTime()) / 1000); - const minutes = Math.floor(diffInSecconds / 60); - const seconds = diffInSecconds % 60; + const diffInSeconds = Math.floor((endDate.getTime() - startDate.getTime()) / 1000); + const minutes = Math.floor(diffInSeconds / 60); + const seconds = diffInSeconds % 60; return { minutes, seconds, @@ -41,53 +41,63 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { - // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта + // Состояние для игровых карт const [cards, setCards] = useState([]); // Текущий статус игры const [status, setStatus] = useState(STATUS_PREVIEW); - - // Дата начала игры + // Дата начала и окончания игры const [gameStartDate, setGameStartDate] = useState(null); - // Дата конца игры const [gameEndDate, setGameEndDate] = useState(null); - - // Стейт для таймера, высчитывается в setInteval на основе gameStartDate и gameEndDate + // Состояние таймера const [timer, setTimer] = useState({ seconds: 0, minutes: 0, }); + // Количество оставшихся жизней + const [lives, setLives] = useState(3); + // Выбранные в данный момент карты + const [selectedCards, setSelectedCards] = useState([]); + // Флаг для блокировки кликов во время проверки пар + const [isProcessing, setIsProcessing] = useState(false); - function finishGame(status = STATUS_LOST) { + // Функция для завершения игры + function finishGame(gameStatus = STATUS_LOST) { setGameEndDate(new Date()); - setStatus(status); + setStatus(gameStatus); } + + // Функция для старта игры function startGame() { const startDate = new Date(); setGameEndDate(null); setGameStartDate(startDate); setTimer(getTimerValue(startDate, null)); setStatus(STATUS_IN_PROGRESS); + setLives(3); + setSelectedCards([]); + setIsProcessing(false); } + + // Функция для перезапуска игры function resetGame() { setGameStartDate(null); setGameEndDate(null); setTimer(getTimerValue(null, null)); setStatus(STATUS_PREVIEW); + setLives(3); + setSelectedCards([]); + setIsProcessing(false); } /** - * Обработка основного действия в игре - открытие карты. - * После открытия карты игра может пепереходит в следующие состояния - * - "Игрок выиграл", если на поле открыты все карты - * - "Игрок проиграл", если на поле есть две открытые карты без пары - * - "Игра продолжается", если не случилось первых двух условий + * Обработка открытия карты */ const openCard = clickedCard => { - // Если карта уже открыта, то ничего не делаем - if (clickedCard.open) { + if (isProcessing || clickedCard.open) { return; } - // Игровое поле после открытия кликнутой карты + + // Открываем кликнутую карту const nextCards = cards.map(card => { if (card.id !== clickedCard.id) { return card; @@ -101,56 +111,72 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { setCards(nextCards); - const isPlayerWon = nextCards.every(card => card.open); - - // Победа - все карты на поле открыты - if (isPlayerWon) { - finishGame(STATUS_WON); - return; - } - - // Открытые карты на игровом поле - const openCards = nextCards.filter(card => card.open); + // Добавляем карту в выбранные + const nextSelectedCards = [...selectedCards, clickedCard]; + setSelectedCards(nextSelectedCards); - // Ищем открытые карты, у которых нет пары среди других открытых - const openCardsWithoutPair = openCards.filter(card => { - const sameCards = openCards.filter(openCard => card.suit === openCard.suit && card.rank === openCard.rank); + if (nextSelectedCards.length === 2) { + setIsProcessing(true); + const [firstCard, secondCard] = nextSelectedCards; - if (sameCards.length < 2) { - return true; - } + const isMatch = firstCard.rank === secondCard.rank && firstCard.suit === secondCard.suit; - return false; - }); + if (isMatch) { + // Карты совпали + setSelectedCards([]); - const playerLost = openCardsWithoutPair.length >= 2; + // Проверяем, выиграл ли игрок + const isPlayerWon = nextCards.every(card => card.open); + if (isPlayerWon) { + finishGame(STATUS_WON); + } + setIsProcessing(false); + } else { + // Карты не совпали + const nextLives = lives - 1; + setLives(nextLives); - // "Игрок проиграл", т.к на поле есть две открытые карты без пары - if (playerLost) { - finishGame(STATUS_LOST); - return; + if (nextLives === 0) { + // Жизни закончились, игрок проиграл + finishGame(STATUS_LOST); + setIsProcessing(false); + } else { + // Закрываем карты обратно после задержки + setTimeout(() => { + setCards(currentCards => + currentCards.map(card => { + if (card.id === firstCard.id || card.id === secondCard.id) { + return { + ...card, + open: false, + }; + } + return card; + }), + ); + setSelectedCards([]); + setIsProcessing(false); + }, 1000); // Задержка в 1 секунду + } + } } - - // ... игра продолжается }; const isGameEnded = status === STATUS_LOST || status === STATUS_WON; - // Игровой цикл + // Инициализация игры useEffect(() => { - // В статусах кроме превью доп логики не требуется if (status !== STATUS_PREVIEW) { return; } - // В статусе превью мы if (pairsCount > 36) { alert("Столько пар сделать невозможно"); return; } setCards(() => { - return shuffle(generateDeck(pairsCount, 10)); + return shuffle(generateDeck(pairsCount)); }); const timerId = setTimeout(() => { @@ -162,7 +188,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { }; }, [status, pairsCount, previewSeconds]); - // Обновляем значение таймера в интервале + // Обновление таймера useEffect(() => { const intervalId = setInterval(() => { setTimer(getTimerValue(gameStartDate, gameEndDate)); @@ -185,17 +211,24 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { <>
min
-
{timer.minutes.toString().padStart("2", "0")}
+
{timer.minutes.toString().padStart(2, "0")}
.
sec
-
{timer.seconds.toString().padStart("2", "0")}
+
{timer.seconds.toString().padStart(2, "0")}
)} - {status === STATUS_IN_PROGRESS ? : null} + {status === STATUS_IN_PROGRESS ? ( + <> +
+

Жизни: {lives}

+
+ + + ) : null}
diff --git a/src/components/Cards/Cards.module.css b/src/components/Cards/Cards.module.css index 000c5006c..5524de90b 100644 --- a/src/components/Cards/Cards.module.css +++ b/src/components/Cards/Cards.module.css @@ -70,3 +70,9 @@ margin-bottom: -12px; } +.lives { + font-size: 18px; + margin-left: 20px; + display: flex; + align-items: center; +} \ No newline at end of file From b3c74edf21301505a559656aa7810141f3d73126 Mon Sep 17 00:00:00 2001 From: HydroponKing Date: Sun, 15 Sep 2024 16:20:39 +0500 Subject: [PATCH 2/6] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D0=B2=D1=8B=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B2=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 9b90842c4..9497c875a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +## Оценка времени выполнения работы "Вводный урок" + +- **Ожидаемое время:** 6 часов +- **Фактическое время:** 2 часа + # MVP Карточная игра "Мемо" В этом репозитории реализован MVP карточкой игры "Мемо" по [тех.заданию](./docs/mvp-spec.md) From 34d49b5036ee01ff4f26315f6611986191506be9 Mon Sep 17 00:00:00 2001 From: HydroponKing <155968943+HydroponKing@users.noreply.github.com> Date: Tue, 17 Sep 2024 00:02:22 +0500 Subject: [PATCH 3/6] =?UTF-8?q?=D0=BF=D0=BE=D1=8F=D0=B2=D0=B8=D0=BB=D1=81?= =?UTF-8?q?=D1=8F=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=20=D1=80=D0=B5=D0=B6?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc.js | 1 + src/components/Cards/Cards.jsx | 25 +++++++++++++------ src/context/GameModeContext.js | 8 ++++++ src/index.js | 18 +++++++++++-- src/pages/SelectLevelPage/SelectLevelPage.jsx | 13 ++++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 src/context/GameModeContext.js diff --git a/.prettierrc.js b/.prettierrc.js index 65e18f5ff..a037d25c9 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -7,4 +7,5 @@ module.exports = { bracketSpacing: true, arrowParens: "avoid", htmlWhitespaceSensitivity: "ignore", + endOfLine: "auto", // для своместной разработки и с linux и с windows }; diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 9f54a4dea..83a667e54 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -1,12 +1,13 @@ // src/components/Cards/Cards.jsx import { shuffle } from "lodash"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useContext } from "react"; import { generateDeck } from "../../utils/cards"; import styles from "./Cards.module.css"; import { EndGameModal } from "../../components/EndGameModal/EndGameModal"; import { Button } from "../../components/Button/Button"; import { Card } from "../../components/Card/Card"; +import { GameModeContext } from "../../context/GameModeContext"; // Константы статусов игры const STATUS_LOST = "STATUS_LOST"; @@ -41,6 +42,8 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { + const { livesMode } = useContext(GameModeContext); // Используем контекст + // Состояние для игровых карт const [cards, setCards] = useState([]); // Текущий статус игры @@ -54,12 +57,18 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { minutes: 0, }); // Количество оставшихся жизней - const [lives, setLives] = useState(3); + const initialLives = livesMode ? 3 : 1; + const [lives, setLives] = useState(initialLives); // Выбранные в данный момент карты const [selectedCards, setSelectedCards] = useState([]); // Флаг для блокировки кликов во время проверки пар const [isProcessing, setIsProcessing] = useState(false); + // Обновляем количество жизней при изменении режима игры + useEffect(() => { + setLives(initialLives); + }, [initialLives]); + // Функция для завершения игры function finishGame(gameStatus = STATUS_LOST) { setGameEndDate(new Date()); @@ -73,7 +82,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { setGameStartDate(startDate); setTimer(getTimerValue(startDate, null)); setStatus(STATUS_IN_PROGRESS); - setLives(3); + setLives(initialLives); setSelectedCards([]); setIsProcessing(false); } @@ -84,7 +93,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { setGameEndDate(null); setTimer(getTimerValue(null, null)); setStatus(STATUS_PREVIEW); - setLives(3); + setLives(initialLives); setSelectedCards([]); setIsProcessing(false); } @@ -223,9 +232,11 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) {
{status === STATUS_IN_PROGRESS ? ( <> -
-

Жизни: {lives}

-
+ {livesMode && ( +
+

Жизни: {lives}

+
+ )} ) : null} diff --git a/src/context/GameModeContext.js b/src/context/GameModeContext.js new file mode 100644 index 000000000..8651bbcef --- /dev/null +++ b/src/context/GameModeContext.js @@ -0,0 +1,8 @@ +// src/GameModeContext.js + +import { createContext } from "react"; + +export const GameModeContext = createContext({ + livesMode: false, // false - оригинальный режим, true - режим с тремя жизнями + setLivesMode: () => {}, +}); diff --git a/src/index.js b/src/index.js index f689c5f0b..19b128507 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,26 @@ -import React from "react"; +// src/index.js + +import React, { useState } from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import { RouterProvider } from "react-router-dom"; import { router } from "./router"; +import { GameModeContext } from "./context/GameModeContext"; const root = ReactDOM.createRoot(document.getElementById("root")); + +function App() { + const [livesMode, setLivesMode] = useState(false); + + return ( + + + + ); +} + root.render( - + , ); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index 758942e51..472b4d618 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -1,11 +1,24 @@ +// src/pages/SelectLevelPage/SelectLevelPage.jsx + import { Link } from "react-router-dom"; import styles from "./SelectLevelPage.module.css"; +import { useContext } from "react"; +import { GameModeContext } from "../../context/GameModeContext"; export function SelectLevelPage() { + const { livesMode, setLivesMode } = useContext(GameModeContext); + + const handleCheckboxChange = event => { + setLivesMode(event.target.checked); + }; return (

Выбери сложность

+
  • From b0136ed3992b575bd694174f6bf5a6450eb40b5b Mon Sep 17 00:00:00 2001 From: HydroponKing <155968943+HydroponKing@users.noreply.github.com> Date: Tue, 17 Sep 2024 02:24:14 +0500 Subject: [PATCH 4/6] =?UTF-8?q?=D0=B1=D0=BE=D0=BC=D0=B1=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D1=8F=20=D1=81=D1=82=D0=B8=D0=BB=D0=B8=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/components/Cards/Cards.module.css | 18 +++++--- .../SelectLevelPage.module.css | 43 +++++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9497c875a..dfb7cb167 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Оценка времени выполнения работы "Вводный урок" - **Ожидаемое время:** 6 часов -- **Фактическое время:** 2 часа +- **Фактическое время:** 6 часов # MVP Карточная игра "Мемо" diff --git a/src/components/Cards/Cards.module.css b/src/components/Cards/Cards.module.css index 5524de90b..c2298bb16 100644 --- a/src/components/Cards/Cards.module.css +++ b/src/components/Cards/Cards.module.css @@ -1,3 +1,15 @@ +@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap'); + +.lives { + font-size: 24px; /* Увеличим размер шрифта */ + margin-left: 20px; + display: flex; + align-items: center; + color: #fff; + font-family: 'Orbitron', sans-serif; /* Добавляем угловатый шрифт */ +} + + .container { width: 672px; margin: 0 auto; @@ -69,10 +81,4 @@ line-height: 32px; margin-bottom: -12px; -} -.lives { - font-size: 18px; - margin-left: 20px; - display: flex; - align-items: center; } \ No newline at end of file diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 390ac0def..49e69f3dc 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -1,3 +1,46 @@ +@import url('https://fonts.googleapis.com/css2?family=Cabin+Sketch:wght@400;700&display=swap'); + +.checkboxContainer { + display: flex; + align-items: center; + font-family: 'Cabin Sketch', cursive; /* Подключённый шрифт */ + font-size: 18px; + color: #333; +} + +.checkboxContainer input[type="checkbox"] { + width: 20px; + height: 20px; + margin-right: 10px; + position: relative; + cursor: pointer; + appearance: none; + background-color: #fff; + border: 2px solid #333; + border-radius: 5px; + transition: background-color 0.2s ease; + display: flex; + justify-content: center; + align-items: center; +} + +.checkboxContainer input[type="checkbox"]:checked { + background-color: #4caf50; +} + +.checkboxContainer input[type="checkbox"]:checked::before { + content: '✓'; + font-size: 18px; /* Сделаем галочку чуть больше */ + color: #fff; + font-weight: bold; /* Галочка станет толще */ + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); /* Выравнивание галочки по центру */ + font-family: 'Comic Sans MS', cursive; /* стили для галочки */ +} + + .container { width: 100%; min-height: 100%; From 513fe8bb02c9eebbe8404f15ce0d7728528a4031 Mon Sep 17 00:00:00 2001 From: HydroponKing <155968943+HydroponKing@users.noreply.github.com> Date: Tue, 17 Sep 2024 03:51:35 +0500 Subject: [PATCH 5/6] =?UTF-8?q?=D1=81=D1=82=D0=B8=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BD=D1=83=20=D0=B2=D0=BE=D0=BE=D0=B1?= =?UTF-8?q?=D1=89=D0=B5=20=D0=B1=D0=BE=D0=BC=D0=B1=D0=BE=D0=B2=D0=B0=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Cards/Cards.jsx | 2 +- src/components/Cards/Cards.module.css | 13 +++++++++---- .../SelectLevelPage/SelectLevelPage.module.css | 14 +++++--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 83a667e54..604d1df23 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -233,7 +233,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { {status === STATUS_IN_PROGRESS ? ( <> {livesMode && ( -
    +

    Жизни: {lives}

    )} diff --git a/src/components/Cards/Cards.module.css b/src/components/Cards/Cards.module.css index c2298bb16..d6d59f50a 100644 --- a/src/components/Cards/Cards.module.css +++ b/src/components/Cards/Cards.module.css @@ -1,15 +1,20 @@ -@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Handjet:wght@100..900&display=swap'); .lives { - font-size: 24px; /* Увеличим размер шрифта */ + font-size: 32px; margin-left: 20px; display: flex; align-items: center; - color: #fff; - font-family: 'Orbitron', sans-serif; /* Добавляем угловатый шрифт */ + font-family: "Handjet", sans-serif; + color: #fff; /* По умолчанию белый цвет */ +} + +.livesCritical { + color: rgb(255, 55, 55); /* Красный цвет при 1 жизни */ } + .container { width: 672px; margin: 0 auto; diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 49e69f3dc..650261dc7 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -15,7 +15,7 @@ position: relative; cursor: pointer; appearance: none; - background-color: #fff; + background-color: #c2f5ff; border: 2px solid #333; border-radius: 5px; transition: background-color 0.2s ease; @@ -24,18 +24,14 @@ align-items: center; } -.checkboxContainer input[type="checkbox"]:checked { - background-color: #4caf50; -} - .checkboxContainer input[type="checkbox"]:checked::before { content: '✓'; - font-size: 18px; /* Сделаем галочку чуть больше */ - color: #fff; + font-size: 32px; /* Сделаем галочку чуть больше */ + color: #004980; font-weight: bold; /* Галочка станет толще */ position: absolute; - left: 50%; - top: 50%; + left: 63%; + top: 18%; transform: translate(-50%, -50%); /* Выравнивание галочки по центру */ font-family: 'Comic Sans MS', cursive; /* стили для галочки */ } From b2ff97c13e5513318e0bb55e65268a096a3d7f0f Mon Sep 17 00:00:00 2001 From: HydroponKing <155968943+HydroponKing@users.noreply.github.com> Date: Tue, 17 Sep 2024 04:00:07 +0500 Subject: [PATCH 6/6] =?UTF-8?q?=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=B8?= =?UTF-8?q?=D0=B3=D1=80=D1=8B=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D1=8F?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/context/GameModeContext.js | 19 +++++++++++++++---- src/index.js | 12 ++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/context/GameModeContext.js b/src/context/GameModeContext.js index 8651bbcef..d0d6976b4 100644 --- a/src/context/GameModeContext.js +++ b/src/context/GameModeContext.js @@ -1,8 +1,19 @@ -// src/GameModeContext.js - -import { createContext } from "react"; +import { createContext, useState, useEffect } from "react"; export const GameModeContext = createContext({ - livesMode: false, // false - оригинальный режим, true - режим с тремя жизнями + livesMode: false, setLivesMode: () => {}, }); + +export function GameModeProvider({ children }) { + const [livesMode, setLivesMode] = useState(() => { + const savedMode = localStorage.getItem("livesMode"); + return savedMode === "true"; + }); + + useEffect(() => { + localStorage.setItem("livesMode", livesMode); + }, [livesMode]); + + return {children}; +} diff --git a/src/index.js b/src/index.js index 19b128507..30c3029f6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,21 +1,17 @@ -// src/index.js - -import React, { useState } from "react"; +import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import { RouterProvider } from "react-router-dom"; import { router } from "./router"; -import { GameModeContext } from "./context/GameModeContext"; +import { GameModeProvider } from "./context/GameModeContext"; // Импортируем обновленный провайдер const root = ReactDOM.createRoot(document.getElementById("root")); function App() { - const [livesMode, setLivesMode] = useState(false); - return ( - + - + ); }