Example Output

Physics Whiz Quiz!
--------------------------------------------------------------------------
Please select a quiz category:
1. Kinematics
2. Dynamics
3. Energy & Momentum
4. Waves & Optics
5. Electricity & Magnetism
6. Exit
Enter your choice (1-6): 5
 
Select the difficulty level:
1. Easy
2. Medium
3. Hard
4. I don't care, just give me the questions!
Enter your choice (1-4): 4
How many questions would you like to answer?
Enter your choice (1-4): 3
 
[Question 1]
The unit of electric potential difference is:
1. Ampere (A)
2. Ohm (Ω)
3. Volt (V)
4. Watt (W)
Enter your choice (1-4): 3
Correct!
 
[Question 2]
Ohm's Law states that the current (I) is directly proportional to:
1. Resistance
2. Voltage
3. Power
4. Charge
Enter your choice (1-4): 1
Incorrect. The correct answer was: 2.
 
[Question 3]
A circuit has a resistance of 10 Ω and a current of 2 A. What is the voltage?
1. 5 V
2. 20 V
3. 0.2 V
4. 200 V
Enter your choice (1-4): 2
Correct!
 
Quiz finished!
--------------------------------------------------------------------------
Your final score: 2 out of 3
Percentage: 66.67%
 
Physics Whiz Quiz!
--------------------------------------------------------------------------
Please select a quiz category:
1. Kinematics
2. Dynamics
3. Energy & Momentum
4. Waves & Optics
5. Electricity & Magnetism
6. Exit
Enter your choice (1-6): 6
Goodbye!
 
Process finished with exit code 0

Code

import java.util.ArrayList;  
import java.util.Collections;  
import java.util.List;  
import java.util.Scanner;  
  
public class ISP {  
  
    // Constants for difficulty levels  
    private static final int EASY = 1;  
    private static final int MEDIUM = 2;  
    private static final int HARD = 3;  
    private static final int ALL = 4;  
  
