Day 17
主題:JS DOM 操作 — 建立卡片生成與翻牌事件
今日目標
前幾天完成了介面、切版、配色以及基本動畫,現在正式進入遊戲邏輯的實作。今天的重點是使用 JavaScript 操作 DOM,讓遊戲能夠:
學習與操作重點
DOM 生成元素
使用 document.createElement 動態建立卡片。
將卡片加入遊戲區塊(appendChild)。
為卡片設計 front(背面符號)與 back(正面符號)兩層。
事件監聽
使用 addEventListener("click", ...) 監聽卡片的翻牌行為。
透過切換 CSS class(如 flip)來觸發翻牌動畫。
遊戲互動邏輯雛形
記錄已翻開的兩張卡片。
如果兩張相同 → 保持翻開狀態。
如果不同 → 等待一小段時間後再翻回去。
避免短時間內快速點擊導致 bug,需要 lockBoard(鎖定狀態)。
程式範例
以下是一個簡單的翻牌遊戲雛形,今天的目標就是讓「卡片能生成+翻轉+簡單比對」。
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
  <meta charset="UTF-8">
  <title>翻牌遊戲 Day 17</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background: #fef6e4;
    }
    .game-board {
      display: grid;
      grid-template-columns: repeat(4, 100px);
      grid-gap: 10px;
    }
    .card {
      width: 100px;
      height: 140px;
      perspective: 1000px;
      cursor: pointer;
    }
    .card-inner {
      width: 100%;
      height: 100%;
      position: relative;
      transform-style: preserve-3d;
      transition: transform 0.6s;
    }
    .card.flip .card-inner {
      transform: rotateY(180deg);
    }
    .front, .back {
      position: absolute;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 28px;
      font-weight: bold;
      border-radius: 10px;
      backface-visibility: hidden;
    }
    .front {
      background: #8ecae6;
      color: white;
    }
    .back {
      background: #ffb703;
      color: black;
      transform: rotateY(180deg);
    }
  </style>
</head>
<body>
  <div class="game-board" id="gameBoard"></div>
  <script>
    // 1. 卡片資料(6 對 = 12 張卡片)
    const symbols = ["🍎", "🍌", "🍇", "🍓", "🍍", "🥝"];
    let cards = [...symbols, ...symbols]; // 複製形成配對
    // 2. 打亂陣列
    cards.sort(() => Math.random() - 0.5);
    const board = document.getElementById("gameBoard");
    let flippedCards = [];
    let lockBoard = false;
    // 3. 建立卡片
    cards.forEach(symbol => {
      const card = document.createElement("div");
      card.classList.add("card");
      card.innerHTML = `
        <div class="card-inner">
          <div class="front">?</div>
          <div class="back">${symbol}</div>
        </div>
      `;
      // 點擊事件
      card.addEventListener("click", () => {
        if (lockBoard || card.classList.contains("flip")) return;
        card.classList.add("flip");
        flippedCards.push(card);
        if (flippedCards.length === 2) {
          checkMatch();
        }
      });
      board.appendChild(card);
    });
    // 4. 檢查配對
    function checkMatch() {
      lockBoard = true;
      const [card1, card2] = flippedCards;
      const symbol1 = card1.querySelector(".back").textContent;
      const symbol2 = card2.querySelector(".back").textContent;
      if (symbol1 === symbol2) {
        flippedCards = [];
        lockBoard = false;
      } else {
        setTimeout(() => {
          card1.classList.remove("flip");
          card2.classList.remove("flip");
          flippedCards = [];
          lockBoard = false;
        }, 1000);
      }
    }
  </script>
</body>
</html>
今日成果
學會如何用 JS 生成卡片,讓遊戲不需要手動寫死。
完成翻牌事件,點擊即可觸發動畫。
加入比對邏輯,讓遊戲開始具備基本的「玩法」。
雖然目前還沒有計分、回合數、勝利判定,但今天的完成度已經讓遊戲進入 可以玩的雛形!後續只要加上更多功能,就能逐漸變成一個完整的小遊戲。