網頁前端6

楓資 廖姸惁

Index

JS

JS

const game = document.getElementById("game");

const icons = ["🍎", "🍎", "🍌", "🍌", "🍓", "🍓", "🍇", "🍇", "🍉", "🍉", "🥝", "🥝", "🍊", "🍊", "🍒", "🍒"];
let cards = [];
let flippedCards = [];
let matchedCount = 0;

取得 HTML 裡 id 為 game 的那個 <div>

icons: 陣列

用來存放所有創建出來的卡牌元素

當玩家翻開卡片時,會把目前翻開但尚未比對的卡放到這個陣列

紀錄已經配對成功的卡數,用來判斷遊戲是否完成

JS

icons.sort(() => Math.random() - 0.5);

Math.random() - 0.5 會回傳大約在 -0.5 到 +0.5 之間的數,正或負隨機決定,因此每次比較時都會隨機決定哪個元素先後,達成亂序。

JS

for (let i = 0; i < icons.length; i++) {
  const card = document.createElement("div");
  card.classList.add("card");
  card.dataset.icon = icons[i];
  card.addEventListener("click", flipCard);
  game.appendChild(card);
  cards.push(card);
}

這張卡牌上增加一個屬性:data-icon="🍎"。放在 dataset 裡,方便之後取用。(這行不會顯示文字,只是把資料藏起來。)

當玩家點擊時會呼叫 flipCard 函式(後面的)

把這個 card 加到 #game 容器中,於畫面上顯示。

把這個 card 的物件存進 cards 陣列,日後可用來檢查遊戲狀態或重置等。

為每個圖示建立一個新的<div>代表一張卡片。

加上 CSS class card,讓它拿到你在 CSS 裡定義的外觀

JS

function flipCard(e) {
  const card = e.target;

  if (card.classList.contains("flipped") || card.classList.contains("matched")) {
    return;
  }

  card.classList.add("flipped");
  card.textContent = card.dataset.icon;
  flippedCards.push(card);

  if (flippedCards.length === 2) {
    checkMatch();
  }
}

e.target 是被點到的那張卡

如果卡片已經翻開或已經配對成功則不讓玩家再按它

從剛剛藏的 data-icon 拿出水果圖示,顯示出來。

加上 CSS 樣式

記錄這張牌是「已翻」

如果翻到 2 張 → 準備比對

JS

function checkMatch() {
  const [card1, card2] = flippedCards;

  if (card1.dataset.icon === card2.dataset.icon) {
    card1.classList.add("matched");
    card2.classList.add("matched");
    matchedCount += 2;
    flippedCards = [];

    if (matchedCount === cards.length) {
      setTimeout(() => alert("🎉 恭喜完成!"), 300);
    }
  } 
  	else {
    	setTimeout(() => {
      		card1.classList.remove("flipped");
        	card2.classList.remove("flipped");
      		card1.textContent = "";
      		card2.textContent = "";
          	flippedCards = [];
        }, 800);
  	}
}

把 flippedCards[0]、flippedCards[1] 拿出來,一個叫 card1、一個叫 card2。

水果圖案一樣 → 成功配對!加上綠色背景、鎖定不能再按。

紀錄成功的卡片數。

清空,等下一次翻牌。

成功的卡數=全部卡數

稍微延遲300毫秒,避免最後一張還沒完全亮出來就跳通知

等800再蓋回去

蓋回去

變成空白卡

準備下一輪翻牌

完整程式碼

HTML

<!DOCTYPE html>
<html lang="zh-Hant">
<head>
  <meta charset="UTF-8" />
  <title>卡牌配對記憶遊戲</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <h1>卡牌配對記憶遊戲</h1>
  <div id="game"></div>
  <script src="script.js"></script>
</body>
</html>

CSS

body {
  text-align: center;
  background-color: white;
}


#game {
  display: grid;
  grid-template-columns: repeat(4, 100px);
  gap: 10px;
  justify-content: center;
}


.card {
  width: 100px;
  height: 100px;
  background-color: #9cade1;
  color: white;
  font-size: 40px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  border-radius: 10px;
  user-select: none;
  transition: background-color 0.3s;
}


.flipped {
  background-color: #fbf8d7;
  color: #333;
  cursor: default;
}


.matched {
  background-color: #c9e1c9;
  color: #333;
}

JS

const game = document.getElementById("game");


const icons = ["🍎", "🍎", "🍌", "🍌", "🍓", "🍓", "🍇", "🍇", "🍉", "🍉", "🥝", "🥝", "🍊", "🍊", "🍒", "🍒"];
let cards = [];
let flippedCards = [];
let matchedCount = 0;


icons.sort(() => Math.random() - 0.5);


for (let i = 0; i < icons.length; i++) {
  const card = document.createElement("div");
  card.classList.add("card");
  card.dataset.icon = icons[i];
  card.addEventListener("click", flipCard);
  game.appendChild(card);
  cards.push(card);
}


function flipCard(e) {
  const card = e.target;


  if (card.classList.contains("flipped") || card.classList.contains("matched")) {
    return;
  }


  card.classList.add("flipped");
  card.textContent = card.dataset.icon;
  flippedCards.push(card);


  if (flippedCards.length === 2) {
    checkMatch();
  }
}


function checkMatch() {
  const [card1, card2] = flippedCards;


  if (card1.dataset.icon === card2.dataset.icon) {
    card1.classList.add("matched");
    card2.classList.add("matched");
    matchedCount += 2;
    flippedCards = [];


    if (matchedCount === cards.length) {
      setTimeout(() => alert("🎉 恭喜完成!"), 300);
    }
  } else {
    setTimeout(() => {
      card1.classList.remove("flipped");
      card2.classList.remove("flipped");
      card1.textContent = "";
      card2.textContent = "";
      flippedCards = [];
    }, 800);
  }
}

THANKS!

網頁前端6

By ys

網頁前端6

  • 12