Javascript & JQuery 问答游戏第二轮未定义的范围

Scope of undefined in 2nd round of a Javascript & JQuery Trivia game

我的游戏在点击摘要页面开始 link 之前一直有效。然后,当我再次尝试玩游戏时,我得到了未定义的变量。

我是 JS 的新手,所以我确定这是一个愚蠢的用户错误,没有正确处理范围。

如果我在 javascript 底部评论 location.reload 它在计时器启动后工作正常,但编码分配要求我们不要刷新。感谢您的帮助!

$(document).ready(function() {
  var correctAnswers = 0;
  var incorrectAnswers = 0;
  var unansweredQuestions = 0;
  var timeRemaining = 16;
  var intervalID;
  var indexQandA = 0;
  var answered = false;
  var correct;

  var start = $(".start").html("Start Game");
  start.on("click", startGame);

  var triviaQandA = [{
    question: "What is the fastest animal?",
    answer: ["cheetah", "turtle", "giraffe", "elephant"],
    correct: "0",
    image: ("assets/images/circle.png")
  }, {
    question: "When you are blue you turn?",
    answer: ["red", "green", "blue", "yellow"],
    correct: "2",
    image: ("assets/images/dot.jpg")
  }];

  function startGame() {
    $(".start").hide();
    correctAnswers = 0;
    incorrectAnswers = 0;
    unansweredQuestions = 0;
    loadQandA();
  }

  function loadQandA() {
    answered = false;
    timeRemaining = 16;
    intervalID = setInterval(timer, 1000);
    if (answered === false) {
      timer();
    }

    correct = triviaQandA[indexQandA].correct;
    var question = triviaQandA[indexQandA].question;
    $(".question").html(question);
    for (var i = 0; i < 4; i++) {
      var answer = triviaQandA[indexQandA].answer[i];
      $(".answers").append("<h4 class = answersAll id =" + i + ">" + answer + "</h4>");
    }

    $("h4").click(function() {
      var id = $(this).attr("id");
      if (id === correct) {
        answered = true;
        $(".question").text("The answer is: " + triviaQandA[indexQandA].answer[correct]);
        correctAnswer();
      } else {
        answered = true;
        $(".question").text("You chose: " + triviaQandA[indexQandA].answer[id] + "    the correct answer is: " + triviaQandA[indexQandA].answer[correct]);
        incorrectAnswer();
      }
      console.log(correct);
    });
  }

  function timer() {
    if (timeRemaining === 0) {
      answered = true;
      clearInterval(intervalID);
      $(".question").text("The correct answer is: " + triviaQandA[indexQandA].answer[correct]);
      unAnswered();
    } else if (answered === true) {
      clearInterval(intervalID);
    } else {
      timeRemaining--;
      $(".timeRemaining").text("You have " + timeRemaining);
    }
  }

  function correctAnswer() {
    correctAnswers++;
    $(".timeRemaining").text("You are spot on!!!").css({
      "color": "#3d414f"
    });
    reset();
  }

  function incorrectAnswer() {
    incorrectAnswers++;
    $(".timeRemaining").text("You are sooo wrong").css({
      "color": "#3d414f"
    });
    reset();
  }

  function unAnswered() {
    unansweredQuestions++;
    $(".timeRemaining").text("You didn't choose anything...").css({
      "color": "#3d414f"
    });
    reset();
  }

  function reset() {
    $(".answersAll").remove();
    $(".answers").append("<img class=answerImage width='150' height='150' src='" + triviaQandA[indexQandA].image + "'>");
    indexQandA++;
    if (indexQandA < triviaQandA.length) {
      setTimeout(function() {
        loadQandA();
        $(".answerImage").remove();
      }, 2000);
    } else {
      setTimeout(function() {
        $(".question").remove();
        $(".timeRemaining").remove();
        $(".answerImage").remove();
        $(".answers").append("<h4 class = answersAll end>Correct answers: " + correctAnswers + "</h4>");
        $(".answers").append("<h4 class = answersAll end>Wrong answers: " + incorrectAnswers + "</h4>");
        $(".answers").append("<h4 class = answersAll end>Unanswered questions: " + unansweredQuestions + "</h4>");
        correctAnswers = 0;
        incorrectAnswers = 0;
        unansweredQuestions = 0;
        // setTimeout(function() {
        //     location.reload();
        // }, 5000);

        var start = $(".start-over").html("Start Game");
        start.on("click", startGame);
      }, 2000);
    }
  };


});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

<div class="start"></div>
<h1>Trivia</h1>
<h5 class="timeRemaining"></h5>
<h3 class="question"></h3>
<div class="answers"></div>
<div class="start-over"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

这是我的 Codepen 的内联 link。

问题是因为您在每个问题上增加了 indexQandA,但从未重置它。您需要在开始新游戏时将其重置为 0 - 也就是说,在 reset 函数的 else 子句中,您需要将 indexQandA=0 放在您将其他变量重置为 0 的位置.

完成后还有一个问题,测验 运行 现在第二次可以了,但不再显示问题。那是因为您在 reset 期间删除了 .question 元素。这个可以不用,直接隐藏,重启游戏再显示即可。

其实后来发现还有问题。我已经解决了 - 运行 连续 5 次通过游戏,没有明显的问题 - 使用以下代码(我没有声称这是正确的代码,它只是对你的最小改动让它工作的现有代码):

