You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript乘法游戏逻辑错误:选中正确选项但分数未递增

乘法答题游戏分数不递增问题分析

问题概述

开发了一款JavaScript乘法答题游戏:系统生成乘法题目,玩家从4个选项中选择正确答案。但发现选中正确选项时,分数并未递增,结合代码分析如下:

HTML代码

<nav>
  <div class="reset utilites">Reset</div>
  <div class="score utilites">
    Score: <span class="ScoreNumber"> 0</span>
  </div>
  <div class="highScore utilites">
    High Score: <span class="highScoreNumber"> 0</span>
  </div>
</nav>
<section>
  <div class="choices" id="1">
    🚪
    <div class="answer answer1">answer</div>
  </div>
  <div class="choices" id="2">
    🚪
    <div class="answer answer2">answer</div>
  </div>
  <div class="choices" id="3">
    🚪
    <div class="answer answer3">answer</div>
  </div>
  <div class="choices" id="4">
    🚪
    <div class="answer answer4">answer</div>
  </div>
</section>
<div class="question">---</div>

JavaScript代码

"use strict";

const resetBtn = document.querySelector(".reset");
const Navscore = document.querySelector(".ScoreNumber");
const scoreToReset = document.querySelector(".score");
const question = document.querySelector(".question");
const highScoreNumber = document.querySelector(".highScoreNumber");
const choices1 = document.getElementById("1");
const choices2 = document.getElementById("2");
const choices3 = document.getElementById("3");
const choices4 = document.getElementById("4");
const answer1 = document.querySelector(".answer1");
const answer2 = document.querySelector(".answer2");
const answer3 = document.querySelector(".answer3");
const answer4 = document.querySelector(".answer4");
const choices = document.querySelector(".choices");
let score = 0;
let Highscore = 0;
const numberForNumberGen = function() {
  return Math.trunc(Math.random() * 12 + 1);
};
const choicesAssinger = function(usersChoice) {
  console.log(`user choice ${usersChoice}`);
  const answerText = questionGen();
  const correct = numberGen(4);
  console.log(`correct choice ${correct}`);
  if (correct === 1) {
    answer1.innerHTML = answerText;
    answer2.innerHTML = answerText + numberForNumberGen();
    answer3.innerHTML = answerText - numberForNumberGen();
    answer4.innerHTML =
      answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 2) {
    answer2.innerHTML = answerText;
    answer1.innerHTML = answerText - numberForNumberGen();
    answer4.innerHTML = answerText - numberForNumberGen();
    answer3.innerHTML =
      answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 3) {
    answer3.innerHTML = answerText;
    answer4.innerHTML = answerText + numberForNumberGen();
    answer2.innerHTML = answerText - numberForNumberGen();
    answer1.innerHTML =
      answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 4) {
    answer4.innerHTML = answerText;
    answer3.innerHTML = answerText + numberForNumberGen();
    answer1.innerHTML = answerText - numberForNumberGen();
    answer2.innerHTML =
      answerText + numberForNumberGen() - numberForNumberGen();
  }
  console.error(correct);
  console.error(usersChoice);

  console.log(correct == usersChoice);
  if (correct == usersChoice) {
    console.log("correct");
    document.querySelector("body").style.background = "green";
    score++;
    questionGen();
    choicesAssinger();
    Navscore.innerHTML = score;
    if (score > Highscore) {
      Highscore = score;
      highScoreNumber.innerHTML = Highscore;
    }
  } else {
    if (score !== 0) {
      document.querySelector("body").style.background = " #925e36";
      Navscore.innerHTML = "Please click Reset";
      choices1.removeEventListener("click", handler);
      choices2.removeEventListener("click", handler);
      choices3.removeEventListener("click", handler);
      choices4.removeEventListener("click", handler);
    }
  }
};
const start = () => {
  choices1.addEventListener("click", handler);
  choices2.addEventListener("click", handler);
  choices3.addEventListener("click", handler);
  choices4.addEventListener("click", handler);
};
const numberGen = function(n) {
  const number = Math.trunc(Math.random() * n + 1);

  return number;
};