    // Tracks the current score and question index  
    private static int currentScore = 0;  
    private static int questionIndex = 0;  
  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
        do {  
            displayMenu(); // Display the main menu to the user  
            int choice = getUserIntInput(1, 6, scanner);  // Get user input for the category or exit  
            switch (choice) {  
                case 1:  
                case 2:  
                case 3:  
                case 4:  
                case 5:  
                    startQuiz(choice, scanner); // Start the quiz based on the user's choice of category  
                    break;  
                case 6:  
                    System.out.println("Goodbye!"); // Exit message  
                    System.exit(0); // Exit the program  
                    break;  
                default:  
                    System.out.println("Invalid choice. Please try again."); // Handle invalid input  
            }  
        } while (true);  
    }  
  
    /**  
     * Displays the main menu for quiz category selection.     */    private static void displayMenu() {  
        System.out.println("\nPhysics Whiz Quiz!");  
        System.out.println("--------------------------------------------------------------------------");  
        System.out.println("Please select a quiz category:");  
        System.out.println("1. Kinematics");  
        System.out.println("2. Dynamics");  
        System.out.println("3. Energy & Momentum");  
        System.out.println("4. Waves & Optics");  
        System.out.println("5. Electricity & Magnetism");  
        System.out.println("6. Exit");  
    }  
  
    /**  
     * Displays the difficulty level menu.     */    private static void displayDifficultyMenu() {  
        System.out.println("\nSelect the difficulty level:");  
        System.out.println("1. Easy");  
        System.out.println("2. Medium");  
        System.out.println("3. Hard");  
        System.out.println("4. I don't care, just give me the questions!");  
    }  
  
    /**  
     * Retrieves a valid integer input from the user within a specified range.     *     * @param min     The minimum valid input value.  
     * @param max     The maximum valid input value.  
     * @param scanner The scanner object for reading user input.  
     * @return The integer input provided by the user.  
     */    private static int getUserIntInput(int min, int max, Scanner scanner) {  
        int choice = -9999; // Initial invalid value  
        boolean validInput = false; // Flag to control the input loop  
  
        while (!validInput) { // as long as the input is not valid, keep asking for input  
            System.out.print("Enter your choice (" + min + "-" + max + "): ");  
            if (scanner.hasNextInt()) {  
                String choiceRaw = scanner.nextLine();  
                try {  
                    choice = Integer.parseInt(choiceRaw);  
                } catch (NumberFormatException e) {  
                    System.out.println("Invalid input. Please enter a valid integer.");  
                    continue;  
                }  
  
                // Check if the input is within the valid range  
                if (choice >= min && choice <= max) {  
                    validInput = true; // Input is valid, exit the loop  
                } else {  
                    System.out.println("Error: Number out of range. Please try again.");  
                }  
            } else {  
                System.out.println("Error: Invalid input. Please enter a number.");  
                scanner.next(); // Discard the invalid input  
            }  
        }  
        if (choice == -9999) {  
            System.out.println("Invalid input. Please try again."); // Something went wrong in the error handling loop. This should never happen.  
        }  
        return choice;  
    }  
  
    /**  
     * Reduces the list of questions based on the user's input.     *     * @param questions The list of questions to be shortened.  
     * @param scanner   The scanner object for reading user input.  
     * @return A sublist of questions based on the number the user wants to answer.  
     */    private static List<QuizQuestion> cutDownQuestions(List<QuizQuestion> questions, Scanner scanner) {  
        System.out.println("How many questions would you like to answer?");  
        int numQuestions = getUserIntInput(1, questions.size(), scanner);  
  
        List<QuizQuestion> cutDownQuestions = new ArrayList<>();  
        for (int i = 0; i < numQuestions; i++) {  
            cutDownQuestions.add(questions.get(i));  
        }  
        return cutDownQuestions;  
    }  
  
    /**  
     * Starts the quiz by displaying questions based on the selected category and difficulty.     *     * @param categoryIndex The selected category index.  
     * @param scanner       The scanner object for reading user input.  
     */    private static void startQuiz(int categoryIndex, Scanner scanner) {  
        displayDifficultyMenu();  
        int difficultyIndex = getUserIntInput(1, ALL, scanner);  // Get user input for the difficulty  
  
        currentScore = 0;  
        questionIndex = 0;  
        List<QuizQuestion> filteredQuestions = filterQuestions(categoryIndex, difficultyIndex);  
        filteredQuestions = cutDownQuestions(filteredQuestions, scanner); // Limit the number of questions  
        Collections.shuffle(filteredQuestions); // Shuffle the questions  
  
        for (QuizQuestion question : filteredQuestions) {  
            askQuestion(question, scanner);  
            questionIndex++;  
        }  
        displayFinalScore(filteredQuestions.size());  
    }  
  
    /**  
     * Filters questions based on the selected category and difficulty.     *     * @param categoryIndex The index representing the selected category.  
     * @param difficulty    The selected difficulty level.  
     * @return A list of questions matching the category and difficulty.  
     */    private static List<QuizQuestion> filterQuestions(int categoryIndex, int difficulty) {  
        List<QuizQuestion> filtered = new ArrayList<>();  
        for (QuizQuestion q : questions) {  
            if (q.category.equals(getCategoryName(categoryIndex))) {  
                filtered.add(q);  
            }  
        }  
        if (difficulty != ALL) {  
            for (QuizQuestion q : filtered) {  
                if (q.difficulty != difficulty) {  
                    filtered.remove(q); // Remove questions that don't match the selected difficulty  
                }  
            }  
        }  
        return filtered;  
    }  
  
    /**  
     * Retrieves the category name based on its index.     *     * @param index The index representing the category.  
     * @return The name of the category.  
     */    private static String getCategoryName(int index) {  
        String[] categories = {"Kinematics", "Dynamics", "Energy & Momentum", "Waves & Optics", "Electricity & Magnetism"};  
        return categories[index - 1];  
    }  
  
    /**  
     * Asks a question to the user and processes their answer.     *     * @param question The question object containing the question details.  
     * @param scanner  The scanner object for reading user input.  
     */    private static void askQuestion(QuizQuestion question, Scanner scanner) {  
        System.out.println("\n[Question " + (questionIndex + 1) + "]");  
        System.out.println(question.text);  
        for (int i = 0; i < question.options.length; i++) {  
            System.out.println((i + 1) + ". " + question.options[i]);  
        }  
  
        int answer = getUserIntInput(1, question.options.length, scanner);  
        if (answer == question.correctAnswer) {  
            System.out.println("Correct!");  
            currentScore++;  
        } else {  
            System.out.println("Incorrect. The correct answer was: " + question.correctAnswer + ".");  
        }  
    }  
  
    /**  
     * Displays the final score and percentage to the user.     *     * @param totalQuestions The total number of questions in the quiz.  
     */    private static void displayFinalScore(int totalQuestions) {  
        System.out.println("\nQuiz finished!");  
        System.out.println("--------------------------------------------------------------------------");  
        System.out.println("Your final score: " + currentScore + " out of " + totalQuestions);  
        double percentage = (double) currentScore / totalQuestions * 100;  
        System.out.println("Percentage: " + String.format("%.2f", percentage) + "%");  
    }  
  
    // Array containing all quiz questions  
    private static final QuizQuestion[] questions = new QuizQuestion[]{  
            // Kinematics Questions  
            new QuizQuestion("Kinematics", EASY, "What is the formula for average speed?", new String[]{"s = d/t", "s = d * t", "s = d + t", "s = t/d"}, 1),  
            new QuizQuestion("Kinematics", EASY, "Which quantity has both magnitude and direction?", new String[]{"Speed", "Distance", "Time", "Velocity"}, 4),  
            new QuizQuestion("Kinematics", MEDIUM, "A car travels 100 km in 2 hours. What is its average speed?", new String[]{"200 km/h", "50 km/h", "25 km/h", "10 km/h"}, 2),  
            new QuizQuestion("Kinematics", MEDIUM, "An object is dropped from a height. Its initial velocity is:", new String[]{"9.8 m/s", "0 m/s", "Depends on mass", "Depends on height"}, 2),  
            new QuizQuestion("Kinematics", HARD, "A ball is thrown upward with a velocity of 20 m/s. What is its velocity at the highest point?", new String[]{"20 m/s", "10 m/s", "0 m/s", "-10 m/s"}, 3),  
  
            // Dynamics Questions  
            new QuizQuestion("Dynamics", EASY, "Newton's first law of motion is also known as the law of:", new String[]{"Gravity", "Inertia", "Acceleration", "Reaction"}, 2),  
            new QuizQuestion("Dynamics", EASY, "Which force always opposes motion?", new String[]{"Gravity", "Normal force", "Friction", "Tension"}, 3),  
            new QuizQuestion("Dynamics", MEDIUM, "A 10 kg object experiences a net force of 20 N. What is its acceleration?", new String[]{"0.5 m/s^2", "2 m/s^2", "200 m/s^2", "Cannot be determined"}, 2),  
            new QuizQuestion("Dynamics", MEDIUM, "The force of gravity acting on an object is its:", new String[]{"Mass", "Weight", "Density", "Volume"}, 2),  
            new QuizQuestion("Dynamics", HARD, "A 50 N force is applied at a 30-degree angle to a 10 kg box. What is the horizontal component of the force?", new String[]{"25 N", "43.3 N", "86.6 N", "100 N"}, 2),  
  
            // Energy & Momentum Questions  
            new QuizQuestion("Energy & Momentum", EASY, "Kinetic energy is the energy of:", new String[]{"Motion", "Position", "Heat", "Sound"}, 1),  
            new QuizQuestion("Energy & Momentum", EASY, "The law of conservation of energy states that energy:", new String[]{"Cannot be created or destroyed", "Can be created but not destroyed", "Can be destroyed but not created", "Is always constant"}, 1),  
            new QuizQuestion("Energy & Momentum", MEDIUM, "A 2 kg ball is moving at 5 m/s. What is its kinetic energy?", new String[]{"5 J", "10 J", "25 J", "50 J"}, 3),  
            new QuizQuestion("Energy & Momentum", MEDIUM, "What is the unit of work?", new String[]{"Newton (N)", "Joule (J)", "Watt (W)", "Meter (m)"}, 2),  
            new QuizQuestion("Energy & Momentum", HARD, "A 1000 kg car traveling at 20 m/s brakes to a stop. How much work is done by the brakes?", new String[]{"200,000 J", "-200,000 J", "10,000 J", "-10,000 J"}, 2),  
  
            // Waves & Optics Questions  
            new QuizQuestion("Waves & Optics", EASY, "The speed of light in a vacuum is approximately:", new String[]{"3 x 10^8 m/s", "3 x 10^6 m/s", "3 x 10^5 m/s", "3 x 10^3 m/s"}, 1),  
            new QuizQuestion("Waves & Optics", EASY, "The bending of light as it passes from one medium to another is called:", new String[]{"Reflection", "Refraction", "Diffraction", "Dispersion"}, 2),  
            new QuizQuestion("Waves & Optics", MEDIUM, "What is the relationship between the frequency (f) and wavelength (λ) of a wave?", new String[]{"f = λ/v", "f = v/λ", "f = λ * v", "f = v + λ"}, 2),  
            new QuizQuestion("Waves & Optics", MEDIUM, "The image formed by a plane mirror is:", new String[]{"Real and inverted", "Virtual and upright", "Real and upright", "Virtual and inverted"}, 2),  
  
            // Electricity & Magnetism Questions  
            new QuizQuestion("Electricity & Magnetism", EASY, "Ohm's Law states that the current (I) is directly proportional to:", new String[]{"Resistance", "Voltage", "Power", "Charge"}, 2),  
            new QuizQuestion("Electricity & Magnetism", EASY, "The unit of electric potential difference is:", new String[]{"Ampere (A)", "Ohm (Ω)", "Volt (V)", "Watt (W)"}, 3),  
            new QuizQuestion("Electricity & Magnetism", MEDIUM, "A circuit has a resistance of 10 Ω and a current of 2 A. What is the voltage?", new String[]{"5 V", "20 V", "0.2 V", "200 V"}, 2),  
            new QuizQuestion("Electricity & Magnetism", MEDIUM, "The magnetic field lines around a straight current-carrying wire are:", new String[]{"Parallel to the wire", "Radial from the wire", "Circular around the wire", "None of the above"}, 3)  
    };  
}  
  
/**  
 * Class representing a quiz question. */class QuizQuestion {  
    String category;       // The category of the question (e.g., Kinematics)  
    int difficulty;        // The difficulty level of the question (EASY, MEDIUM, HARD)  
    String text;           // The question text  
    String[] options;      // The possible answers  
    int correctAnswer;     // The index of the correct answer (1-based index)  
  
    public QuizQuestion(String category, int difficulty, String text, String[] options, int correctAnswer) {  
        this.category = category;  
        this.difficulty = difficulty;  
        this.text = text;  
        this.options = options;  
        this.correctAnswer = correctAnswer;  
    }  
}