记忆翻牌游戏实现

AI 智能总结

简介

记忆翻牌是一款经典的记忆力训练游戏,玩家翻开卡片寻找配对。游戏厅版本使用 CSS 3D Transform 实现逼真的卡片翻转动画,支持简单(4x4,8对)和困难(6x6,18对)两种难度。

卡片数据

符号库

使用 emoji 作为卡片图案,直观且跨平台:

1var emojis = [
2  '🍎', '🍊', '🍋', '🍇', '🍓', '🍒',
3  '🥝', '🍑', '🌮', '🍕', '🍔', '🌭',
4  '🥨', '🧁', '🍩', '🍪', '🥑', '🌶️'
5];

洗牌算法

使用 Fisher-Yates 洗牌算法打乱卡片顺序:

1function shuffle(cards) {
2  for (var i = cards.length - 1; i > 0; i--) {
3    var j = Math.floor(Math.random() * (i + 1));
4    var temp = cards[i];
5    cards[i] = cards[j];
6    cards[j] = temp;
7  }
8}

难度配置

1var difficulties = {
2  easy: { rows: 4, cols: 4, pairs: 8 },   // 16 张卡片
3  hard: { rows: 6, cols: 6, pairs: 18 }   // 36 张卡片
4};

CSS 3D 翻转动画

卡片结构

每张卡片由正反两面组成,使用 CSS 3D Transform 实现翻转:

1<div class="memo-card">
2  <div class="memo-card-inner">
3    <div class="memo-card-front">?</div>
4    <div class="memo-card-back">🍎</div>
5  </div>
6</div>

翻转 CSS

 1.memo-card {
 2  perspective: 600px;
 3  width: var(--memo-size);
 4  height: var(--memo-size);
 5}
 6.memo-card-inner {
 7  position: relative;
 8  width: 100%;
 9  height: 100%;
10  transition: transform 0.4s ease;
11  transform-style: preserve-3d;
12}
13.memo-card.flipped .memo-card-inner {
14  transform: rotateY(180deg);
15}
16.memo-card-front,
17.memo-card-back {
18  position: absolute;
19  inset: 0;
20  backface-visibility: hidden;
21  border-radius: 10px;
22  display: flex;
23  align-items: center;
24  justify-content: center;
25  font-size: calc(var(--memo-size) * 0.45);
26}
27.memo-card-back {
28  transform: rotateY(180deg);
29  background: linear-gradient(135deg, #fce7f3, #fbcfe8);
30}
31.memo-card-front {
32  background: linear-gradient(135deg, #6366f1, #818cf8);
33  color: #fff;
34  font-weight: 800;
35}

关键 CSS 属性:

  • perspective: 600px — 3D 透视距离
  • transform-style: preserve-3d — 子元素保留 3D 位置
  • backface-visibility: hidden — 隐藏背面
  • transform: rotateY(180deg) — Y 轴翻转 180°

匹配状态

配对成功的卡片添加特殊样式:

1.memo-card.matched .memo-card-back {
2  background: linear-gradient(135deg, #bbf7d0, #86efac);
3  border: 2px solid #22c55e;
4  box-shadow: 0 0 12px rgba(34, 197, 94, 0.3);
5}
6.memo-card.matched {
7  pointer-events: none;
8}

游戏逻辑

翻转控制

每次最多翻开两张卡片,使用 lock 锁防止快速点击:

 1var flipped = [];  // 当前翻开的卡片索引
 2var lock = false;  // 翻转锁定
 3
 4function flipCard(idx) {
 5  if (lock) return;                          // 锁定中
 6  if (flipped.length >= 2) return;           // 已经翻开两张
 7  if (flipped.indexOf(idx) !== -1) return;   // 已经翻开
 8
 9  grid.children[idx].classList.add('flipped');
10  flipped.push(idx);
11
12  if (flipped.length === 2) {
13    moves++;
14    checkMatch();
15  }
16}

配对判定

对比两张翻开的卡片是否相同:

 1function checkMatch() {
 2  if (cards[flipped[0]] === cards[flipped[1]]) {
 3    // 配对成功
 4    matched++;
 5    setTimeout(function() {
 6      grid.children[flipped[0]].classList.add('matched');
 7      grid.children[flipped[1]].classList.add('matched');
 8      flipped = [];
 9      if (matched === totalPairs) {
10        showWinMessage();
11      }
12    }, 300);
13  } else {
14    // 配对失败,延时翻回
15    lock = true;
16    setTimeout(function() {
17      grid.children[flipped[0]].classList.remove('flipped');
18      grid.children[flipped[1]].classList.remove('flipped');
19      flipped = [];
20      lock = false;
21    }, 800);
22  }
23}

等待 300ms 让玩家看清两张卡片后再翻回,提升用户体验。

响应式卡片尺寸

根据屏幕宽度和难度动态计算卡片大小:

 1function renderBoard() {
 2  var maxW = Math.min(window.innerWidth - 300, 600);
 3  if (window.innerWidth <= 900) maxW = window.innerWidth - 50;
 4
 5  var cellSize = Math.floor(maxW / cols) - 8;
 6  cellSize = Math.max(46, Math.min(cellSize, 82));
 7
 8  grid.style.setProperty('--memo-size', cellSize + 'px');
 9  grid.style.gridTemplateColumns = 'repeat(' + cols + ', var(--memo-size))';
10}

难度切换

简单和困难双模式按钮:

 1document.querySelectorAll('.memo-diff-btn').forEach(function(btn) {
 2  btn.addEventListener('click', function() {
 3    document.querySelectorAll('.memo-diff-btn').forEach(function(b) {
 4      b.classList.remove('active');
 5    });
 6    btn.classList.add('active');
 7    diff = btn.dataset.diff;
 8    initGame();
 9  });
10});

步数统计

记录玩家完成游戏所用的步数:

1var moves = 0;
2
3function updateUI() {
4  document.getElementById('amem-moves').textContent = moves;
5  document.getElementById('amem-pairs').textContent = matched + '/' + totalPairs;
6}

通关提示显示步数:

1function showWinMessage() {
2  document.getElementById('amem-status').innerHTML =
3    '<span>🎉</span><span>恭喜通关!用了 ' + moves + ' 步</span>';
4}

总结

记忆翻牌的核心在于 CSS 3D Transform 翻转动画和配对判定逻辑。backface-visibilitypreserve-3d 的组合实现了真实的卡片翻转效果。延时翻回机制(800ms)给玩家足够的观察时间。响应式卡片尺寸确保了在不同屏幕和设备上的良好体验。

留言评论

期待你的想法

评论加载中