import React, { useEffect, useMemo, useState } from “react”; import { motion } from “framer-motion”; import { Button } from “@/components/ui/button”; import { Card, CardContent } from “@/components/ui/card”; const flowers = [ { name: “Rose”, emoji: “🌹” }, { name: “Tulipan”, emoji: “🌷” }, { name: “Solsikke”, emoji: “🌻” }, { name: “Hibiscus”, emoji: “🌺” }, { name: “Margerit”, emoji: “🌼” }, { name: “Blomst”, emoji: “🌸” }, ]; function createDeck(items) { return items.flatMap((flower, index) => [ { …flower, id: `${index}-a`, pairId: index }, { …flower, id: `${index}-b`, pairId: index }, ]); } function shuffle(array) { const copy = […array]; for (let index = copy.length – 1; index > 0; index -= 1) { const randomIndex = Math.floor(Math.random() * (index + 1)); [copy[index], copy[randomIndex]] = [copy[randomIndex], copy[index]]; } return copy; } function runGameLogicTests() { const deck = createDeck(flowers); console.assert(deck.length === flowers.length * 2, “Deck should contain exactly two cards per flower.”); const pairCounts = deck.reduce((counts, card) => { counts[card.pairId] = (counts[card.pairId] || 0) + 1; return counts; }, {}); console.assert( Object.values(pairCounts).every((count) => count === 2), “Each flower should appear as exactly one pair.” ); const shuffledDeck = shuffle(deck); console.assert(shuffledDeck.length === deck.length, “Shuffle should keep the same number of cards.”); console.assert(shuffledDeck !== deck, “Shuffle should return a new array instead of mutating the original deck.”); console.assert( new Set(shuffledDeck.map((card) => card.id)).size === deck.length, “Shuffle should preserve all unique card ids.” ); } runGameLogicTests(); function FlowerIcon() { return ; } function ResetIcon() { return ; } export default function FlowerMemoryGame() { const [cards, setCards] = useState([]); const [flipped, setFlipped] = useState([]); const [matched, setMatched] = useState([]); const [moves, setMoves] = useState(0); const [startedAt, setStartedAt] = useState(Date.now()); const [seconds, setSeconds] = useState(0); const totalPairs = flowers.length; const gameWon = matched.length === totalPairs * 2 && cards.length > 0; const newDeck = useMemo(() => createDeck(flowers), []); function resetGame() { setCards(shuffle(newDeck)); setFlipped([]); setMatched([]); setMoves(0); setStartedAt(Date.now()); setSeconds(0); } useEffect(() => { resetGame(); }, []); useEffect(() => { if (gameWon) return undefined; const timer = setInterval(() => { setSeconds(Math.floor((Date.now() – startedAt) / 1000)); }, 1000); return () => clearInterval(timer); }, [startedAt, gameWon]); useEffect(() => { if (flipped.length !== 2) return undefined; const [first, second] = flipped; setMoves((count) => count + 1); if (!cards[first] || !cards[second]) { setFlipped([]); return undefined; } if (cards[first].pairId === cards[second].pairId) { setMatched((current) => […current, cards[first].id, cards[second].id]); setFlipped([]); return undefined; } const timeout = setTimeout(() => setFlipped([]), 850); return () => clearTimeout(timeout); }, [flipped, cards]); function handleCardClick(index) { const card = cards[index]; if (!card) return; if (flipped.length === 2) return; if (flipped.includes(index)) return; if (matched.includes(card.id)) return; setFlipped((current) => […current, index]); } return (
Blomstervendespil

Find de matchende blomster

Vend to kort ad gangen. Kan du finde alle parrene?

{moves}
Træk
{matched.length / 2}
Par
{seconds}s
Tid
{gameWon && (
🎉

Flot klaret!

Du fandt alle blomsterpar på {moves} træk.

)}
{cards.map((card, index) => { const isOpen = flipped.includes(index) || matched.includes(card.id); return ( ); })}
); }