Остановка функции после остановки таймера

Я делаю игру и хочу, чтобы функция игры останавливалась, как только таймер достиг 0. В настоящее время игра сбрасывается только при нажатии кнопки сброса.

Таймер сбрасывается, однако пользователь может продолжать нажимать на поля и продолжать игру, вместо того, чтобы снова нажимать «Пуск».

Это моя игровая функция:

function startGame() {
    changedBox = null;
    let allBoxes = document.getElementsByClassName("box");
    for (let i = 0; i < allBoxes.length; i++) {
        allBoxes[i].style.backgroundColor = "#e7014c";
    }
    let randomBox = Math.floor(Math.random() * allBoxes.length);
    changedBox = allBoxes[randomBox].id;
    document.getElementById(changedBox).style.backgroundColor = randomColor();

    clearInterval(intervalId);
    intervalId = setInterval(function () {
        let randomBox = Math.floor(Math.random() * allBoxes.length);
        changedBox = allBoxes[randomBox].id;
        document.getElementById(changedBox).style.backgroundColor = randomColor();
    }, 2000);
    if (seconds < 0) {
        return;
    }
}

Это моя функция кнопки запуска, которая также останавливает таймер:

let startButton = document.getElementById("start-game");
startButton.addEventListener("click", function () {
    startGame();
    countDown = setInterval(function () {
        document.getElementById("timer").innerHTML = seconds;
        seconds--;
        if (seconds < 0) {
            clearInterval(countDown);
            document.getElementById("timer").innerHTML = "Times up!";
            resetGame();
        }
    }, 1000);
});

Функция сброса игры

    function resetGame() {
        clearInterval(intervalId);
        clearInterval(countDown);
        clicks = 0;
        level = 1;
        seconds = 20;
        timer = 20;
        document.getElementById("clicks").innerText = 0;
        document.getElementById("level").innerText = level;
        document.getElementById("timer").innerText = seconds;
        let allBoxes = document.getElementsByClassName("box");
        for (let i = 0; i < allBoxes.length; i++) {
            allBoxes[i].style.backgroundColor = "#e7014c";
        }
    }

Изменяет цвета ящиков в игре:

    function changeBackground(boxId) {
        if (seconds < 0) {
            return;
        }
        if (intervalId) {
            if (boxId === changedBox) {
                clearInterval(intervalId);
                increaseClicks();
                startGame();
                console.info('box clicked');
            } else {
                clearInterval(intervalId);
                alert('Sorry Wrong Box, Try again!');
                console.info('wrong box');
            }
        }
    }

Я перепробовал все, что мог придумать, и игра просто продолжается.

Я попытался добавить функцию resetGame в функцию startGame.

Любая помощь будет действительно оценена!

Добро пожаловать в СО! Пожалуйста, включите любой соответствующий HTML, чтобы сделать этот минимальный воспроизводимый пример. Кроме того, пожалуйста, включите свой код для resetGame(); Мое лучшее предположение, не имея возможности увидеть полную игру, заключается в том, что прослушиватели событий не удаляются, когда игра заканчивается или перезапускается, поэтому пользователь может продолжать взаимодействовать с ящиками.

WOUNDEDStevenJones 08.08.2023 20:28

Где-нибудь объявлены секунды? В вашем коде секунды нигде не объявляются

imvain2 08.08.2023 20:31

Привет! Извините, что пишу первый раз. Я добавил функцию resetGame и функцию changeBackground. Секунды объявлены в переменных ``` // Переменные let intervalId; пусть changeBox = ноль; пусть уровень = 1; пусть кликов = 0; пусть секунды = 20; пусть обратный отсчет; пусть totalClicks = 0; пусть таймер = 20; ``` Если это поможет, это моя ссылка на github для этого проекта github.com/sarahgoodwin93/project2-colourchange-challenge

sg93 08.08.2023 20:42

Проблема в том, что когда вы используете clearInterval, переменная interval по-прежнему содержит ссылку на setInterval. Таким образом, оператор if if (intervalId) все равно будет оцениваться как истинный. Для простого решения, после того, как вы очистите его, попробуйте intervalId = null;

imvain2 08.08.2023 21:27

Спасибо за вашу помощь! Мне нужно было добавить в функции переменную gameActive, чтобы они работали только при включенной игре :)

sg93 08.08.2023 21:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я вижу, что если вы играете в свою игру и время истекло, вы можете продолжать щелкать ячейками в своем игровом столе. Вы получаете сообщение об ошибке, но да, вы можете продолжать нажимать (то есть играть).

