卡牌配对游戏开发问题:错误匹配卡牌无法自动翻转
卡牌配对游戏匹配逻辑与翻转问题排查
我正在开发一款简单的卡牌配对游戏,规则为:
- 选中两张不同卡牌时,卡牌会翻转回去并消耗一次步数
- 选中两张相同卡牌时,卡牌保持翻转状态,同时消耗步数并获得1分
目前不确定代码是否能正确识别卡牌是否匹配,且卡牌翻转效果与预期不符,曾参考类似游戏教程构建本游戏。以下是我的代码:
// Set global variables const cards = document.getElementsByClassName('card'); let movesDisplay = document.querySelector('.move-counter'); let toggledCardsArray = []; let move = 0; let winCount = 0; const restart = document.getElementById('restart'); const imagesLinkArray = [ { id: 1, image: './assets/talisman1.png', newAlt: 'talisman1' }, { id: 2, image: './assets/talisman2.png', newAlt: 'talisman2' }, { id: 3, image: './assets/talisman3.png', newAlt: 'talisman3' }, { id: 4, image: './assets/talisman4.png', newAlt: 'talisman4' }, { id: 5, image: './assets/talisman5.png', newAlt: 'talisman5' }, { id: 6, image: './assets/talisman6.png', newAlt: 'talisman6' }, { id: 7, image: './assets/talisman1.png', newAlt: 'talisman1' }, { id: 8, image: './assets/talisman2.png', newAlt: 'talisman2' }, { id: 9, image: './assets/talisman3.png', newAlt: 'talisman3' }, { id: 10, image: './assets/talisman4.png', newAlt: 'talisman4' }, { id: 11, image: './assets/talisman5.png', newAlt: 'talisman5' }, { id: 12, image: './assets/talisman6.png', newAlt: 'talisman6' } ]; // Function to restart the game const restartGame = () => { const toggledCards = document.querySelectorAll('.card.toggled'); toggledCards.forEach((card) => { card.classList.remove('toggled'); }); // Shuffle the imagesLinkArray imagesLinkArray.sort(() => Math.random() - 0.5); // Reset game state toggledCardsArray = []; move = 0; winCount = 0; movesDisplay.innerText = `Turn(s): ${move}`; // Update card images const allImagesSrc = document.querySelectorAll('.card-img'); allImagesSrc.forEach((el, index) => { el.src = imagesLinkArray[index].image; el.alt = imagesLinkArray[index].newAlt; el.id = imagesLinkArray[index].id; }); }; // Add event listener to restart button restart.addEventListener('click', restartGame); // Function to handle card clicks for (let i = 0; i < cards.length; i++) { cards[i].addEventListener('click', function () { // If the card is already flipped or two cards are already in the array, return if (this.classList.contains('toggled') || toggledCardsArray.length === 2) return; // Add 'toggled' class and add to toggledCardsArray this.classList.add('toggled'); toggledCardsArray.push(this); // Check if two cards are flipped if (toggledCardsArray.length === 2) { let firstCardSrc = toggledCardsArray[0].querySelector('.card-img')?.src; let secondCardSrc = toggledCardsArray[1].querySelector('.card-img')?.src; // If cards match if (firstCardSrc === secondCardSrc) { winCount++; toggledCardsArray = []; // Clear the array for the next pair } else { // If cards do not match, flip them back after a delay setTimeout(() => { toggledCardsArray.forEach((card) => { card.classList.remove('toggled'); }); toggledCardsArray = []; // Reset the array }, 500); } // Increment move count and update display move++; movesDisplay.innerText = `Turn(s): ${move}`; // Check if the player has won if (winCount === 6) { setTimeout(() => { alert(`Congratulations!!! You won the game in ${move} moves.`); }, 300); } } }); }
问题修复与优化建议
- 卡牌匹配判断逻辑修正
当前使用src属性判断匹配存在风险:浏览器会将相对路径转换为绝对路径,可能导致原本应该匹配的卡牌因为路径格式不一致判断失败。建议改用alt属性(或自定义data-*属性)做匹配判断,修改后的代码如下:
// 替换原匹配判断部分 let firstCardAlt = toggledCardsArray[0].querySelector('.card-img').alt; let secondCardAlt = toggledCardsArray[1].querySelector('.card-img').alt; if (firstCardAlt === secondCardAlt) { winCount++; toggledCardsArray = []; } else { // 原翻转逻辑不变 }
- 防止重复点击的状态锁
在处理配对的延迟期间,用户可能快速点击第三张卡牌导致逻辑混乱,新增全局状态锁控制点击:
// 新增全局变量 let isProcessing = false; // 修改点击事件开头的判断条件 if (this.classList.contains('toggled') || toggledCardsArray.length === 2 || isProcessing) return; // 处理两张卡牌时设置锁 if (toggledCardsArray.length === 2) { isProcessing = true; // ... 匹配判断逻辑 // 匹配成功后释放锁 if (firstCardAlt === secondCardAlt) { winCount++; toggledCardsArray = []; isProcessing = false; } else { setTimeout(() => { toggledCardsArray.forEach((card) => { card.classList.remove('toggled'); }); toggledCardsArray = []; isProcessing = false; // 延迟后释放锁 }, 500); } }
- 洗牌算法优化
原sort(() => Math.random() - 0.5)的洗牌方式不均匀,替换为Fisher-Yates洗牌算法:
// 新增洗牌函数 function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } // 在restartGame中替换原洗牌逻辑 shuffleArray(imagesLinkArray);
- 语法错误修复
原代码的点击事件循环末尾缺少闭合的});和},已在代码块中补充完整,确保代码能正常运行。
内容的提问来源于stack exchange,提问作者Waskar Paulino
相关产品推荐
相关产品推荐