const questionGen = function() {
  const num1 = numberGen(numberForNumberGen());
  const num2 = numberGen(numberForNumberGen());
  const answer = num1 * num2;
  console.log(answer);
  const questionWriting = `${num1} x ${num2}`;
  question.innerHTML = questionWriting;
  return answer;
};

function handler(event) {
  const usersChoice = event.target.id;

  choicesAssinger(usersChoice);
}

resetBtn.addEventListener("click", () => {
  start();
  document.querySelector("body").style.background = " #925e36";
  score = 0;
  Navscore.innerHTML = 0;
  questionGen();
});
questionGen();
start();

核心失效原因

1. 递归调用直接覆盖分数更新逻辑

当用户选择正确选项后,代码执行score++后立即无参数调用choicesAssinger():

  • 新的choicesAssinger执行时,usersChoice为undefined
  • 新生成的随机correct与undefined比较结果为false,进入错误分支
  • 错误分支中因score !== 0,会将Navscore内容改为"Please click Reset",直接覆盖了刚递增的分数,同时移除所有点击事件导致后续操作失效

2. 事件目标ID获取不精准

handler函数通过event.target.id获取选项ID,但用户点击选项内的子元素(如带"answer"文本的div)时,子元素无ID,导致usersChoice为空字符串,无法与数字类型的correct匹配,即使选对也会被判错误。

3. 类型不匹配的隐式转换风险

usersChoice是字符串类型(DOM元素ID默认是字符串),correct是数字类型,使用==的隐式转换容易引发不可预期的判断错误,严格来说二者类型不统一,直接比较逻辑存在漏洞。


修复方案示例

修复递归调用问题

将生成新题目的逻辑从判断分支中剥离,避免递归覆盖:

// 新增单独生成题目和选项的函数
const generateNewQuestion = function() {
  const answerText = questionGen();
  const correct = numberGen(4);
  if (correct === 1) {
    answer1.innerHTML = answerText;
    answer2.innerHTML = answerText + numberForNumberGen();
    answer3.innerHTML = answerText - numberForNumberGen();
    answer4.innerHTML = answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 2) {
    answer2.innerHTML = answerText;
    answer1.innerHTML = answerText - numberForNumberGen();
    answer4.innerHTML = answerText - numberForNumberGen();
    answer3.innerHTML = answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 3) {
    answer3.innerHTML = answerText;
    answer4.innerHTML = answerText + numberForNumberGen();
    answer2.innerHTML = answerText - numberForNumberGen();
    answer1.innerHTML = answerText + numberForNumberGen() - numberForNumberGen();
  } else if (correct === 4) {
    answer4.innerHTML = answerText;
    answer3.innerHTML = answerText + numberForNumberGen();
    answer1.innerHTML = answerText - numberForNumberGen();
    answer2.innerHTML = answerText + numberForNumberGen() - numberForNumberGen();
  }
  return correct;
};

// 修改choicesAssinger中的正确分支逻辑
if (correct == usersChoice) {
  console.log("correct");
  document.querySelector("body").style.background = "green";
  score++;
  Navscore.innerHTML = score;
  if (score > Highscore) {
    Highscore = score;
    highScoreNumber.innerHTML = Highscore;
  }
  // 调用独立函数生成新题,不再递归choicesAssinger
  generateNewQuestion();
}

修复事件目标ID问题

确保点击子元素时也能获取到父选项的ID:

function handler(event) {
  // 向上查找最近的.choices元素,稳定获取选项ID
  const choiceElement = event.target.closest(".choices");
  const usersChoice = choiceElement.id;
  choicesAssinger(usersChoice);
}

统一类型并使用严格相等

将usersChoice转为数字,用===做严格判断:

const choicesAssinger = function(usersChoice) {
  // 统一类型为数字
  usersChoice = Number(usersChoice);
  // ...其他逻辑
  if (correct === usersChoice) {
    // ...正确分支逻辑
  }
};

内容的提问来源于stack exchange,提问作者T122wd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:46:09