Math Sprint Game in VueJS

The Math Sprint Game is a simple web-based game designed to help users practice basic arithmetic operations such as addition and subtraction in a fun and interactive way. It generates random math problems for the users to solve within the limited time frame testing their mental math skills and agility.

Prerequisites:

Approach

  • Initialize the Vue instance and define the necessary data properties such as the math problem, user answer, results, and time-tracking variables.
  • Implement the method to generate random math problems with addition or subtraction.
  • To Create a method to validate the user’s answer, update the correct/incorrect counts, and track the number of the remaining questions.
  • The Start the timer at the beginning of the game and calculate the total time taken when the game ends converting the time into the minutes and seconds.
  • The Provide the method to the reset all variables and restart the game including the regenerating problems and restarting the timer.

CDN link:

https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js

Example: This example shows the implementation of the above-explained approach.

HTML
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,
                                   initial-scale=1.0">
    <title>The Math Sprint Game</title>
    <link href=
"https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"
          rel="stylesheet">
    <style>
        .problem-container {
            background-color: #F3F4F6;
        }

        .answer-input {
            border: 2px solid #D1D5DB;
        }
    </style>
</head>

<body class="bg-gradient-to-b from-blue-400
             to-blue-700 min-h-screen flex 
             items-center justify-center">
    <div id="app" class="bg-white p-8 rounded-lg
                         shadow-md w-full max-w-md">
        <h1 class="text-3xl font-bold text-center 
                   text-gray-800 mb-6">Math Sprint Game</h1>
        <div v-if="!finished">
            <div class="problem-container
                        mb-4 p-4 rounded-md">
                <p id="problem" class="text-xl font-semibold
                                       text-gray-800">{{ problem }}</p>
            </div>
            <input type="number" v-model="answer"
                class="answer-input block w-full
                       px-4 py-2 border border-gray-300
                       rounded-md focus:outline-none
                       focus:ring-2 focus:ring-blue-500
                       focus:border-transparent"
                placeholder="Your Answer">
            <div class="flex justify-center mt-4">
                <button @click="checkAnswer"
                    class="px-6 py-3 bg-green-500 text-white
                           rounded-md hover:bg-green-600
                           focus:outline-none focus:ring-2
                           focus:ring-green-500 
                           focus:ring-opacity-50">
                    Submit
                </button>
            </div>
        </div>
        <div id="result" class="mt-4 text-xl font-semibold
                                text-gray-800 text-center"
             v-show="result !== ''">{{ result
            }}</div>
        <div v-if="finished" class="mt-4 text-xl 
                                    font-semibold text-gray-800 
                                    text-center">
            <p>Game Over!</p>
            <p>Correct Answers: {{ correctAnswers }}</p>
            <p>Incorrect Answers: {{ incorrectAnswers }}</p>
            <p>Total Time: {{ formatTime(totalTime) }}</p>
            <button @click="restartGame"
                class="mt-4 px-6 py-3 bg-blue-500 
                       text-white rounded-md hover:bg-blue-600
                       focus:outline-none focus:ring-2
                       focus:ring-blue-500 
                       focus:ring-opacity-50">
                Restart Game
            </button>
        </div>
    </div>
    <script src=
"https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">
      </script>
    <script>
        new Vue({
            el: '#app',
            data: {
                problem: '',
                answer: null,
                result: '',
                correctAnswers: 0,
                incorrectAnswers: 0,
                questionsLeft: 10,
                finished: false,
                startTime: null,
                endTime: null,
                totalTime: 0
            },
            methods: {
                generateProblem() {
                    const num1 = Math.floor(Math.random() * 10) + 1;
                    const num2 = Math.floor(Math.random() * 10) + 1;
                    const operator = Math.random() < 0.5 ? '+' : '-';
                    this.problem = `${num1} ${operator} ${num2}`;
                },
                checkAnswer() {
                    if (!this.answer) {
                        alert('Please provide an answer.');
                        return;
                    }
                    const [num1, operator, num2] = this.problem.split(' ');
                    let correctAnswer;
                    if (operator === '+') {
                        correctAnswer = parseInt(num1) + parseInt(num2);
                    } else {
                        correctAnswer = parseInt(num1) - parseInt(num2);
                    }
                    if (parseInt(this.answer) === correctAnswer) {
                        this.result = 'Correct!';
                        this.correctAnswers++;
                    } else {
                        this.result = 'Incorrect!!';
                        this.incorrectAnswers++;
                    }
                    this.answer = null;
                    this.questionsLeft--;
                    if (this.questionsLeft === 0) {
                        this.finished = true;
                        this.endTime = new Date();
                        this.totalTime = Math.round((this.endTime 
                                                   - this.startTime) / 1000);
                    } else {
                        setTimeout(() => {
                            this.result = '';
                            this.generateProblem();
                            // Generate next problem
                        }, 1500);
                    }
                },
                formatTime(totalSeconds) {
                    const minutes = Math.floor(totalSeconds / 60);
                    const seconds = totalSeconds % 60;
                    return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
                },
                restartGame() {
                    this.problem = '';
                    this.answer = null;
                    this.result = '';
                    this.correctAnswers = 0;
                    this.incorrectAnswers = 0;
                    this.questionsLeft = 10;
                    this.finished = false;
                    this.startTime = null;
                    this.endTime = null;
                    this.totalTime = 0;
                    this.generateProblem();
                  // Start the timer
                    this.startTime = new Date(); 
                }
            },
            mounted() {
              // Generate initial problem
                this.generateProblem(); 
              // Start the timer again
                this.startTime = new Date(); 
            }
        });
    </script>
</body>

</html>

Output: