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

JavaScript文字版Hangman游戏结束逻辑异常求助

文字版JavaScript Hangman游戏结束逻辑问题求助

我正在开发一款基于文字的JavaScript Hangman游戏,作为编程新手,代码可能存在冗余或过度设计的地方,还请见谅。目前游戏的结束逻辑完全不符合预期,具体问题如下:

  • 猜对任意字母时,游戏直接判定获胜;
  • 猜错字母时不会扣除生命值,玩家拥有无限生命;
  • 生命值耗尽的判定永远无法触发;
  • 猜完所有字母的胜利判定逻辑失效。

我的实现逻辑如下:

  • 准备了不同长度单词的数组,通过Math.random()获取随机单词randomWord;
  • 初始化空数组randomWordArray,用for循环为单词每个字母插入" _ "以展示待猜格式;
  • guessLetter()函数中包含4项逻辑:
    1. 检查猜中的字母是否在单词中,若存在则替换对应位置的" _ ";
    2. 检查字母不在单词中时扣除生命值(从未执行);
    3. 检查生命值是否耗尽(从未触发);
    4. 检查randomWordArray是否无" _ "以判定获胜(逻辑错误)。

附上完整代码:

//Random array of words
const words = [
    //4 letter words
    "maze", "pate", "swig", "yawn", "belt",
    //5 letter words
    "blush", "dwarf", "fable", "haste", "jumbo", "knave", "liver", "moose", "pilot", "quill", "smile", "thief",
    //6 letter words
    "affect", "bronze", "cursor", "dancer", "fossil", "fungus", "glassy", "glitch", "kitten", "lotion","anemone", 
    //7 letter words
    "bouncing", "carpeted", "clustery", "flavored", "grapple", "lunging", "pompous",
    //8 letter words
    "abstract", "barbecue", "coffee", "clotting", "flounder", "hopping", "loudest", "pending"];

var randomWord = words[Math.floor(Math.random() * words.length)];
var randomWordArray =[];
var lives = 5;

for(i=0;i<randomWord.length;i++) {
    randomWordArray.push(" _ ");
}

function guessLetter(randomWord, randomWordArray, lives) {
    let guess = window.prompt(randomWordArray+"     Lives:"+lives);
  
  if (!guess) return; // prompt shortcut
  
  if(guess == "end") {
    window.alert("Game over");
    return;
  }
    
  //check if letter is in word
  for (i=0; i<randomWord.length; i++) {
    if (guess == randomWord[i]) {
      randomWordArray.splice(i, 1, randomWord[i]);
    }
  }
    
  //check if letter isnt in word
  if (randomWordArray.indexOf(guess) == -1) {
    lives--;
  } 
    
  //check if game should end because lives are out
  if (lives==0) {
    window.alert("Congrats the game is over!");
    return;
  }
    
  if (randomWord.indexOf("_") == -1) {
    window.alert(randomWord);
    window.alert("Congrats! You've solved the word!!");
    return;
  }
  
  if (lives > 0) {
    guessLetter(randomWord, randomWordArray,lives);
  }
}

// don't start until explicitly asked to
start.addEventListener(`click`, () => guessLetter(randomWord, randomWordArray,lives));
<button id="start">Start</button>

欢迎任何相关建议,包括代码优化方向,感谢您的时间。


问题修复方案

1. 修正胜利判定逻辑

原代码错误地检查原始单词randomWord中是否有下划线(原始单词根本不含下划线),导致条件永远为真,猜对任意字母就触发胜利。应改为检查待显示数组randomWordArray中是否还有未被猜出的下划线:

// 替换原胜利判定代码
if (!randomWordArray.includes(" _ ")) {
  window.alert(randomWord);
  window.alert("Congrats! You've solved the word!!");
  return;
}

2. 修复生命值扣除逻辑

原代码通过randomWordArray.indexOf(guess)判断是否猜错,但若字母多次出现(如"coffee"中的"f"),替换后数组中存在该字母,会导致猜错不扣血。应直接判断原始单词是否包含猜测的字母:

// 替换原猜错判断代码
if (!randomWord.includes(guess)) {
  lives--;
}

3. 解决生命值传递失效问题

原函数中lives是按值传递的,递归调用时传递的是值的副本,生命值变化无法保留。最简单的方式是去掉函数参数中的lives,直接使用全局变量:

// 修改函数定义
function guessLetter(randomWord, randomWordArray) {
  let guess = window.prompt(randomWordArray+"     Lives:"+lives);
  
  // 其他代码保持不变,递归调用时去掉lives参数
  if (lives > 0) {
    guessLetter(randomWord, randomWordArray);
  }
}

// 启动调用也去掉lives参数
start.addEventListener(`click`, () => guessLetter(randomWord, randomWordArray));

4. 修正失败提示文案

原提示"Congrats the game is over!"不符合失败场景,改为:

if (lives === 0) {
  window.alert(`Game over! The word was ${randomWord}`);
  return;
}

代码优化建议

  • 减少全局变量:把游戏状态(随机单词、待显示数组、生命值)封装在对象或闭包里,避免全局污染。
  • 处理重复猜测:添加逻辑判断玩家是否重复猜测同一字母,避免无效操作。
  • 替换弹窗为DOM元素:用页面元素显示游戏状态和输入框,提升用户体验,不要依赖prompt/alert。
  • 统一字母大小写:将玩家输入转成小写(或大写),避免大小写不匹配问题:guess = guess.toLowerCase();
  • 简化数组初始化:用Array.from替代for循环初始化待显示数组:
    const randomWordArray = Array.from(randomWord, () => " _ ");
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:45:23