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

JavaScript战斗模拟器中window.prompt提前执行,页面内容未先显示的解决求助

JavaScript战斗模拟器中window.prompt提前执行,页面内容未先显示的解决求助

嘿,我来帮你搞定这个问题!你遇到的情况其实是window.prompt的特性导致的,还有几个小代码问题需要调整,我一步步给你拆解:

为什么prompt会先弹出来?

window.prompt(包括alert、confirm)是同步阻塞式的API——意思是,当代码执行到它时,浏览器会立刻暂停所有页面渲染和后续JS执行,直到你在prompt里输入内容确认。

你现在的代码里,所有document.write和yourTurn()调用都在同一个JS执行块里。浏览器会先执行document.write语句,但不会立刻渲染到页面——它要等当前JS执行块跑完才会开始渲染。但你紧接着就调用了yourTurn(),里面的prompt直接卡住浏览器,导致之前的document.write内容根本没机会显示,所以你先看到prompt,看不到敌人攻击和你的状态。

另外还有两个小bug:

  1. switch里的case "FIGHT" || "fight" || "Fight"写法错了——逻辑或||会返回第一个真值(也就是"FIGHT"),所以这个case其实只匹配"FIGHT",不过你已经把yourMove转成大写了,其实只需要写case "FIGHT":就够了。
  2. document.write不是现代浏览器的推荐写法,它容易重写页面,渲染时机也不好控制。

解决方法

我给你调整了代码,解决了这些问题,你可以直接参考:

首先在HTML里加一个专门放游戏日志的容器(代替document.write):

<div id="game-log"></div>

然后修改JS代码:

const enemy = 'Mettaton'.toUpperCase();
const player = window.prompt("Enter your Name, Player").toUpperCase();
let enemyHP = 500;
let enemyMercy = 0;
let playerHP = 150;

// 获取游戏日志容器
const gameLog = document.getElementById('game-log');

// 封装添加日志的函数,方便重复使用
function addLog(text) {
  gameLog.innerHTML += text + '<br>';
}

// 先输出初始游戏内容
addLog(`${enemy} attacks!`);
addLog(`YOUR STATS:`);
addLog(`${playerHP} HP`);

function yourTurn() {
  let yourMove = window.prompt("FIGHT, ACT, CHECK, or SPARE").toUpperCase();
  switch (yourMove) {
    case "FIGHT":
      addLog(`${player} used FIGHT!`);
      const fightPower = Math.floor(Math.random() * 100 / 5);
      addLog(`${enemy} took ${fightPower} damage!`);
      enemyHP -= fightPower;
      break;
    case "ACT":
      addLog(`${player} chose to ACT! (可以根据Undertale设定完善这里的怜悯值逻辑)`);
      enemyMercy += 20; // 示例:ACT增加怜悯值
      break;
    case "CHECK":
      addLog(`You checked ${enemy}! HP: ${enemyHP} | Mercy: ${enemyMercy}`);
      break;
    case "SPARE":
      addLog(`${player} tried to SPARE!`);
      break;
    default:
      addLog(`Invalid move! Please enter FIGHT, ACT, CHECK, or SPARE.`);
      // 让用户重新输入
      yourTurn();
  }
}

function enemyTurn() {
  const enemyPower = Math.floor(Math.random() * 100 / 3);
  addLog(`<br>${enemy} attacks back!`);
  addLog(`${player} took ${enemyPower} damage!`);
  playerHP -= enemyPower;
  addLog(`Your HP is now ${playerHP}`);
}

// 用setTimeout让浏览器先渲染初始内容,再执行你的回合
setTimeout(() => {
  yourTurn();
  // 可以在这里加游戏循环逻辑,比如判断是否继续战斗
  enemyTurn();
}, 0);

关键改动说明

  1. 替换document.write为DOM容器:用game-logdiv管理所有游戏文本,避免内容被意外覆盖,浏览器也能更及时地更新DOM。
  2. 解决阻塞渲染问题:setTimeout(() => {}, 0)把yourTurn()的调用放到事件队列末尾——让浏览器先渲染完初始的游戏日志,再弹出操作选择的prompt,这样你就能先看到页面内容再输入了。
  3. 修复switch条件错误:因为yourMove已经转成大写,直接匹配大写字符串即可,不需要多余的逻辑或写法。
  4. 补全其他操作逻辑:给ACT、CHECK、SPARE加了示例代码,你可以根据Undertale的设定继续完善。
  5. 修复敌人回合逻辑:原来的代码里敌人攻击后没有减少你的HP,现在补上了playerHP -= enemyPower的逻辑。

额外小建议

如果想让游戏体验更好,还可以:

  • 把原生prompt换成页面上的按钮/自定义输入框(非阻塞式UI),避免打断页面渲染。
  • 增加游戏循环,比如判断enemyHP是否为0、怜悯值是否满,自动继续战斗轮次,而不是只执行一次回合。

这样调整后,你就能先看到敌人攻击信息和自己的状态,再进行操作选择啦!

备注:内容来源于stack exchange,提问作者Cyrus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:13:01