網頁前端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