Одна вещь, которую вы можете сделать, это когда время истекло (то есть игра окончена), в дополнение к индикации времени на экране, вы можете удалить div игрового стола, чтобы пользователь больше не мог играть. Итак, в вашем Click eventListener на кнопке «Начать игру» вы заменяете вызов resetGame(); с document.getElementById("game-table".style.display = 'none'; чтобы игровой стол исчез.

let startButton = document.getElementById("start-game");
startButton.addEventListener("click", function () {
  startGame();
  countDown = setInterval(function () {
      document.getElementById("timer").innerHTML = seconds;
      seconds--;
      if (seconds < 0) {
        clearInterval(countDown);
        document.getElementById("timer").innerHTML = "Times up!";
        document.getElementById("game-table".style.display = 'none';
      }
  }, 1000);
});

Затем в вашей функции restGame() добавьте блок, чтобы игровой стол Div снова появился:

if (document.getElementById('game-table').style.display == 'none') {
  document.getElementById('game-table').style.display = 'flex';
}

Также в вашей функции StartGame() добавьте галочку прямо под changeBox = null; и вызовите функцию resetGame для соответствующего сброса, если игра уже пройдена.

if (document.getElementById('game-table').style.display == 'none') {
  resetGame();
}
Ответ принят как подходящий

Я просмотрел код и запустил его. Этот код должен решить вашу проблему с тем, что игра не останавливается, а пользователь все еще может щелкать поля.

// Variables
let intervalId;
let changedBox = null;
let level = 1;
let clicks = 0;
let seconds = 20;
let countDown;
let totalClicks = 0;
let gameActive = false;

/** COLOUR ARRAY
 * List of colours that the game can choose from to keep the site design with pastel colours
 */
let colors = ["#ffb5e8", "#d5aaff", "#6eb5ff", "#faf99d", "#bffcc6",
    "#ffabab", "#ff9cee", "#ffcf9e", "#b28dff", "#c4faf8", "#fff5ba", "#ffbebc", "#c4faf8"];

/** WHICH BOX HAS CHANGED
 * This if statement checks if the box that has been clicked matches the box that has changed colour
 * If the correct box is clicked, the increaseClicks function is called.
 * If user clicks on the wrong box the below message will appear
 */
function changeBackground(boxId) {
    if (!gameActive) {
        return;
    }

    if (seconds < 0) {
        return;
    }
    if (intervalId) {
        if (boxId === changedBox) {
            clearInterval(intervalId);
            increaseClicks();
            startGame();
            console.info('box clicked');
        } else {
            clearInterval(intervalId);
            alert('Sorry Wrong Box, Try again!');
            console.info('wrong box');
        }
    }
}

/** RANDOM COLOURS
 * This function runs through the array of colours outlined in the variable 'colors'
 * So that they are randomly selected
 */
function randomColor() {
    let randomColors = Math.floor(Math.random() * colors.length);
    return colors[randomColors];
}

/** START GAME FUNCTION
 * This function begins by making sure the changedBox is resert to null at the beginning of each round.
 * The for loop goes through each box and makes sure its background is set to the original pink colour.
 * The randomBox will change colour, and calls the randomColor function written above.
 * The clear interval clears the previouis internal is stoped before starting a new one.
 * This was impliments so that the colours did not all change together.
 * An internvial is set to change the boxes every 2 seconds
 */
function startGame() {
    changedBox = null;
    let allBoxes = document.getElementsByClassName("box");
    for (let i = 0; i < allBoxes.length; i++) {
        allBoxes[i].style.backgroundColor = "#e7014c";
        allBoxes[i].disabled = false; // Enable grid buttons
    }
    let randomBox = Math.floor(Math.random() * allBoxes.length);
    changedBox = allBoxes[randomBox].id;
    document.getElementById(changedBox).style.backgroundColor = randomColor();
    clearInterval(intervalId);
    intervalId = setInterval(function () {
        let randomBox = Math.floor(Math.random() * allBoxes.length);
        changedBox = allBoxes[randomBox].id;
        document.getElementById(changedBox).style.backgroundColor = randomColor();
    }, 2000);
}

// SCORE SECTION
function increaseClicks() {
    let currentClicks = parseInt(document.getElementById("clicks").innerText);
    let newClicks = currentClicks + 1;
    document.getElementById("clicks").innerText = newClicks;
    totalClicks++;
    document.getElementById("total-clicks").innerText = totalClicks;
}

// START GAME WITH CLICK
let startButton = document.getElementById("start-game");
startButton.addEventListener("click", function () {
    if (!gameActive) {
        startGame();
        countDown = setInterval(function () {
            document.getElementById("timer").innerHTML = seconds;
            seconds--;

            if (seconds < 0) {
                clearInterval(countDown);
                document.getElementById("timer").innerHTML = "Times up!";
                gameActive = false;
                resetButton.disabled = false; // Enable reset button when game ends
            }
        }, 1000);
        resetButton.disabled = false; // Enable reset game if start button is clicked
        gameActive = true;
    }
});

// RESET GAME
function resetGame() {
    clearInterval(intervalId);
    clearInterval(countDown);
    clicks = 0;
    level = 1;
    seconds = 20;
    document.getElementById("clicks").innerText = 0;
    document.getElementById("level").innerText = level;
    let allBoxes = document.getElementsByClassName("box");
    for (let i = 0; i < allBoxes.length; i++) {
        allBoxes[i].style.backgroundColor = "#e7014c";
        allBoxes[i].disabled = true; // Disable grid buttons
    }
    gameActive = false; // Set the game state to inactive
    resetButton.disabled = true; // Disable Reset button after resetting the game
    startButton.disabled = false; // Enable the Start button
}

// LEVEL
function addLevel() {
    let currentLevel = parseInt(document.getElementById("level").innerText);
    let newLevel = currentLevel + 1;
    document.getElementById("level").innerText = newLevel;
}

// RESET BUTTON
let resetButton = document.getElementById("reset");
resetButton.addEventListener("click", resetGame);

Я использовал флаговую переменную gameActive, чтобы проверить, активна ли игра, и соответственно отключить сетку 4x4, а также соответствующим образом изменить функции. Функция stopBoxes() была удалена, поскольку она была избыточной. Попробуйте. Хотя в вашей игре есть и другие возможные ошибки, например, если пользователь нажимает на старое выделенное поле, он получает неверное сообщение, что не имеет логического смысла.

Другие вопросы по теме