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

JavaScript赛博朋克破解小游戏类名操作致序列误判问题

问题解决:赛博朋克2077入侵协议克隆游戏的序列误判问题

项目背景与核心逻辑

我正在学习JavaScript,开发《赛博朋克2077》“入侵协议”迷你游戏的克隆项目。游戏核心玩法是玩家点击矩阵中的十六进制按钮,匹配屏幕上的3组目标序列,选中的十六进制会存入buffer。

核心代码逻辑:

  • coreMatrixMechanic:创建矩阵按钮,点击后将选中项存入buffer,添加chosen-hexadecimals类,调用compareClickedHexadecimalsToSequence和sequenceCheck函数。
  • compareClickedHexadecimalsToSequence:检查选中项是否匹配当前序列的目标项,匹配则添加correctly-chosen-hex类并递增sequenceIndexTracker。
  • sequenceCheck:检查矩阵中是否存在可用项匹配序列未完成的部分,若不存在则标记该序列为failed。

问题场景

当目标序列为「63 34」且矩阵中仅存在一个63时,点击63后,compare函数会禁用该按钮,随后sequenceCheck因找不到可用的63(已被禁用),误将仍有可用34的序列标记为failed。之前尝试添加if (arrayOfHexadecimalsInASequence[sequenceIndexTracker].classList.contains('correctly-chosen-hex')) return;解决,但因部分序列尚未匹配到对应元素出现undefined错误。


解决方案

方案一:修正sequenceCheck的检查逻辑(推荐)

不要检查整个序列的所有项,只针对当前序列下一个需要匹配的项做判断,同时跳过已完成的序列:

function sequenceCheck() {
  // 假设用数组维护每个序列的追踪器,对应3组序列
  sequences.forEach((sequenceDom, seqIndex) => {
    const currentTracker = sequenceIndexTracker[seqIndex];
    // 序列已完成,直接跳过检查
    if (currentTracker >= targetSequences[seqIndex].length) return;

    const nextRequiredHex = targetSequences[seqIndex][currentTracker];
    // 查找矩阵中未被选中的对应按钮
    const hasAvailableBtn = Array.from(document.querySelectorAll('.matrix-button:not(.chosen-hexadecimals)'))
      .some(btn => btn.textContent.trim() === nextRequiredHex);

    if (!hasAvailableBtn) {
      sequenceDom.classList.add('failed');
    } else {
      // 恢复之前误标记的failed状态
      sequenceDom.classList.remove('failed');
    }
  });
}

方案二:用MutationObserver监听类名变化

如果坚持用监听类名的思路,需要先判断目标元素是否存在,避免undefined错误:

// 初始化类名变化监听
const classObserver = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
      const targetBtn = mutation.target;
      sequences.forEach((sequenceDom, seqIndex) => {
        const tracker = sequenceIndexTracker[seqIndex];
        const targetSequence = targetSequences[seqIndex];
        if (tracker >= targetSequence.length) return;

        // 确保当前追踪的元素存在,再判断类名
        const matchedElement = arrayOfHexadecimalsInASequence[seqIndex]?.[tracker];
        if (matchedElement && matchedElement === targetBtn && targetBtn.classList.contains('correctly-chosen-hex')) {
          return; // 已匹配的项跳过检查
        }
        // 执行序列可用性检查
        checkSequenceValidity(sequenceDom, seqIndex);
      });
    }
  });
});

// 给所有矩阵按钮添加监听
document.querySelectorAll('.matrix-button').forEach(btn => {
  classObserver.observe(btn, { attributes: true });
});

// 封装序列检查逻辑
function checkSequenceValidity(sequenceDom, seqIndex) {
  const tracker = sequenceIndexTracker[seqIndex];
  const targetSequence = targetSequences[seqIndex];
  if (tracker >= targetSequence.length) return;

  const nextHex = targetSequence[tracker];
  const hasAvailable = Array.from(document.querySelectorAll('.matrix-button:not(.chosen-hexadecimals)'))
    .some(btn => btn.textContent.trim() === nextHex);

  sequenceDom.classList.toggle('failed', !hasAvailable);
}

代码优化建议

  1. 独立维护序列状态:用数组sequenceIndexTracker = [0, 0, 0]对应3组序列的追踪进度,避免全局变量冲突。
  2. 分离数据与DOM:提前将矩阵按钮的文本、目标序列存入JS变量,减少频繁DOM查询的开销。
  3. 禁用按钮更可靠:点击后给按钮添加disabled属性,检查可用项时用.matrix-button:not([disabled])选择器,比类名判断更准确。
  4. 函数职责单一化:拆分coreMatrixMechanic的逻辑,比如把buffer更新、类名标记拆成独立函数,提升代码可读性。

内容的提问来源于stack exchange,提问作者MInH THiỆn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:52:53