برنامه نویسی

React Native Speed ​​Math App

سلام به همه، من بعد از 1 سال و 4 ماه برگشتم. این بار با پروژه react native.

بیایید پروژه را شروع کنیم
من این پروژه را با Expo ایجاد کردم و از Expo Router استفاده شده برای مسیریابی استفاده کردم.
یک پوشه جدید ایجاد کنید و ترمینال را باز کنید و این دستور را اجرا کنید

npx create-expo-app@latest
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پس از اجرای موفقیت آمیز این دستور، می توانید کد boilerplate را حذف کرده و با یک پروژه جدید شروع به کار کنید. دستور زیر را برای ریست کردن پروژه خود اجرا کنید:

npm run reset-project
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

قبل از پرش به کد، بیایید عملکرد برنامه خود را درک کنیم.
هنگامی که کاربر در صفحه اصلی است، کاربر باید یک عملیات ریاضی را انتخاب کند که می خواهد تمرین کند.

صفحه اصلی

هنگامی که آنها عملیات را انتخاب کردند، سپس به صفحه آزمون منتقل می شوند و سؤالات در صفحه کاربر ظاهر می شوند. کاربر باید در مدت 10 ثانیه به سوال پاسخ دهد و اگر پاسخ صحیح باشد امتیاز 1 افزایش می یابد و سؤال بعدی ظاهر می شود و اگر کاربر در مدت 10 ثانیه به سؤال پاسخ ندهد سؤال بعدی ارائه می شود.

صفحه مسابقه

app نقطه شروع برنامه ما و داخل است app، _layout.tsx چیدمان ریشه ما است و index.tsx صفحه اصلی ما است

_layout.tsx :-

import { Stack } from "expo-router";

export default function RootLayout() {
  return (
    
      
      
    
  );
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون دو صفحه داریم، یکی صفحه اصلی و دیگری یک صفحه پویا است که سوالات را بر اساس عملیات انتخاب شده توسط کاربر ارائه می دهد.

index.tsx :-

// HomeScreen.js
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import {router} from 'expo-router'

const HomeScreen = () => {

  const handleStartQuiz = (operation: string) => {
    router.push({pathname:'/quiz/[id]',
    params:{id:operation}

    }

    )
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Choose a Operation:</Text>
      <Button title="Addition" onPress={() => handleStartQuiz('addition')} />
      <Button title="Subtraction" onPress={() => handleStartQuiz('subtraction')} />
      <Button title="Multiplication" onPress={() => handleStartQuiz('multiplication')} />
      <Button title="Division" onPress={() => handleStartQuiz('division')} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    display:'flex',
    marginTop:60,
    justifyContent: 'center',
    // alignItems: 'center',
    rowGap:10,
    margin:20
  },
  title: {
    fontSize: 20,
    marginTop: 20,
  },
});

export default HomeScreen;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا یک پوشه جدید بسازید app/quiz و داخل آن مسیری پویا ایجاد می کند [id].tsx

[id]tsx :-

// QuizScreen.js
import { useLocalSearchParams } from 'expo-router';
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, StyleSheet, SafeAreaView } from 'react-native';

