I’m creating a simple memory game in react and have a problem where it is possible to select more than two cards at once. The game works as it should when only clicking two cards, but breaks if you select more.
I have tried to limit the amount of cards in openCards to 2 before flipping another, but it didn’t work. I have also considered adding all cards that are not open to disabledCards when you’ve selected two, but that would mix them up with the cards that are already a match.
function App() {
const [images, setImages] = useState([]);
const [openCards, setOpenCards] = useState([]);
const [shouldFlipBack, setShouldFlipBack] = useState(false);
const [disabledCards, setDisabledCards] = useState([]); //cards that are matched
const imageArray = [
{type: "penguin", image: penguin},
{type: "penguin", image: penguin},
{type: "snail", image: snail},
{type: "snail", image: snail},
{type: "chicken", image: chicken},
{type: "chicken", image: chicken},
{type: "raccoon", image: raccoon},
{type: "raccoon", image: raccoon},
{type: "fox", image: fox},
{type: "fox", image: fox}
];
useEffect(() => {
setImages((prevImages) => shuffleImages(prevImages));
}, []);
useEffect(() => {
if (openCards.length === 2) {
checkIfMatch();
setOpenCards([]);
}
}, [openCards]);
function checkIfMatch() {
if (openCards[0] === openCards[1]) {
console.log("match");
setDisabledCards(()=> [...disabledCards, openCards[0]]);
setShouldFlipBack(false);
} else {
console.log("not match");
setTimeout(() => {
setShouldFlipBack(true);
}, 1000);
}
setShouldFlipBack(false);
}
function Card({card, setOpenCards, openCards, shouldFlipBack, disabledCards}) {
const [isFlipped, setFlipped] = useState(false);
useEffect(() => {
if (!disabledCards.includes(card.type)) {
setTimeout(() => {
setFlipped(false);
}, 500);
}
}, [shouldFlipBack]);
function flipCard() {
if (!disabledCards.includes(card.type)) {
setFlipped(!isFlipped);
setOpenCards(()=> [...openCards, card.type]);
}
}
return (
<div className="card" onClick={flipCard}>
<div className={isFlipped ? "card-inner flipped" : "card-inner"}>
<div className="card-front"></div>
<div className="card-back">
{isFlipped && <img src={card.image} alt="card" />}
</div>
</div>
</div>
);
}
export default Card;