JS如何实现数组内每个图片元素仅调用2次?配对游戏开发相关问题
问题根源
你当前的实现逻辑是每次渲染都随机生成0-8的索引,没有对每个索引的出现次数做限制,所以必然会出现单张图片出现次数多于/少于2次、部分图片未被调用的问题。同时你代码里使用的i++没有提前定义初始值,也会导致id赋值异常。
解决方案
核心思路是先构造符合「每个图片索引出现2次」要求的总池,再打乱总池后顺序渲染,同时可选择规避相邻重复的问题:
- 先生成长度为18的索引池,0-8每个索引各出现2次,从根源保证每张图片刚好出现2次
- 对索引池做随机洗牌,可额外校验避免相同索引相邻
- 遍历洗牌后的索引池直接渲染元素,不需要额外生成随机数
实现代码
// 1. 构造索引池,每个0-8的索引各出现2次,总长度18 const imgIndexPool = Array.from({length: 9}, (_, idx) => idx).flatMap(num => [num, num]) // 2. 可选:带相邻去重的洗牌函数,不需要相邻去重则可删掉校验逻辑 function shufflePool(pool) { // 先执行Fisher-Yates基础洗牌 for (let i = pool.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [pool[i], pool[j]] = [pool[j], pool[i]] } // 检查相邻重复,有则交换到其他位置 for (let i = 0; i < pool.length -1; i++) { if (pool[i] === pool[i+1]) { // 找一个不相邻的位置交换 for (let k = i+2; k < pool.length; k++) { if (pool[k] !== pool[i] && (pool[k+1] === undefined || pool[k+1] !== pool[i])) { [pool[i+1], pool[k]] = [pool[k], pool[i+1]] break } } } } return pool } const shuffledIndex = shufflePool(imgIndexPool) const template = document.getElementsByTagName('template')[0] const target = document.getElementById('Playground') // 提前定义按钮id初始值 let btnId = 0 // 3. 遍历洗牌后的索引渲染元素 for (let index = 0 ; index < 18; index++) { const x = shuffledIndex[index] const clone = template.content.cloneNode(true) clone.querySelector("img").src = item[x].src clone.querySelector("img").alt = item[x].id clone.querySelector('button').setAttribute('id', btnId++) clone.querySelector('button').removeAttribute('onclick') target.appendChild(clone) }
内容的提问来源于stack exchange,提问作者StephanieAn
相关产品推荐
相关产品推荐

