import "./styles.css";
import React, { useState, useEffect } from "react";
const values = [1, 2, 3, 4, 5];
type Card = {
id: number;
value: number;
isFlipped: boolean;
isMatched: boolean;
};
function getShuffledCards(): Card[] {
const deck = [...values, ...values].map((value, index) => ({
id: index,
value,
isFlipped: false,
isMatched: false,
}));
// Shuffle
return deck.sort(() => Math.random() - 0.5);
}
export default function App() {
const [cards, setCards] = useState<Card[]>(getShuffledCards);
const [selected, setSelected] = useState<number[]>([]);
useEffect(() => {
if (selected.length !== 2) return;
const [first, second] = selected;
const card1 = cards[first];
const card2 = cards[second];
if (card1.value === card2.value) {
setCards((prev) =>
prev.map((card, i) =>
i === first || i === second ? { ...card, isMatched: true } : card
)
);
setSelected([]);
} else {
// flip back after delay
setTimeout(() => {
setCards((prev) =>
prev.map((card, i) =>
i === first || i === second ? { ...card, isFlipped: false } : card
)
);
setSelected([]);
}, 800);
}
}, [selected, cards]);
const handleCardClick = (index: number) => {
if (
cards[index].isFlipped ||
cards[index].isMatched ||
selected.length === 2
)
return;
setCards((prev) =>
prev.map((card, i) => (i === index ? { ...card, isFlipped: true } : card))
);
setSelected((prev) => [...prev, index]);
};
return (
<div className="App">
<div className="grid">
{cards.map((card, index) => (
<div
key={card.id}
className={`card ${
card.isFlipped || card.isMatched ? "flipped" : ""
}`}
onClick={() => handleCardClick(index)}
>
<div className="card-inner">
{card.isFlipped || card.isMatched ? card.value : "?"}
</div>
</div>
))}
</div>
</div>
);
}
.App {
font-family: sans-serif;
padding: 20px;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 80px);
gap: 12px;
justify-content: center;
}
.card {
width: 80px;
height: 80px;
background: #2c3e50;
color: white;
font-size: 24px;
cursor: pointer;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
transition: transform 0.3s, background 0.3s;
}
.card.flipped {
background: #27ae60;
transform: scale(1.05);
}
.card-inner {
font-weight: bold;
}

Top comments (0)