Open In App

Create a Memory Pair Game using React-Native

Last Updated : 08 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will build the interactive Memory Pair Game using the React Native language. We are displaying the 12 boxes to the user, in the user has to click on each box, and when the user clicks on the box the random icon will be shown. Users have to guess or find its match by clicking on the other box. If the user correctly finds that, then the score of the match gets incremented. When the score reaches 6, the user wins the game.

Preview of final output: Let us have a look at how the final output will look like.

pairGame

Output Preview

Prerequisites:

Approach:

The project code in React Native language allows us to build the interactive Memory Pair Game. We can easiy amange the state using the useState hook, and useEffect hook to display the win message. In the UI of the application, there is title as GeeksforGeeks and the application name. Also there are cards which are clickable, when the user clicks on the card they are been flipped by the styling applied to it. The icon behind the card is been shown, the user have to find its matching pair, if user finds the matching pair then the match value is been incremented, else the both the opneed cards are cloesed.

Steps to Create React Native Application:

Step 1: Create a react native application by using this command:

npx create-expo-app memory-game

Step 2: After creating your project folder, i.e. memory-game use the following command to navigate to it:

cd memory-game

Project Structure:

PS

The updated dependencies in package.json file will look like:

  "dependencies": {
"@expo/webpack-config": "^19.0.0",
"expo": "~49.0.13",
"expo-status-bar": "~1.6.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.5",
"react-native-vector-icons": "^10.0.0",
"react-native-web": "~0.19.6"
}

Example: Below is the implementation of the above discussed approach

Javascript




import React, { useState, useEffect } from 'react';
import {
    View, Text, Button, StyleSheet,
    TouchableOpacity, Animated, Easing
} from 'react-native';
import Icon
    from 'react-native-vector-icons/FontAwesome';
const randomArrFunction = (arr) => {
    for (let i = arr.length - 1; i > 0; i--) {
        const j =
            Math.floor(Math.random() * (i + 1));
        [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
};
const gameCardsFunction = () => {
    const icons = [
        'paw',
        'paw',
        'heart',
        'heart',
        'tree',
        'tree',
        'star',
        'star',
        'bell',
        'bell',
        'gift',
        'gift',
    ];
    const randomIcons =
        randomArrFunction(icons);
    return randomIcons.map(
        (icon, index) => ({
            id: index,
            symbol: icon,
            isFlipped: false,
        }));
};
const App = () => {
    const [cards, setCards] =
        useState(gameCardsFunction());
    const [selectedCards, setSelectedCards] =
        useState([]);
    const [matches, setMatches] = useState(0);
    const [winMessage, setWinMessage] =
        useState(new Animated.Value(0));
    const [gameWon, setGameWon] = useState(false);
    const cardClickFunction = (card) => {
        if (!gameWon && selectedCards.length < 2
            && !card.isFlipped) {
            const updatedSelectedCards =
                [...selectedCards, card];
            const updatedCards =
                cards.map((c) =>
                    c.id ===
                        card.id ?
                        { ...c, isFlipped: true } : c
                );
            setSelectedCards(updatedSelectedCards);
            setCards(updatedCards);
            if (updatedSelectedCards.length === 2) {
                if (updatedSelectedCards[0].symbol ===
                    updatedSelectedCards[1].symbol) {
                    setMatches(matches + 1);
                    setSelectedCards([]);
                    if (matches + 1 === cards.length / 2) {
                        geekWinGameFunction();
                        setGameWon(true);
                    }
                } else {
                    setTimeout(() => {
                        const flippedCards =
                            updatedCards.map((c) =>
                                updatedSelectedCards.some((s) =>
                                    s.id === c.id) ?
                                    { ...c, isFlipped: false } : c
                            );
                        setSelectedCards([]);
                        setCards(flippedCards);
                    }, 1000);
                }
            }
        }
    };
    const geekWinGameFunction = () => {
        Animated.timing(winMessage, {
            toValue: 1,
            duration: 1000,
            easing: Easing.linear,
            useNativeDriver: false,
        }).start();
    };
    useEffect(() => {
        if (matches === cards.length / 2) {
            geekWinGameFunction();
            setGameWon(true);
        }
    }, [matches]);
    const msg =
        `Matches: ${matches} /
             ${cards.length / 2}`;
    return (
        <View style={styles.container}>
            <Text style={styles.header1}>
                GeeksforGeeks
            </Text>
            <Text style={styles.header2}>
                Memory Pair Game using React-Native
            </Text>
            <Text style={styles.matchText}>{msg}</Text>
            {gameWon ? (
                <View style={styles.winMessage}>
                    <View style={styles.winMessageContent}>
                        <Text style={styles.winText}>
                            Congratulations Geek!
                        </Text>
                        <Text style={styles.winText}>You Won!</Text>
                    </View>
                    <Button
                        title="Restart"
                        onPress={() => {
                            setCards(gameCardsFunction());
                            setSelectedCards([]);
                            setMatches(0);
                            setWinMessage(new Animated.Value(0));
                            setGameWon(false);
                        }}
                    />
                </View>
            ) : (
                <View style={styles.grid}>
                    {cards.map((card) => (
                        <TouchableOpacity
                            key={card.id}
                            style={
                                [styles.card,
                                card.isFlipped && styles.cardFlipped]}
                            onPress={() => cardClickFunction(card)}
                        >
                            {card.isFlipped ?
                                <Icon name={card.symbol}
                                    size={40} style={styles.cardIcon} /> : null}
                        </TouchableOpacity>
                    ))}
                </View>
            )}
        </View>
    );
};
const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: 'white',
    },
    header1: {
        fontSize: 36,
        marginBottom: 10,
        color: 'green',
    },
    header2: {
        fontSize: 18,
        marginBottom: 20,
        color: 'black',
        fontWeight: 'bold',
    },
    matchText: {
        fontSize: 18,
        color: 'black',
    },
    grid: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        justifyContent: 'center',
    },
    card: {
        width: 80,
        height: 80,
        margin: 10,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#FFD700',
        borderRadius: 10,
        borderWidth: 1,
        borderColor: 'black',
    },
    cardFlipped: {
        backgroundColor: 'white',
    },
    cardIcon: {
        color: 'blue',
    },
    winMessage: {
        position: 'absolute',
        backgroundColor: 'rgba(0, 0, 0, 0.7)',
        width: '100%',
        height: '100%',
        justifyContent: 'center',
        alignItems: 'center',
        zIndex: 1,
    },
    winMessageContent: {
        backgroundColor: 'rgba(255, 215, 0, 0.7)',
        padding: 20,
        borderRadius: 10,
        alignItems: 'center',
    },
    winText: {
        fontSize: 36,
        color: 'white',
    },
});
export default App;


Step 4: Go to the Terminal and type the following command to run the react native application.

npx expo start


To run on Android:

npx react-native run-android


To run on IOS:

npx react-native run-ios


Output:

Record_2023-10-12-21-28-38_f73b71075b1de7323614b647fe394240



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads