开发者问题收集

JS 测验:正确答案识别问题

2022-12-15
85

我正在开发一个小型 JavaScript 测验来练习语言并将项目添加到我的投资组合中。

到目前为止,我已经成功实现了随机问题和选择、计时器、进度条和分数计数器。

但是,我无法让我的代码识别用户提交选项的事实,该选项应该被注册为正确并亮起绿色。作为修复,我尝试将答案放入单独的数组中,并让代码通过将答案选项与所述答案数组进行匹配来检查正确性。这导致我的代码将所有用户输入识别为不正确。

请在下面找到我的项目的可运行示例。您会注意到选项仍然亮起绿色或红色,但它们没有考虑随机选择,因此错误地通知用户他们的成功。为了实用,我淡化了 CSS 和 HTML 方面,并将问题对象减少到 3 个项目。

我非常感谢在这方面的一些建议。非常感谢您抽出时间,我期待了解如何解决这个问题。

const question = document.querySelector('#question');
const choices = Array.from(document.querySelectorAll('.choice-text'));
const progressText = document.querySelector('#progressText');
const scoreText = document.querySelector('#score');
const progressBarFull = document.querySelector('#progressBarFull');
const SCORE_POINTS = 10;
const MAX_QUESTIONS = 3;

let currentQuestion = {};
let acceptingAnswers = true;
let score = 0;
let questionCounter = 0;
let availableQuestions = [];

/* Object containing the questions of the quiz game. */
let questions = [{
    question: 'According to Roman mythology, who was the father of Romulus and Remus?',
    choice1: 'A wolf',
    choice2: 'King Numitor',
    choice3: 'Jupiter',
    choice4: 'Mars',
    answer: 4,
  },
  {
    question: 'Which was the first Roman road?',
    choice1: 'Via Egnatia',
    choice2: 'Via Valeria',
    choice3: 'Via Appia',
    choice4: 'Via Flaminia',
    answer: 3,
  },
  {
    question: 'Which of the following did not defeat Mithridates VI of Pontus?',
    choice1: 'Lucullus',
    choice2: 'Marius',
    choice3: 'Pompey',
    choice4: 'Sulla',
    answer: 2,
  }
]

// Start game by setting default hud values
function startGame() {
  questionCounter = 0;
  score = 0;
  availableQuestions = [...questions]; /* Spread operator */
  getNewQuestion()
}

//Randomize question choices
shuffle = array => {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}

//Get new question and increment the question counter
getNewQuestion = () => {
  if (availableQuestions.length === 0 || questionCounter >= MAX_QUESTIONS) {
    localStorage.setItem('mostRecentScore', score);

    return window.location.assign('index.html') /* Take player to end game*/
  }

  questionCounter++;

  const questionsIndex = Math.floor(Math.random() * availableQuestions.length);
  currentQuestion = availableQuestions[questionsIndex];
  question.innerText = currentQuestion.question;

  //Locate choices
  const answerChoices = [
    currentQuestion.choice1,
    currentQuestion.choice2,
    currentQuestion.choice3,
    currentQuestion.choice4,
  ];

  //Call randomize choices function
  shuffle(answerChoices);

  //Display randomized choices  
  choices.forEach((choice, index) => {
    choice.innerHTML = answerChoices[index];
  });

  availableQuestions.splice(questionsIndex, 1);

  acceptingAnswers = true;
}

//Check answer if correct (Currently can't detect the right answer in randomized choices)
choices.forEach(choice => {
  choice.addEventListener('click', e => {
    if (!acceptingAnswers) return

    acceptingAnswers = false;
    const selectedChoice = e.target;
    const selectedAnswer = selectedChoice.dataset['number'];

    let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect';

    if (classToApply === 'correct') {
      incrementScore(SCORE_POINTS);
    }

    selectedChoice.parentElement.classList.add(classToApply);

    setTimeout(() => {
      selectedChoice.parentElement.classList.remove(classToApply);
      getNewQuestion();
    }, 1000);
  })
})

incrementScore = num => {
  score += num;
  scoreText.innerText = score;
}

startGame()
.choice-container {
  color: var(--basic-black);
  display: flex;
  margin-bottom: 1rem;
  width: 100%;
  border-radius: 4px;
  background-color: var(--honey-yellow);
  font-size: 3rem;
  min-width: 40rem;
}

.choice-prefix {
  padding: 1.5rem 1.5rem;
  color: var(--basic-black);
}

.correct {
  background: green;
}

.incorrect {
  background: red;
}
<div id="game" class="justify-center flex-column">
  <div id="hud">
    <div class="hud-item">
      <p id="progressText" class="hud-prefix">
        Question
      </p>
      <div id="progressBar">
        <div id="progressBarFull"></div>
      </div>
    </div>
    <div class="hud-item">
      <p class="hud-prefix">
        Score
      </p>
      <h1 class="hud-main-text" id="score">
        0
      </h1>
    </div>
  </div>
  <h1 id="question">Sample Question?</h1>
  <div class="choice-container">
    <p class="choice-prefix">I.</p>
    <p class="choice-text" data-number="1">Choice 1</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">II.</p>
    <p class="choice-text" data-number="2">Choice 2</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">III.</p>
    <p class="choice-text" data-number="3">Choice 3</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">IV.</p>
    <p class="choice-text" data-number="4">Choice 4</p>
  </div>
</div>
1个回答

代码还有改进的空间,但 OP 的错误源于标记中的 data-number 是一个字符串,而问题对象的答案由 int 表示。通过转换其中一个或另一个来修复。

请参阅代码片段中的注释...

const question = document.querySelector('#question');
const choices = Array.from(document.querySelectorAll('.choice-text'));
const progressText = document.querySelector('#progressText');
const scoreText = document.querySelector('#score');
const progressBarFull = document.querySelector('#progressBarFull');
const SCORE_POINTS = 10;
const MAX_QUESTIONS = 3;

let currentQuestion = {};
let acceptingAnswers = true;
let score = 0;
let questionCounter = 0;
let availableQuestions = [];

/* Object containing the questions of the quiz game. */
let questions = [{
    question: 'According to Roman mythology, who was the father of Romulus and Remus?',
    choice1: 'A wolf',
    choice2: 'King Numitor',
    choice3: 'Jupiter',
    choice4: 'Mars',
    answer: 4,
  },
  {
    question: 'Which was the first Roman road?',
    choice1: 'Via Egnatia',
    choice2: 'Via Valeria',
    choice3: 'Via Appia',
    choice4: 'Via Flaminia',
    answer: 3,
  },
  {
    question: 'Which of the following did not defeat Mithridates VI of Pontus?',
    choice1: 'Lucullus',
    choice2: 'Marius',
    choice3: 'Pompey',
    choice4: 'Sulla',
    answer: 2,
  }
]

// Start game by setting default hud values
function startGame() {
  questionCounter = 0;
  score = 0;
  availableQuestions = [...questions]; /* Spread operator */
  getNewQuestion()
}

//Randomize question choices
shuffle = array => {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}

//Get new question and increment the question counter
getNewQuestion = () => {
  if (availableQuestions.length === 0 || questionCounter >= MAX_QUESTIONS) {
    localStorage.setItem('mostRecentScore', score);

    return window.location.assign('index.html') /* Take player to end game*/
  }

  questionCounter++;

  const questionsIndex = Math.floor(Math.random() * availableQuestions.length);
  currentQuestion = availableQuestions[questionsIndex];
  question.innerText = currentQuestion.question;

  //Locate choices
  const answerChoices = [
    currentQuestion.choice1,
    currentQuestion.choice2,
    currentQuestion.choice3,
    currentQuestion.choice4,
  ];

  //Call randomize choices function
  shuffle(answerChoices);

  //Display randomized choices  
  choices.forEach((choice, index) => {
    choice.innerHTML = answerChoices[index];
  });

  availableQuestions.splice(questionsIndex, 1);

  acceptingAnswers = true;
}

//Check answer if correct (Currently can't detect the right answer in randomized choices)
choices.forEach(choice => {
  choice.addEventListener('click', e => {
    if (!acceptingAnswers) return

    acceptingAnswers = false;
    const selectedChoice = e.target;

    // HERE: the + sign coerces the string from the markup into an int
    const selectedAnswer = +selectedChoice.dataset['number'];

    let classToApply = selectedAnswer == currentQuestion.answer ? 'correct' : 'incorrect';

    if (classToApply === 'correct') {
      incrementScore(SCORE_POINTS);
    }

    selectedChoice.parentElement.classList.add(classToApply);

    setTimeout(() => {
      selectedChoice.parentElement.classList.remove(classToApply);
      getNewQuestion();
    }, 1000);
  })
})

incrementScore = num => {
  score += num;
  scoreText.innerText = score;
}

startGame()
.choice-container {
  color: var(--basic-black);
  display: flex;
  margin-bottom: 1rem;
  width: 100%;
  border-radius: 4px;
  background-color: var(--honey-yellow);
  font-size: 3rem;
  min-width: 40rem;
}

.choice-prefix {
  padding: 1.5rem 1.5rem;
  color: var(--basic-black);
}

.correct {
  background: green;
}

.incorrect {
  background: red;
}
<div id="game" class="justify-center flex-column">
  <div id="hud">
    <div class="hud-item">
      <p id="progressText" class="hud-prefix">
        Question
      </p>
      <div id="progressBar">
        <div id="progressBarFull"></div>
      </div>
    </div>
    <div class="hud-item">
      <p class="hud-prefix">
        Score
      </p>
      <h1 class="hud-main-text" id="score">
        0
      </h1>
    </div>
  </div>
  <h1 id="question">Sample Question?</h1>
  <div class="choice-container">
    <p class="choice-prefix">I.</p>
    <p class="choice-text" data-number="1">Choice 1</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">II.</p>
    <p class="choice-text" data-number="2">Choice 2</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">III.</p>
    <p class="choice-text" data-number="3">Choice 3</p>
  </div>
  <div class="choice-container">
    <p class="choice-prefix">IV.</p>
    <p class="choice-text" data-number="4">Choice 4</p>
  </div>
</div>
danh
2022-12-16