$(document).ready(function() {

var correctAnswers = 0;
var incorrectAnswers = 0;
var unansweredQuestions = 0;
var timeRemaining = 16;
var intervalID;
var indexQandA = 0;
var answered = false;
var correct;
    
    var start = $(".start").html("Start Game");
    start.on("click", startGame);
  $(".start-over").on("click", startGame);
    
var triviaQandA = [{
    question:"What is the fastest animal?",
    answer:["cheetah","turtle","giraffe","elephant"],
    correct:"0",
    image: ("assets/images/circle.png")
}, { 
    question:"When you are blue you turn?",
    answer:["red","green","blue","yellow"],
    correct:"1",
    image: ("assets/images/dot.jpg")
}];

function startGame() {
    $(".summary").hide();
    $(".start").hide();
    $(".timeRemaining").show();
    $(".question").show();
    $(".answers").show();
    $(".start-over").hide();
    correctAnswers = 0;
    incorrectAnswers = 0;
    unansweredQuestions = 0;
    loadQandA();
}

function loadQandA() {
    answer = [];
    answered = false;
    timeRemaining = 16;
    timer();
    intervalID = setInterval(timer, 1000);
    /*if (answered === false) {
        timer();
    }*/
    
    correct = triviaQandA[indexQandA].correct;
    var question = triviaQandA[indexQandA].question;
    $(".question").html(question);
    for (var i = 0; i < 4; i++) {
        var answer = triviaQandA[indexQandA].answer[i];
        $(".answers").append("<h4 class = answersAll id =" + i + ">" + answer + "</h4>");
    }

    $("h4").click(function() {
        var id = $(this).attr("id");
        if (id === correct) {
            answered = true;
            $(".question").text("The answer is: " + triviaQandA[indexQandA].answer[correct]);
            correctAnswer();
        } else {
            answered = true;
            $(".question").text("You chose: " + triviaQandA[indexQandA].answer[id] + "    the correct answer is: " + triviaQandA[indexQandA].answer[correct]);
            incorrectAnswer();
        }
        console.log(correct);
    });
}

function timer() {
    if (timeRemaining === 0) {
        answered = true;
        //clearInterval(intervalID);
        $(".question").text("The correct answer is: " + triviaQandA[indexQandA].answer[correct]);
        unAnswered();
    } else if (answered === true) {
        //clearInterval(intervalID);
    } else {
        timeRemaining--;
        $(".timeRemaining").text("You have " + timeRemaining);
    }
}

function correctAnswer() {
    correctAnswers++;
    $(".timeRemaining").text("You are spot on!!!").css({
        "color": "#3d414f"
    });
    reset();
}

function incorrectAnswer() {
    incorrectAnswers++;
    $(".timeRemaining").text("You are sooo wrong").css({
        "color": "#3d414f"
    });
    reset();
}

function unAnswered() {
    unansweredQuestions++;
    $(".timeRemaining").text("You didn't choose anything...").css({
        "color": "#3d414f"
    });
    reset();
}

function reset() {
      clearInterval(intervalID);
    $(".answersAll").remove();
    $(".answers").append("<img class=answerImage width='150' height='150' src='" + triviaQandA[indexQandA].image + "'>");
    indexQandA++;
    if (indexQandA < triviaQandA.length) {
        setTimeout(function () {
            loadQandA();
            $(".answerImage").remove();
        }, 2000);
    } else {
        setTimeout(function() {
            $(".summary").show();
            $(".question").hide();
            $(".timeRemaining").hide();
            $(".answers").hide();
            $(".start-over").show();
            $(".answerImage").remove();
            $(".summary").append("<h4 class = answersAll end>Correct answers: " + correctAnswers + "</h4>");
            $(".summary").append("<h4 class = answersAll end>Wrong answers: " + incorrectAnswers + "</h4>");
            $(".summary").append("<h4 class = answersAll end>Unanswered questions: " + unansweredQuestions + "</h4>");
            correctAnswers = 0;
            incorrectAnswers = 0;
            unansweredQuestions = 0;
            indexQandA=0;
            // setTimeout(function() {
            //     location.reload();
            // }, 5000);
    
            $(".start-over").html("Start Game");
            start.on("click", startGame);
        }, 2000);
    }
};

    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
    <div class="start"></div>
    <h1>Trivia</h1>
    <h5 class="timeRemaining"></h5>
    <h3 class="question"></h3>
    <div class="answers"></div>
    <div class="summary"></div>
    <div class="start-over"></div>

</body>
</html>

您的代码最初存在 2 个主要问题:

  • 最严重的是,每次调用 reset 函数时,您都将 startGame 添加为 "start over" 按钮的 click 处理程序。结果,当您玩第 3 次、第 4 次、第 5 次...时,多个此类处理程序被添加,结果 startGame 函数被多次调用,这就是为什么您得到多次打印答案选项。我通过完全删除该部分代码并在页面加载时添加一次事件侦听器来解决此问题。
  • 你的计时器也有点失控,因为你手动调用 timer 函数以及每秒使用 setInterval 到 运行 它,而且你也不总是这样回答问题时清除它。我已经大大简化了它,并使其工作,只需像以前一样在 loadQandA 中设置计时器,并在 reset 函数中清除它。

您会看到我主要只是将内容注释掉,而不是删除它们 - 希望这能让您更容易看到我删除的内容。