const QuizScreen = () => {
    const { id } = useLocalSearchParams<{id:string}>();
    const operation = typeof id === 'string' ? id : 'addition'; // Provide a default operation if id is undefined or not a string
    const [num1, setNum1] = useState(0);
    const [num2, setNum2] = useState(0);
    const [userAnswer, setUserAnswer] = useState('');
    const [score, setScore] = useState(0);
    const [time, setTime] = useState(10);

    useEffect(() => {
        console.log('Operation from params:', operation);
        generateQuestion();
    }, [operation]);

    const generateQuestion = () => {
        switch (operation) {
            case 'addition':
                setNum1(Math.floor(Math.random() * 100) + 1);
                setNum2(Math.floor(Math.random() * 100) + 1);
                break;
            case 'subtraction':
                setNum2(Math.floor(Math.random() * 100) + 1);
                setNum1(Math.floor(Math.random() * 100) + 1); // Adjusted to ensure num2 is generated properly
                break;
            case 'multiplication':
                setNum1(Math.floor(Math.random() * 100) + 1);
                setNum2(Math.floor(Math.random() * 10) + 1);
                break;
            case 'division':
                const divisor = Math.floor(Math.random() * 9) + 1;
                const quotient = Math.floor(Math.random() * 100) + 1;
                setNum2(divisor);
                setNum1(divisor * quotient);
                break;
            default:
                setNum1(0);
                setNum2(0);
        }
    };

    const handleAnswerChange = (text:string) => {
        setUserAnswer(text);
        const answer = calculateAnswer();
        const tolerance = 0.0001; // Adjust tolerance level as needed
        if (Math.abs(parseFloat(text) - answer) <= tolerance) {
            setScore(score + 1);
            handleNextQuestion();
        }
    };

    const calculateAnswer = () => {
        switch (operation) {
            case 'addition':
                return num1 + num2;
            case 'subtraction':
                return num1 - num2;
            case 'multiplication':
                return num1 * num2;
            case 'division':
                return num1 / num2; // Ensure it's a precise division
            default:
                return num1 + num2; // Default to addition
        }
    };

    const handleNextQuestion = () => {
        generateQuestion();
        setUserAnswer('');
        setTime(10);
    };

    useEffect(() => {
        const timer = setInterval(() => {
            setTime((prevTime) => {
                if (prevTime > 0) {
                    return prevTime - 1;
                } else {
                    handleNextQuestion();
                    return 10; // Reset timer to 10 seconds for the next question
                }
            });
        }, 1000);

        return () => clearInterval(timer);
    }, []);

    return (
        <SafeAreaView style={styles.container}>
            <Text style={{ fontWeight: 'bold', fontSize: 38 }}>Speed Math</Text>
            <View style={styles.topBar}>
                <View>
                    <Text style={styles.timer}><Text></Text> {time} secText>
                </View>
                <Text style={styles.score}>Score: {score}</Text>
            </View>
            <Text style={styles.question}>
                {num1} {getOperationSymbol(operation)} {num2} =
            </Text>
            <TextInput
                style={styles.input}
                keyboardType="numeric"
                value={userAnswer}
                onChangeText={handleAnswerChange}
                autoFocus={true}
            />
        </SafeAreaView>
    );
};

const getOperationSymbol = (operation:string) => {
    switch (operation) {
        case 'addition':
            return '+';
        case 'subtraction':
            return '-';
        case 'multiplication':
            return '×';
        case 'division':
            return '÷';
        default:
            return '+';
    }
};

const styles = StyleSheet.create({
    container: {
        marginTop:50,
        flex: 1,
        alignItems: 'center',
    },
    question: {
        fontSize: 20,
        marginTop: 200,
        marginBottom: 10,
    },
    input: {
        height: 40,
        borderColor: 'gray',
        borderWidth: 1,
        marginBottom: 20,
        textAlign: 'center',
        width: 100,
    },
    timer: {
        marginTop: 10,
        fontSize: 16,
        fontWeight: 'bold',
    },
    score: {
        marginTop: 10,
        fontSize: 16,
        fontWeight: 'bold',
    },
    topBar: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        gap: 30,
        alignItems: 'center',
        width: 360,
    },
});

export default QuizScreen;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

*نکات مهم *

  • اینجا،useLocalSearchParams از جانب expo-router برای استخراج پارامترهای پرس و جو از URL استفاده می شود.
  • useLocalSearchParams را استخراج می کند id پارامتر از URL، که نوع عملیات حسابی را تعیین می کند.
  • عملیات نوع عملیات را بر اساس تنظیم می کند id یا پیش‌فرض «افزودن» است.
  • متغیرهای حالت را مقداردهی اولیه می کنیم: num1، num2، userAnswer، score، و time.

تابعی برای ایجاد سوالات

    const generateQuestion = () => {
        switch (operation) {
            case 'addition':
                setNum1(Math.floor(Math.random() * 100) + 1);
                setNum2(Math.floor(Math.random() * 100) + 1);
                break;
            case 'subtraction':
                setNum2(Math.floor(Math.random() * 100) + 1);
                setNum1(Math.floor(Math.random() * 100) + 1);
                break;
            case 'multiplication':
                setNum1(Math.floor(Math.random() * 100) + 1);
                setNum2(Math.floor(Math.random() * 10) + 1);
                break;
            case 'division':
                const divisor = Math.floor(Math.random() * 9) + 1;
                const quotient = Math.floor(Math.random() * 100) + 1;
                setNum2(divisor);
                setNum1(divisor * quotient);
                break;
            default:
                setNum1(0);
                setNum2(0);
        }
    };
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من تازه وارد واکنش نیتیو هستم و شاید در توضیح کد آنقدرها خوب نباشم. با این حال، شما می توانید با من تماس بگیرید
لینکدین
Live Apk
کد

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا