iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0

Day 17
主題:JS DOM 操作 — 建立卡片生成與翻牌事件
今日目標
前幾天完成了介面、切版、配色以及基本動畫,現在正式進入遊戲邏輯的實作。今天的重點是使用 JavaScript 操作 DOM,讓遊戲能夠:

  1. 動態生成卡片(避免手動寫死在 HTML)。
  2. 建立翻牌事件(點擊卡片可以翻轉)。
  3. 讓卡片之間開始有基礎的互動(初步的比對邏輯)。
    這是遊戲從「靜態網頁」轉變成「互動遊戲」的第一步。

學習與操作重點

  1. DOM 生成元素
    使用 document.createElement 動態建立卡片。
    將卡片加入遊戲區塊(appendChild)。
    為卡片設計 front(背面符號)與 back(正面符號)兩層。

  2. 事件監聽
    使用 addEventListener("click", ...) 監聽卡片的翻牌行為。
    透過切換 CSS class(如 flip)來觸發翻牌動畫。

  3. 遊戲互動邏輯雛形
    記錄已翻開的兩張卡片。
    如果兩張相同 → 保持翻開狀態。
    如果不同 → 等待一小段時間後再翻回去。
    避免短時間內快速點擊導致 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 生成卡片,讓遊戲不需要手動寫死。
完成翻牌事件,點擊即可觸發動畫。
加入比對邏輯,讓遊戲開始具備基本的「玩法」。
雖然目前還沒有計分、回合數、勝利判定,但今天的完成度已經讓遊戲進入 可以玩的雛形!後續只要加上更多功能,就能逐漸變成一個完整的小遊戲。


上一篇
Day 16 | CSS動畫
下一篇
Day 18 | 基礎邏輯測試
系列文
30天打造純前端互動小遊戲網站19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言