class MemoryGame {
constructor() {
this.symbols = ['🍎', '🍊', '🍋', '🍇', '🍓', '🍒', '🥝', '🍑'];
this.cards = [];
this.flippedCards = [];
this.matchedPairs = 0;
this.moves = 0;
this.timer = null;
this.seconds = 0;
this.isLocked = false;
this.gameStarted = false;
this.boardEl = document.getElementById('game-board');
this.movesEl = document.getElementById('moves');
this.timerEl = document.getElementById('timer');
this.pairsEl = document.getElementById('pairs');
this.winModal = document.getElementById('win-modal');
this.finalMovesEl = document.getElementById('final-moves');
this.finalTimeEl = document.getElementById('final-time');
document.getElementById('restart-btn').addEventListener('click', () => this.init());
document.getElementById('play-again-btn').addEventListener('click', () => {
this.winModal.style.display = 'none';
this.init();
});
this.init();
}
init() {
// 重置状态
this.cards = [];
this.flippedCards = [];
this.matchedPairs = 0;
this.moves = 0;
this.seconds = 0;
this.isLocked = false;
this.gameStarted = false;
// 清除计时器
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
// 更新UI
this.movesEl.textContent = '0';
this.timerEl.textContent = '0:00';
this.pairsEl.textContent = '0/8';
// 生成卡牌
this.generateCards();
this.renderBoard();
}
generateCards() {
// 创建配对卡牌
const cardPairs = [...this.symbols, ...this.symbols];
// 洗牌 (Fisher-Yates shuffle)
for (let i = cardPairs.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[cardPairs[i], cardPairs[j]] = [cardPairs[j], cardPairs[i]];
}
this.cards = cardPairs.map((symbol, index) => ({
id: index,
symbol: symbol,
isFlipped: false,
isMatched: false
}));
}
renderBoard() {
this.boardEl.innerHTML = '';
this.cards.forEach(card => {
const cardEl = document.createElement('div');
cardEl.className = 'card';
cardEl.dataset.id = card.id;
cardEl.innerHTML = `
${card.symbol}
`;
cardEl.addEventListener('click', () => this.flipCard(card.id));
this.boardEl.appendChild(cardEl);
});
}
flipCard(id) {
const card = this.cards[id];
const cardEl = this.boardEl.querySelector(`[data-id="${id}"]`);
// 防止重复点击或锁定状态
if (this.isLocked || card.isFlipped || card.isMatched) return;
// 开始计时
if (!this.gameStarted) {
this.gameStarted = true;
this.startTimer();
}
// 翻牌
card.isFlipped = true;
cardEl.classList.add('flipped');
this.flippedCards.push(card);
// 检查是否翻了两张
if (this.flippedCards.length === 2) {
this.moves++;
this.movesEl.textContent = this.moves;
this.checkMatch();
}
}
checkMatch() {
const [card1, card2] = this.flippedCards;
if (card1.symbol === card2.symbol) {
// 配对成功
this.matchSuccess(card1, card2);
} else {
// 配对失败
this.matchFail(card1, card2);
}
}
matchSuccess(card1, card2) {
card1.isMatched = true;
card2.isMatched = true;
this.matchedPairs++;
this.pairsEl.textContent = `${this.matchedPairs}/8`;
const cardEl1 = this.boardEl.querySelector(`[data-id="${card1.id}"]`);
const cardEl2 = this.boardEl.querySelector(`[data-id="${card2.id}"]`);
// 延迟消除动画
setTimeout(() => {
cardEl1.classList.add('matched');
cardEl2.classList.add('matched');
}, 500);
this.flippedCards = [];
// 检查胜利
if (this.matchedPairs === 8) {
this.win();
}
}
matchFail(card1, card2) {
this.isLocked = true;
// 延迟翻回
setTimeout(() => {
card1.isFlipped = false;
card2.isFlipped = false;
const cardEl1 = this.boardEl.querySelector(`[data-id="${card1.id}"]`);
const cardEl2 = this.boardEl.querySelector(`[data-id="${card2.id}"]`);
cardEl1.classList.remove('flipped');
cardEl2.classList.remove('flipped');
this.flippedCards = [];
this.isLocked = false;
}, 1000);
}
startTimer() {
this.timer = setInterval(() => {
this.seconds++;
const mins = Math.floor(this.seconds / 60);
const secs = this.seconds % 60;
this.timerEl.textContent = `${mins}:${secs.toString().padStart(2, '0')}`;
}, 1000);
}
win() {
clearInterval(this.timer);
const mins = Math.floor(this.seconds / 60);
const secs = this.seconds % 60;
const timeStr = `${mins}:${secs.toString().padStart(2, '0')}`;
this.finalMovesEl.textContent = this.moves;
this.finalTimeEl.textContent = timeStr;
setTimeout(() => {
this.winModal.style.display = 'flex';
}, 800);
}
}
// 启动游戏
new MemoryGame();