🎮ArcadeLab

Медиа Крокодил — Карточки терминов

by CrystalFox63
748 lines32.1 KB
▶ Play
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
    <title>Медиа Крокодил — Карточки терминов</title>
    <!-- Font Awesome 6 (иконки для достижений) -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
    <!-- Google Font: комичный и чистый шрифт -->
    <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none; /* небольшая имитация карточек, но текст можно копировать */
        }

        body {
            min-height: 100vh;
            background: linear-gradient(145deg, #fde9e0 0%, #fff3e8 100%);
            font-family: 'Quicksand', sans-serif;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* Основной контейнер игры */
        .game-container {
            max-width: 1300px;
            width: 100%;
            background: rgba(255, 250, 240, 0.85);
            border-radius: 70px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25), inset 0 1px 2px rgba(255,255,255,0.6);
            backdrop-filter: blur(2px);
            padding: 20px 25px 35px;
            transition: all 0.2s ease;
        }

        /* Верхняя панель: таймер, счёт, прогресс */
        .stats-bar {
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: center;
            gap: 15px;
            background: #fff6e8;
            padding: 12px 25px;
            border-radius: 60px;
            margin-bottom: 30px;
            box-shadow: 0 8px 14px rgba(0,0,0,0.05), inset 0 1px 0 white;
        }

        .stat-card {
            background: #fde2c4;
            padding: 8px 20px;
            border-radius: 50px;
            display: flex;
            align-items: center;
            gap: 12px;
            font-weight: 700;
            font-size: 1.3rem;
            color: #7b3f00;
            box-shadow: 0 3px 6px rgba(0,0,0,0.05);
        }

        .stat-card i {
            font-size: 1.8rem;
            color: #ff8c42;
        }

        .timer-box {
            background: #2e2c2a;
            color: #ffe0b5;
            background: linear-gradient(135deg, #3d3b38, #282623);
        }
        .timer-box i {
            color: #ffb347;
        }

        .progress-area {
            background: #ffe1b9;
            border-radius: 40px;
            padding: 5px 18px;
            font-weight: 600;
            font-size: 1.2rem;
        }

        /* Основная карточка с термином */
        .term-card {
            background: #ffffffd9;
            backdrop-filter: blur(4px);
            border-radius: 65px;
            padding: 40px 20px;
            margin-bottom: 35px;
            text-align: center;
            box-shadow: 0 20px 35px -12px rgba(0, 0, 0, 0.2), inset 0 1px 4px rgba(255,255,240,0.8);
            transition: transform 0.2s;
            border: 2px solid #ffddb0;
        }

        .term-word {
            font-size: 3.5rem;
            font-weight: 800;
            color: #e26d1f;
            background: linear-gradient(135deg, #ffb347, #ff8622);
            background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
            text-shadow: 4px 4px 12px rgba(0,0,0,0.05);
            letter-spacing: -0.02em;
            word-break: break-word;
        }

        .term-hint {
            font-size: 1rem;
            color: #9b6a3c;
            margin-top: 12px;
            font-weight: 500;
        }

        /* варианты ответов */
        .options-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
            gap: 18px;
            margin: 25px 0 20px;
        }

        .option-btn {
            background: #fef3e4;
            border: 3px solid #ffcf9a;
            border-radius: 50px;
            padding: 14px 12px;
            font-size: 1rem;
            font-weight: 600;
            color: #704214;
            text-align: center;
            cursor: pointer;
            transition: all 0.2s ease;
            font-family: 'Quicksand', sans-serif;
            box-shadow: 0 6px 0 #e7bc8b;
        }

        .option-btn:hover:not(:disabled) {
            transform: translateY(-2px);
            background: #fff0e0;
            border-color: #ffb56b;
            box-shadow: 0 8px 0 #e7bc8b;
        }

        .option-btn:active:not(:disabled) {
            transform: translateY(3px);
            box-shadow: 0 3px 0 #e7bc8b;
        }

        .option-btn.disabled-btn, .option-btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }

        .correct-feedback {
            background: #c8e6b5;
            border-left: 12px solid #5fad41;
        }
        .wrong-feedback {
            background: #ffe0d4;
            border-left: 12px solid #e07c4c;
        }

        .feedback-area {
            background: #fff2e5;
            border-radius: 48px;
            padding: 12px 20px;
            margin-top: 10px;
            font-weight: 500;
            text-align: center;
            font-size: 1rem;
        }

        /* панель достижений */
        .achievements-panel {
            background: #fffbee;
            border-radius: 48px;
            padding: 18px 20px;
            margin-top: 30px;
            box-shadow: 0 5px 12px rgba(0,0,0,0.05);
        }

        .achievements-title {
            font-size: 1.4rem;
            font-weight: 800;
            color: #c2601a;
            display: flex;
            align-items: center;
            gap: 12px;
            margin-bottom: 15px;
        }

        .badges-container {
            display: flex;
            flex-wrap: wrap;
            gap: 14px;
            justify-content: center;
        }

        .badge {
            background: #f2e2d0;
            border-radius: 60px;
            padding: 8px 16px;
            display: inline-flex;
            align-items: center;
            gap: 10px;
            font-size: 0.85rem;
            font-weight: 600;
            color: #5d3a1f;
            transition: 0.1s;
            box-shadow: inset 0 0 0 1px #fff8, 0 2px 6px rgba(0,0,0,0.05);
        }

        .badge.locked {
            opacity: 0.5;
            filter: grayscale(0.2);
            background: #e2d3c4;
        }

        .badge.unlocked {
            background: #ffe8b6;
            color: #b45309;
            box-shadow: 0 0 0 2px #ffbc6e, 0 4px 10px rgba(0,0,0,0.1);
        }

        .badge i {
            font-size: 1.3rem;
            width: 24px;
        }

        /* кнопки управления */
        .action-buttons {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 16px;
            margin-top: 20px;
        }

        .game-btn {
            background: #ffcf8a;
            border: none;
            padding: 12px 28px;
            border-radius: 40px;
            font-weight: 800;
            font-size: 1rem;
            font-family: 'Quicksand', sans-serif;
            color: #5a2d00;
            cursor: pointer;
            transition: 0.1s linear;
            display: inline-flex;
            align-items: center;
            gap: 12px;
            box-shadow: 0 5px 0 #b97f3e;
        }

        .game-btn:active {
            transform: translateY(2px);
            box-shadow: 0 2px 0 #b97f3e;
        }

        /* уведомление об окончании */
        .modal-overlay {
            position: fixed;
            top: 0; left: 0;
            width: 100%; height: 100%;
            background: rgba(0,0,0,0.5);
            backdrop-filter: blur(5px);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            visibility: hidden;
            opacity: 0;
            transition: 0.2s;
        }
        .modal-content {
            background: #fff5e6;
            max-width: 400px;
            width: 90%;
            border-radius: 60px;
            padding: 30px;
            text-align: center;
            box-shadow: 0 30px 40px rgba(0,0,0,0.3);
        }
        .modal-content h3 {
            font-size: 2rem;
            color: #e07c2c;
        }
        .close-modal {
            margin-top: 20px;
            background: #ffaa55;
            padding: 10px 25px;
            border-radius: 50px;
            border: none;
            font-weight: bold;
            cursor: pointer;
        }

        @media (max-width: 720px) {
            .game-container { padding: 15px; }
            .term-word { font-size: 2.2rem; }
            .stat-card { font-size: 1rem; padding: 5px 15px; }
            .options-grid { grid-template-columns: 1fr; }
            .badge { font-size: 0.75rem; padding: 5px 12px; }
        }
        footer {
            text-align: center;
            font-size: 0.7rem;
            margin-top: 20px;
            color: #b88d62;
        }
    </style>
</head>
<body>
<div class="game-container" id="gameApp">
    <!-- панель статуса -->
    <div class="stats-bar">
        <div class="stat-card"><i class="fas fa-star"></i> <span id="scoreValue">0</span> очков</div>
        <div class="stat-card timer-box"><i class="fas fa-hourglass-half"></i> <span id="timerDisplay">15:00</span></div>
        <div class="progress-area"><i class="fas fa-layer-group"></i> <span id="questionCounter">1</span> / <span id="totalQuestions">10</span></div>
    </div>

    <!-- карточка термина -->
    <div class="term-card">
        <div class="term-word" id="termWord">SMM</div>
        <div class="term-hint"><i class="fas fa-lightbulb"></i> Выбери правильное определение</div>
    </div>

    <!-- варианты ответов -->
    <div class="options-grid" id="optionsContainer"></div>

    <!-- область обратной связи -->
    <div class="feedback-area" id="feedbackMessage">
        🧠 Нажми на вариант, чтобы проверить знание термина
    </div>

    <!-- панель достижений -->
    <div class="achievements-panel">
        <div class="achievements-title"><i class="fas fa-medal"></i> Достижения и значки <i class="fas fa-grin-tongue-squint"></i></div>
        <div class="badges-container" id="badgesList"></div>
    </div>

    <div class="action-buttons">
        <button class="game-btn" id="resetGameBtn"><i class="fas fa-undo-alt"></i> Новая игра</button>
        <button class="game-btn" id="saveGameBtn"><i class="fas fa-save"></i> Сохранить прогресс</button>
    </div>
    <footer>🎙️ Медиа Крокодил — запомни термины за 15 минут!</footer>
</div>

<!-- модальное окно окончания -->
<div id="endModal" class="modal-overlay">
    <div class="modal-content">
        <i class="fas fa-crown" style="font-size: 3rem; color: gold;"></i>
        <h3 id="modalTitle">Игра завершена!</h3>
        <p id="modalText"></p>
        <button class="close-modal" id="closeModalBtn">Попробовать снова</button>
    </div>
</div>

<script>
    // ---------------------- УЧЕБНЫЙ МАТЕРИАЛ: ТЕРМИНЫ И ОПРЕДЕЛЕНИЯ ----------------------
    const QUESTIONS_DATA = [
        { term: "SMM", correct: "Продвижение бренда или продукта через социальные сети", distractors: ["Создание компьютерных игр", "Управление серверами", "Разработка мобильных приложений"] },
        { term: "Аудитория", correct: "Группа людей, на которую направлен контент", distractors: ["Количество лайков", "Список подписок блогера", "Технические настройки аккаунта"] },
        { term: "Контент", correct: "Любая информация, создаваемая для публикации (тексты, видео, картинки)", distractors: ["Только видеоролики", "Рекламный бюджет", "Программный код сайта"] },
        { term: "Блог", correct: "Веб-сайт или страница, где автор регулярно публикует записи", distractors: ["Короткое видео до 60 секунд", "Платная реклама", "Личное сообщение в соцсети"] },
        { term: "Алгоритм", correct: "Система правил, по которым соцсеть ранжирует посты в ленте", distractors: ["Фотография с высоким разрешением", "План публикаций на месяц", "Анализ хештегов"] },
        { term: "Тизер", correct: "Короткий интригующий анонс, рекламирующий будущий контент", distractors: ["Длинная статья-обзор", "Повтор готового поста", "Техническая ошибка в посте"] },
        { term: "Коллаборация", correct: "Совместный проект двух или более блогеров/брендов", distractors: ["Одиночный стрим", "Удаление старых публикаций", "Автоматическое комментирование"] },
        { term: "Вовлеченность", correct: "Показатель активности аудитории (лайки, комментарии, репосты)", distractors: ["Количество подписчиков", "Частота публикаций", "Возраст подписчиков"] },
        { term: "Копирайтинг", correct: "Написание продающих или вовлекающих текстов", distractors: ["Дизайн обложек", "Съемка видео", "Монтаж звука"] },
        { term: "Хэштег", correct: "Ключевое слово с символом # для группировки постов", distractors: ["Ссылка на сайт", "Система оценки постов", "Фильтр для фото"] }
    ];

    // глобальные переменные игры
    let currentQIndex = 0;
    let score = 0;              // максимум 100 (10*10)
    let timeLeft = 900;        // 15 минут в секундах
    let timerInterval = null;
    let gameActive = true;
    let answerLock = false;     // блокировка после ответа
    let questionStartTime = null;
    let consecutiveCorrect = 0;
    let fastAnswersCount = 0;   // ответы быстрее 5 сек
    let gotSpeedster = false;
    let gotChampion = false;
    let answeredFlags = new Array(10).fill(false);
    let achievementsState = {
        firstBlood: false,
        streak5: false,
        expertAllCorrect: false,
        maxScore: false,
        sprinter: false,
        lightning: false
    };

    // DOM элементы
    const termWordEl = document.getElementById("termWord");
    const optionsContainer = document.getElementById("optionsContainer");
    const scoreSpan = document.getElementById("scoreValue");
    const timerDisplaySpan = document.getElementById("timerDisplay");
    const questionCounterSpan = document.getElementById("questionCounter");
    const totalQSpan = document.getElementById("totalQuestions");
    const feedbackDiv = document.getElementById("feedbackMessage");
    const badgesContainer = document.getElementById("badgesList");
    const resetBtn = document.getElementById("resetGameBtn");
    const saveBtn = document.getElementById("saveGameBtn");
    const modal = document.getElementById("endModal");
    const modalTitle = document.getElementById("modalTitle");
    const modalText = document.getElementById("modalText");
    const closeModalBtn = document.getElementById("closeModalBtn");

    totalQSpan.innerText = QUESTIONS_DATA.length;

    // ------ Вспомогательные функции ------
    function formatTime(seconds) {
        let mins = Math.floor(seconds / 60);
        let secs = seconds % 60;
        return `${mins.toString().padStart(2,'0')}:${secs.toString().padStart(2,'0')}`;
    }

    function updateTimerUI() {
        timerDisplaySpan.innerText = formatTime(timeLeft);
        if (timeLeft <= 0 && gameActive) {
            endGame("Время вышло! ⏰", false);
        }
    }

    function updateScoreUI() {
        scoreSpan.innerText = score;
    }

    function updateProgressUI() {
        questionCounterSpan.innerText = currentQIndex + 1;
    }

    // обновление достижений на панели
    function renderAchievements() {
        const badges = [
            { id: "firstBlood", name: "Первый шаг", icon: "fa-footsteps", desc: "Правильный ответ" },
            { id: "streak5", name: "Пять из пяти", icon: "fa-layer-group", desc: "5 правильных подряд" },
            { id: "sprinter", name: "Спринтер", icon: "fa-bolt", desc: "3 ответа за 5 секунд" },
            { id: "lightning", name: "Чемпион скорости", icon: "fa-gauge-high", desc: "Ответ за 2 секунды" },
            { id: "expertAllCorrect", name: "Эксперт", icon: "fa-graduation-cap", desc: "Все 10 верно" },
            { id: "maxScore", name: "Терминатор", icon: "fa-trophy", desc: "Максимум 100 очков" }
        ];
        badgesContainer.innerHTML = "";
        for (let b of badges) {
            const unlocked = achievementsState[b.id];
            const badgeDiv = document.createElement("div");
            badgeDiv.className = `badge ${unlocked ? "unlocked" : "locked"}`;
            badgeDiv.innerHTML = `<i class="fas ${b.icon}"></i> <span>${b.name}</span>`;
            badgeDiv.title = b.desc;
            badgesContainer.appendChild(badgeDiv);
        }
    }

    // проверка и разблокировка достижений на основе действий
    function checkAchievementsOnAnswer(correct, timeTakenSec, isFirstCorrectEver, newStreak, totalCorrectCount, isMaxScoreNow) {
        if (correct) {
            if (!achievementsState.firstBlood && isFirstCorrectEver) {
                achievementsState.firstBlood = true;
                showFeedbackMessage("🏆 Достижение: Первый шаг!", "#cfa668");
            }
            if (!achievementsState.streak5 && newStreak >= 5) {
                achievementsState.streak5 = true;
                showFeedbackMessage("🔥 Ура! 5 правильных подряд! Значок 'Пять из пяти'", "#e27c2c");
            }
            if (!achievementsState.sprinter && !achievementsState.sprinter && fastAnswersCount >= 3) {
                achievementsState.sprinter = true;
                showFeedbackMessage("⚡ Спринтер! 3 быстрых ответа (<5 сек)!", "#f59e0b");
            }
            if (!achievementsState.lightning && timeTakenSec < 2.0) {
                achievementsState.lightning = true;
                showFeedbackMessage("💥 Молниеносно! Чемпион скорости!", "#ffaa33");
            }
        }
        // после завершения игры проверим эксперт и макс очки
        let allAnswered = answeredFlags.every(v => v === true);
        if (allAnswered && !achievementsState.expertAllCorrect) {
            let allCorrectFlag = true;
            for (let i = 0; i < QUESTIONS_DATA.length; i++) {
                // не храним напрямую, но проверим по score? нам нужно проверить были ли ошибки
                // проще: если счет максимальный (100) или мы отслеживали ошибки – добавим флаг, когда ответ был неверным
                // создадим доп массив errors
            }
        }
        if (score === 100 && !achievementsState.maxScore) {
            achievementsState.maxScore = true;
            showFeedbackMessage("🏅 Идеальный счёт! Ты Терминатор!", "#ca8a04");
        }
        // доп. логика для эксперт: все ответы без ошибок. Используем проверку при завершении
        renderAchievements();
    }

    function finalAchievementsCheck() {
        let hasAnyWrong = false;
        // мы не сохраняли массив правильности ответов в явном виде, поэтому добавим глобальный массив answerCorrectness
        if (window.answerCorrectness && window.answerCorrectness.length === QUESTIONS_DATA.length) {
            hasAnyWrong = window.answerCorrectness.some(v => v === false);
        } else {
            // fallback: если счет 100 значит все верно
            if (score !== 100) hasAnyWrong = true;
        }
        if (!hasAnyWrong && !achievementsState.expertAllCorrect) {
            achievementsState.expertAllCorrect = true;
            showFeedbackMessage("🎓 Эксперт! Все термины освоены!", "#f7b05e");
            renderAchievements();
        }
        if (score === 100 && !achievementsState.maxScore) {
            achievementsState.maxScore = true;
            showFeedbackMessage("💎 Максимум очков! Ты чемпион медиасловаря!", "#d98c2b");
            renderAchievements();
        }
    }

    // завершение игры
    function endGame(reason, isWin = false) {
        if (!gameActive) return;
        if (timerInterval) clearInterval(timerInterval);
        gameActive = false;
        answerLock = true;
        finalAchievementsCheck();
        let finalMessage = reason + "\n✨ Твой результат: " + score + " очков.\n";
        if (score === 100) finalMessage += "🎉 Блестяще! Ты мастер медиатерминов!";
        else if (score >= 70) finalMessage += "Отлично! Совсем немного до эксперта.";
        else finalMessage += "Повтори термины и попробуй ещё раз!";
        modalTitle.innerText = isWin ? "🏆 ПОБЕДА!" : "⏰ Игра окончена";
        modalText.innerText = finalMessage;
        modal.style.visibility = "visible";
        modal.style.opacity = "1";
        // сохраним состояние в локал сторедж не нужно, игра кончилась
        localStorage.removeItem("mediaCrocGameSave");
    }

    // остановить таймер и начать новый
    function startTimer() {
        if (timerInterval) clearInterval(timerInterval);
        timerInterval = setInterval(() => {
            if (!gameActive) return;
            if (timeLeft <= 1) {
                timeLeft = 0;
                updateTimerUI();
                endGame("Время вышло! Попробуй снова.", false);
                clearInterval(timerInterval);
            } else {
                timeLeft--;
                updateTimerUI();
            }
        }, 1000);
    }

    // загрузить вопрос
    function loadQuestion() {
        if (!gameActive) return;
        if (currentQIndex >= QUESTIONS_DATA.length) {
            endGame("Ты ответил на все вопросы! Поздравляем!", true);
            return;
        }
        const q = QUESTIONS_DATA[currentQIndex];
        termWordEl.innerText = q.term;
        // перемешиваем варианты: правильный + дистракторы
        let allOptions = [q.correct, ...q.distractors];
        for (let i = allOptions.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [allOptions[i], allOptions[j]] = [allOptions[j], allOptions[i]];
        }
        optionsContainer.innerHTML = "";
        allOptions.forEach(opt => {
            const btn = document.createElement("div");
            btn.classList.add("option-btn");
            btn.innerText = opt;
            btn.addEventListener("click", () => handleAnswer(opt, q.correct));
            optionsContainer.appendChild(btn);
        });
        answerLock = false;
        questionStartTime = Date.now();
        updateProgressUI();
        // сброс стилей
        feedbackDiv.innerHTML = "🤔 Выбери правильное определение...";
        feedbackDiv.style.background = "#fff2e5";
    }

    function handleAnswer(selected, correctAnswer) {
        if (!gameActive || answerLock) return;
        answerLock = true;
        const isCorrect = (selected === correctAnswer);
        const timeSpent = (Date.now() - questionStartTime) / 1000;
        let pointsEarned = 0;
        if (isCorrect) {
            pointsEarned = 10;
            score += pointsEarned;
            consecutiveCorrect++;
            if (timeSpent < 5.0) {
                fastAnswersCount++;
            }
            updateScoreUI();
            showFeedbackMessage(`✅ Верно! +10 очков. (${timeSpent.toFixed(1)} сек)`, "#b0d98c");
            // сохранение корректности ответа
            if (!window.answerCorrectness) window.answerCorrectness = new Array(QUESTIONS_DATA.length).fill(false);
            window.answerCorrectness[currentQIndex] = true;
        } else {
            consecutiveCorrect = 0;
            showFeedbackMessage(`❌ Неверно! Правильный ответ: "${correctAnswer}". Запомни!`, "#ffccbb");
            if (!window.answerCorrectness) window.answerCorrectness = new Array(QUESTIONS_DATA.length).fill(false);
            window.answerCorrectness[currentQIndex] = false;
        }
        answeredFlags[currentQIndex] = true;
        // проверим первый правильный ответ
        let anyCorrectBefore = false;
        for (let i=0; i<currentQIndex; i++) if (answeredFlags[i] && window.answerCorrectness?.[i]) anyCorrectBefore = true;
        const isFirstCorrectEver = isCorrect && !anyCorrectBefore && (consecutiveCorrect === 1 || (window.answerCorrectness && window.answerCorrectness.filter(v=>v===true).length === 1));
        checkAchievementsOnAnswer(isCorrect, timeSpent, isFirstCorrectEver, consecutiveCorrect, null, score===100);

        // сохраняем состояние после каждого хода
        saveGameToLocalStorage();

        // переход на следующий вопрос после паузы
        setTimeout(() => {
            if (gameActive) {
                currentQIndex++;
                if (currentQIndex < QUESTIONS_DATA.length) {
                    loadQuestion();
                } else {
                    endGame("Поздравляем! Ты завершил игру!", true);
                }
            }
            answerLock = false;
        }, 800);
    }

    function showFeedbackMessage(msg, bgColor) {
        feedbackDiv.innerHTML = `<i class="fas fa-comment-dots"></i> ${msg}`;
        feedbackDiv.style.background = bgColor || "#fff0e0";
        setTimeout(() => {
            if (feedbackDiv && gameActive) feedbackDiv.style.background = "#fff2e5";
        }, 1300);
    }

    // сохранение прогресса (localStorage)
    function saveGameToLocalStorage() {
        if (!gameActive) return;
        const saveData = {
            currentQIndex, score, timeLeft, consecutiveCorrect, fastAnswersCount,
            achievementsState, answeredFlags, gameActive: true,
            answerCorrectness: window.answerCorrectness || new Array(QUESTIONS_DATA.length).fill(false),
            timestamp: Date.now()
        };
        localStorage.setItem("mediaCrocGameSave", JSON.stringify(saveData));
    }

    function loadSavedGame() {
        const raw = localStorage.getItem("mediaCrocGameSave");
        if (!raw) return false;
        try {
            const data = JSON.parse(raw);
            if (data.gameActive && data.currentQIndex < QUESTIONS_DATA.length) {
                currentQIndex = data.currentQIndex;
                score = data.score;
                timeLeft = data.timeLeft;
                consecutiveCorrect = data.consecutiveCorrect || 0;
                fastAnswersCount = data.fastAnswersCount || 0;
                achievementsState = data.achievementsState || achievementsState;
                answeredFlags = data.answeredFlags || new Array(QUESTIONS_DATA.length).fill(false);
                window.answerCorrectness = data.answerCorrectness || new Array(QUESTIONS_DATA.length).fill(false);
                gameActive = true;
                answerLock = false;
                updateScoreUI();
                updateTimerUI();
                if (timerInterval) clearInterval(timerInterval);
                startTimer();
                loadQuestion();
                renderAchievements();
                return true;
            }
        } catch(e) {}
        return false;
    }

    function resetGame(keepLocal = false) {
        if (timerInterval) clearInterval(timerInterval);
        currentQIndex = 0;
        score = 0;
        timeLeft = 900;
        consecutiveCorrect = 0;
        fastAnswersCount = 0;
        answeredFlags.fill(false);
        gameActive = true;
        answerLock = false;
        achievementsState = { firstBlood: false, streak5: false, expertAllCorrect: false, maxScore: false, sprinter: false, lightning: false };
        window.answerCorrectness = new Array(QUESTIONS_DATA.length).fill(false);
        updateScoreUI();
        updateTimerUI();
        renderAchievements();
        loadQuestion();
        startTimer();
        if (!keepLocal) localStorage.removeItem("mediaCrocGameSave");
    }

    // Инициализация
    function initGame() {
        const hasSave = localStorage.getItem("mediaCrocGameSave");
        if (hasSave) {
            const confirmResume = confirm("🔄 Найдена сохранённая игра. Продолжить? (Нажми «Отмена» для новой игры)");
            if (confirmResume) {
                const loaded = loadSavedGame();
                if (!loaded) resetGame(false);
            } else {
                resetGame(false);
            }
        } else {
            resetGame(false);
        }
    }

    // события кнопок
    resetBtn.addEventListener("click", () => {
        if (timerInterval) clearInterval(timerInterval);
        resetGame(false);
    });
    saveBtn.addEventListener("click", () => {
        if (gameActive) {
            saveGameToLocalStorage();
            showFeedbackMessage("💾 Прогресс сохранён! (состояние игры запомнено)", "#e6d5b8");
        } else {
            showFeedbackMessage("Игра окончена, сохранять нечего. Начни новую", "#ffe0cc");
        }
    });
    closeModalBtn.addEventListener("click", () => {
        modal.style.visibility = "hidden";
        modal.style.opacity = "0";
        resetGame(false);
    });

    initGame();
</script>
</body>
</html>

Game Source: Медиа Крокодил — Карточки терминов

Creator: CrystalFox63

Libraries: none

Complexity: complex (748 lines, 32.1 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: -crystalfox63" to link back to the original. Then publish at arcadelab.ai/publish.