数组比较逻辑优化:正确统计有效与错位元素
如何正确统计游戏中的有效元素与错位元素(避免重复统计)
问题描述
我在做一个简单游戏,需要对比两个长度为n的数组:用户输入数组和随机生成的获胜组合数组(获胜组合元素唯一)。
- 有效元素:值和索引均与获胜组合对应位置匹配的元素
- 错位元素:值存在于获胜组合中,但索引不匹配的元素
我原本的有效元素统计逻辑用了嵌套循环:
for (let i = 0; i<arr1.length; i++) { for (let j = 0; j<arr1.length; j++){ if (arr[i] === arr1[j] && getIndices(arr[i], arr1[j]) === true){ valid ++; }
但统计错位元素时出现错误:比如用户输入['A','B','A'] vs 获胜组合['A','C','C'],正确的有效元素是1个,但错误统计出1个错位元素——获胜组合只有1个'A',且已经被精确匹配,不应再算错位。
解决方案
第一步:修正有效元素的统计逻辑
不需要嵌套循环,直接单循环对比相同索引的元素即可,避免重复计数:
let valid = 0; const winningArr = ['A', 'C', 'C']; // 获胜组合 const userArr = ['A', 'B', 'A']; // 用户输入 // 统计精确匹配的有效元素 for (let i = 0; i < winningArr.length; i++) { if (userArr[i] === winningArr[i]) { valid++; } } // 此时 valid = 1,正确
第二步:正确统计错位元素
核心思路:先排除已精确匹配的元素,再确保每个获胜元素只被统计一次
let misplaced = 0; // 复制获胜数组,用null标记已被匹配(精确/错位)的元素,避免重复统计 const remainingWinning = [...winningArr]; // 第一步:把精确匹配的位置标记为已使用 for (let i = 0; i < winningArr.length; i++) { if (userArr[i] === winningArr[i]) { remainingWinning[i] = null; } } // 第二步:遍历用户输入,寻找错位匹配 for (let i = 0; i < userArr.length; i++) { const currentChar = userArr[i]; // 跳过已经精确匹配的元素(已经在valid里统计过) if (currentChar === winningArr[i]) { continue; } // 在剩余未被匹配的获胜元素中查找当前字符 const matchPos = remainingWinning.indexOf(currentChar); if (matchPos !== -1) { misplaced++; remainingWinning[matchPos] = null; // 标记该获胜元素已被统计,防止重复 } } // 此时 misplaced = 0,正确
逻辑解释
- 先标记已精确匹配的获胜元素,避免后续被误判为错位
- 遍历用户输入时,跳过自身已精确匹配的元素
- 每找到一个错位匹配,就把对应的获胜元素标记为已使用,确保同一个获胜元素不会被多次统计
扩展优化(用频率统计法)
如果数组长度较大,indexOf效率较低,可以用对象统计元素出现次数:
// 先统计有效元素 let valid = 0; for (let i = 0; i < winningArr.length; i++) { if (userArr[i] === winningArr[i]) valid++; } // 统计获胜组合中剩余元素的频率(排除已精确匹配的) const winningFreq = {}; for (let i = 0; i < winningArr.length; i++) { if (userArr[i] !== winningArr[i]) { winningFreq[winningArr[i]] = (winningFreq[winningArr[i]] || 0) + 1; } } // 统计错位元素 let misplaced = 0; for (let i = 0; i < userArr.length; i++) { const char = userArr[i]; // 跳过精确匹配的元素,且获胜组合中还有剩余该字符 if (char !== winningArr[i] && winningFreq[char] > 0) { misplaced++; winningFreq[char]--; } }
内容的提问来源于stack exchange,提问作者wasphellion
相关产品推荐
相关产品推荐

