You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

HTML与JavaScript单词记忆游戏BUG原因排查及修复方法咨询

Word Memory Game: Fixing Life Deduction That Relies on Unseen Next Word

The Problem

I'm building a word memory game with HTML and JavaScript. The rules are simple: a word (either new or previously shown) appears on screen, and players click "Seen" or "New" to indicate if they've encountered it before. Wrong answers cost a life.

Right now, the game is unplayable because the life deduction logic checks against the next word generated after clicking the button—not the word the player actually just judged. Players can't possibly know the next word in advance!

Here's my current code:

JavaScript

var word_bank = ["test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12", "test13", "test14", "test15"];
var old_words = [];
var dec = word_bank;
var lives = 3;
function updateLives() {
 document.getElementById("lives").innerHTML = "Lives: " + lives;
}
function thing(v) {
 var rndn = Math.floor(Math.random() * (1 - 0 + 1)) + 0;
 if (rndn == 1) {
 var dec = word_bank
 } else {
 var dec = old_words
 }
 var word = dec[Math.floor(Math.random() * dec.length)];
 document.getElementById("word").textContent = word;
 if (v == 1) {
 if (old_words.includes(word)) {
 } else {
 --lives updateLives();
 }
 } else {
 if (old_words.includes(word)) {
 --lives updateLives();
 }
 }
 old_words.push(word);
 var forDeletion = [word];
 word_bank = word_bank.filter(item => !forDeletion.includes(item))
};
var word = dec[Math.floor(Math.random() * dec.length)];
document.getElementById("word").textContent = word;
updateLives();
old_words.push(word);
var forDeletion = [word];
word_bank = word_bank.filter(item => !forDeletion.includes(item))

HTML

<span id="lives"></span>
<div id="center">
 <span id="word"></span>
</div>
<div>
 <div>
 <button name="submit" class="action_btn_left seen" type="submit" value="seen" onclick="thing(1)">Seen</button>
 <button name="submit" class="action_btn_right new" type="submit" value="new" onclick="thing(0)">New</button>
 </div>
</div>

Why This Is Happening

Let's break down the key issues:

  • Backwards Logic Flow: Your thing() function first generates a new word and updates the screen, then checks if the player's choice matches this new word. But the player clicked the button based on the previous word that was on screen—you're judging their choice against a word they haven't even seen yet!
  • Variable Scope Bug: Inside thing(), you're using var dec which re-declares the variable locally, overriding the global dec you set initially. This breaks your intended word source selection.
  • Syntax Error: Lines like --lives updateLives(); are missing a semicolon between the life deduction and function call, which can cause unexpected behavior.
  • No Reference to Current Word: You don't store the currently displayed word in a persistent variable, so when the player clicks a button, you have no way to check their choice against the word they actually saw.

Fixed Code & Explanation

Here's the corrected version, with comments explaining the changes:

Fixed JavaScript

var word_bank = ["test1", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12", "test13", "test14", "test15"];
var old_words = [];
var lives = 3;
var currentWord = ""; // New: Store the word currently displayed on screen

function updateLives() {
 document.getElementById("lives").innerHTML = "Lives: " + lives;
}

// Helper function to generate the next random word (either new or old)
function getNextWord() {
 // 50% chance to pick a new word or an old one
 const useNewWord = Math.random() > 0.5;
 let wordSource = useNewWord ? word_bank : old_words;
 
 // If word source is empty (e.g., no new words left), fall back to the other source
 if (wordSource.length === 0) {
  wordSource = useNewWord ? old_words : word_bank;
 }
 
 return wordSource[Math.floor(Math.random() * wordSource.length)];
}

// Initialize the first word
function initGame() {
 currentWord = getNextWord();
 document.getElementById("word").textContent = currentWord;
 // Move initial word to old_words and remove from word_bank
 old_words.push(currentWord);
 word_bank = word_bank.filter(item => item !== currentWord);
 updateLives();
}

function handlePlayerChoice(isSeen) {
 // First: Check if the player's choice is correct against the CURRENT word
 if (isSeen) {
  // Player said "Seen" - if it's NOT in old_words (before we add it now), they were wrong
  if (!old_words.includes(currentWord)) {
   lives--;
   updateLives();
  }
 } else {
  // Player said "New" - if it IS in old_words, they were wrong
  if (old_words.includes(currentWord)) {
   lives--;
   updateLives();
  }
 }

 // Second: Generate and display the next word
 currentWord = getNextWord();
 document.getElementById("word").textContent = currentWord;

 // Third: Update word banks (move current word to old_words, remove from word_bank if needed)
 old_words.push(currentWord);
 word_bank = word_bank.filter(item => item !== currentWord);
}

// Start the game when it loads
initGame();

Fixed HTML

<span id="lives"></span>
<div id="center">
 <span id="word"></span>
</div>
<div>
 <div>
 <!-- Updated onclick to use the new function with clear intent -->
 <button name="submit" class="action_btn_left seen" type="button" onclick="handlePlayerChoice(true)">Seen</button>
 <button name="submit" class="action_btn_right new" type="button" onclick="handlePlayerChoice(false)">New</button>
 </div>
</div>

Key improvements:

  • Separated Logic: Split into helper functions (getNextWord, initGame, handlePlayerChoice) for better readability and maintainability.
  • Current Word Tracking: The currentWord variable keeps track of what's on screen, so we always judge the player's choice against the word they actually interacted with.
  • Fixed Flow: First check the player's choice against the current word, then generate the next one.
  • Removed Scope Bugs: No more local variable overriding global ones.
  • Fallback for Empty Word Banks: If all new words are used up, the game will keep using old words, and vice versa.
  • Clearer Function Names: handlePlayerChoice is much more descriptive than thing().

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

火山引擎 最新活动