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

非按钮元素Mousedown事件不生效 记忆游戏代码逻辑修正求助

问题修复与代码优化方案

核心错误原因

  • colorClicked 函数仅注册事件监听器,没有返回等待用户点击的Promise,await colorClicked() 会直接执行完成,不会等待用户交互;且每次调用该函数都会重复绑定事件,导致后续单次点击触发多次回调。
  • 主逻辑存在规则漏洞:生成的随机颜色未存入sequence序列,没有按照记忆游戏规则校验用户输入的完整序列;内层循环变量j最大值为i,永远不可能等于rounds,通关判断条件永远无法触发。

修复代码

第一步:改造事件绑定逻辑(仅在游戏初始化时执行一次,不要放在循环里调用)

// 全局存储点击事件的resolve回调
let resolveUserClick;
const colorList = [red, blue, green, yellow];

// 一次性绑定所有颜色块的点击事件
colorList.forEach(colorEl => {
  colorEl.addEventListener("mousedown", async () => {
    // 游戏未启动或未处于等待点击状态时不响应
    if (!gameOn || !resolveUserClick) return;
    await flash(colorEl);
    await revert();
    // 返回用户点击的颜色块,结束等待
    resolveUserClick(colorEl);
    resolveUserClick = null;
  });
});

// 改造为等待用户点击的异步函数
async function colorClicked() {
  return new Promise(resolve => {
    resolveUserClick = resolve;
  });
}

第二步:修正主游戏逻辑

async function eachRounds() {
  // 每局游戏开始前清空历史序列
  sequence = [];
  const statusEl = document.getElementById("status");
  for (let i = 0; i < rounds; i++) {
    // 每轮生成新的随机颜色,加入序列
    const random = Math.floor(Math.random() * array.length);
    const newColor = array[random];
    sequence.push(newColor);
    // 展示新的颜色
    statusEl.innerHTML = `Round ${i + 1} out of ${rounds}`;
    await flash(newColor);
    await revert();
    // 等待用户复现当前全部序列
    let isPass = true;
    for (let j = 0; j < sequence.length; j++) {
      const userClick = await colorClicked();
      if (userClick !== sequence[j]) {
        statusEl.innerHTML = "Sorry! You lose!";
        gameOn = false;
        isPass = false;
        break;
      }
    }
    if (!isPass) break;
    // 全部通关判断
    if (i === rounds - 1) {
      statusEl.innerHTML = "Congratulations! You win!";
      gameOn = false;
      break;
    }
    statusEl.innerHTML = "On to the next round!";
    // 可加短延迟再进入下一轮提升体验
    await new Promise(resolve => setTimeout(resolve, 800));
  }
}

代码结构优化建议

  • 封装游戏状态:将gameOn、rounds、sequence、当前轮次等全局变量封装到一个游戏状态对象中,避免全局变量污染,也方便多局游戏重置状态。
  • 抽离公共方法:把DOM状态更新、延迟等待等通用逻辑抽成单独函数,减少重复代码。
  • 增加边界判断:增加游戏进行中禁止重复启动、点击响应防抖等逻辑,避免异常操作导致逻辑混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 06:24:06