Problem Statement
Build a memory game. Show a grid of face down cards. The player flips two at a time to find pairs with the same number.
Functional Requirements
- Grid: Show 36 cards in a 6 column grid, made of the numbers 1 to 18 twice, shuffled on load.
- Flip: A face down card shows
?. Clicking it shows its number. - Two at a time: After two cards are open, lock the board so no other card can be flipped.
- Match check: After 3 seconds, keep the two cards face up if their numbers match. Otherwise flip both back.
- Unlock: Clear the open pair and unlock the board after the check.
Technical Constraints
- Keep the game state in a custom hook,
useGameLogic, and keepCardpresentational. - Update card objects immutably and clear the 3 second timer on cleanup.
- There is no move counter, win message or restart.
Overview
This documentation covers a React-based Memory Game implementation where players match pairs of numbered cards. The game features a grid of face-down cards that players can flip to find matching pairs.
Components Structure
1. MemoryGame Component (Main Component)
const MemoryGame = () => {
const { cards, handleCardClick } = useGameLogic();
// ... component JSX
};- Purpose: Serves as the main game container
- Key Features:
- Uses custom hook
useGameLogicfor game state management - Renders a grid of Card components
- Maps through cards array to display individual cards
- Uses custom hook
2. Card Component
const Card = ({ number, isFlipped, onClick }) => (
<div className="cards" onClick={onClick}>
{isFlipped ? number : "?"}
</div>
);- Props:
number: The card's valueisFlipped: Boolean indicating if card is face uponClick: Click handler function
- Functionality: Displays either the card number or "?" based on isFlipped state
Game Logic Implementation
useGameLogic Custom Hook
This hook manages the game's core logic and state:
export const useGameLogic = () => {
const [cards, setCards] = useState(generateGrid);
const [isLock, setIsLock] = useState(false);
const [flippedCard, setFlippedCard] = useState([]);
// ... hook logic
};Key States:
cards: Array of card objectsisLock: Prevents card flipping during matching checkflippedCard: Tracks currently flipped cards
Main Functions:
-
handleCardClick(index):- Handles card flip logic
- Prevents flipping if card is already flipped or game is locked
- Updates card state and tracks flipped cards
-
useEffectLogic:- Triggers when two cards are flipped
- Implements 3-second delay for checking matches
- Flips cards back if they don't match
Grid Generation Utility
export const generateGrid = () => {
const arr = Array.from({ length: 18 }, (_, index) => index + 1);
// ... grid generation logic
};- Creates an array of 18 numbers
- Duplicates array for pairs
- Shuffles cards randomly
- Returns array of card objects with properties: id, number, isFlipped
Code Flow and Dry Run
-
Initial Load:
- generateGrid creates shuffled card array
- MemoryGame component renders grid
- All cards show "?"
-
First Card Click:
// Example state after first click: flippedCard = [3]; // Index of clicked card cards[3] = { id: 3, number: 7, isFlipped: true }; -
Second Card Click:
// State after second click: flippedCard = [3, 8]; cards[8] = { id: 8, number: 4, isFlipped: true }; -
Match Check:
- If numbers match: Cards remain face up
- If numbers don't match: Cards flip face down after 3 seconds
- flippedCard array clears
- Game unlocks for next moves
Key JavaScript Methods Used
-
Array.from(): Creates new array from array-like object
Array.from({ length: 18 }, (_, index) => index + 1); -
sort() with Math.random(): Shuffles array randomly
array.sort(() => Math.random() - 0.5); -
Spread Operator (...): Creates array copies
[...arr, ...arr]; -
map(): Transforms array elements
grid.map((item, index) => ({...}))