2
\$\begingroup\$

I m new in java and created a small project in which you have to solve random math problems there is three levels in it Easy, Medium , Hard, if you win or loss in game the message for three level will be different

Flaws in my program:I didn't use float as data type so there is no question on division and % is not available

package Main;

import java.util.Random;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {

    System.out.println("***************** Welcome to Game of Math ***********************");
    Scanner inputScanner = new Scanner(System.in);

    //genrating random numbers
    Random random = new Random();

    //Assing variables
    int easyNum1 = random.nextInt(11);
    int mediumNum1 =  random.nextInt(101);
    int hardNum1 =  random.nextInt(10000);

    int easyNum2 =  random.nextInt(11);
    int mediumNum2 = random.nextInt(101);
    int hardNum2 = random.nextInt(10000);

    System.out.println("Enter || E for easy || M for medium and || H for hard");
    //Getting user input for game tougness level
    char levelInput= inputScanner.next().charAt(0);



    //Genrating Random win and lose messages
    //For easy level
        //Win
    String[] winMessageEasy = {
        "Correct",
        "Yes you are right",
        "Good",
        "Your basics is good",
        "Keep going"
    };
        //Lose
    String[] lossMessageEasy = {
        "Bruhh thats wrong",
        "Nahh",
        "Wrong",
        "Boy u need to join primary school",

    };
    //for medium level
        //Win
    String[] winMessageMedium= {
            "Cool",
            "Bravo",
            "You are cool",
            "Good",
            "Oh yea",
            "oh Boy",

    };
        //Lose
    String[] loseMessageMedium={
            "Thats not look right",
            "No sorry",
            "Nope",
            "Sorry! thats inncorect",

    };
    //for Hard level
        //Win
    String[] winMessageHard = {
            "Dammm you are correct",
            "Oh yea thats right",
            "Good fella",
            "Your math is good",
            "you are a phenomena",
            "Cool bro",
            "Fab"
    };
        //Lose
    String[] loseMessageHard = {
            "Duhh",
            "mehhh",
            "nope",
            "no",
            "try again",
            "sorry! thats wrong"
    };

    //Random win message genrator for easy level
    int easyWinRandomInt = random.nextInt(winMessageEasy.length);
    String easyWinMessageOutput = winMessageEasy[easyWinRandomInt];
    //Random loss message genrator for easy level
    int easyLossRandomInt = random.nextInt(lossMessageEasy.length);
    String easyLossMessageOutput = lossMessageEasy[easyLossRandomInt];

    //Random win message genrator for medium level
    int mediumWinRandomInt = random.nextInt(winMessageMedium.length);
    String mediumWinMessageOutput = winMessageMedium[mediumWinRandomInt];
    //Random loss message genrator for medium level
    int mediumLossRandomInt = random.nextInt(loseMessageMedium.length);
    String mediumLossMessageOutput = winMessageMedium[mediumLossRandomInt];

    //Random win message genrator for hard level
    int hardWinRandomInt = random.nextInt(winMessageHard.length);
    String hardWinMessageOutput = winMessageHard[hardWinRandomInt];
    //Random loss message genrator for hard level
    int hardLossRandomInt = random.nextInt(loseMessageHard.length);
    String hardLossMessageOutput = loseMessageHard[hardLossRandomInt];






    //Switch statement for selecting level on user input
    if(levelInput == 'e' || levelInput == 'm' || levelInput == 'h'){
        switch (levelInput){
            case 'e':
                easy(easyNum1,easyNum2,easyWinMessageOutput,easyLossMessageOutput);
                break;
            case 'm':
                medium(mediumNum1,mediumNum2,mediumWinMessageOutput,mediumLossMessageOutput);
                break;
            case 'h':
                hard(hardNum1,hardNum2,hardWinMessageOutput,hardLossMessageOutput);
                break;
        }

    }else {
        System.out.println("Error! Please enter valid input E or M or H to select level");
    }


}

//Level methods
static int easy(int num1, int num2,String winMsg,String lossMsg){
    System.out.println("Easy");
    MathProblem(num1,num2,winMsg,lossMsg);

    return 0;
}
static int medium(int num1,int num2,String winMsg,String lossMsg){
    System.out.println("Medium");
    MathProblem(num1,num2,winMsg,lossMsg);
    return 0;
}
static int hard(int num1,int num2,String winMsg,String lossMsg){
    System.out.println("Hard");
    MathProblem(num1,num2,winMsg,lossMsg);
    return 0;
}



//Math methods
static int MathProblem (int num1, int num2, String winMessage, String lossMessage){

    int result = 0;
    String randomMathOp = "+-*";
    final int mathOpIndex = randomMathOp.length();
    Random r = new Random();
    Scanner ansScanner = new Scanner(System.in);
    char mathOp = randomMathOp.charAt(r.nextInt(mathOpIndex));

    switch (mathOp){

        case '+':
            result = num1+num2;
            break;
        case '-':
            result = num1-num2;
            break;
        case '*':
            result=num1*num2;
            break;

    }

    System.out.println("What is "+num1+mathOp+num2);
    int answerInput = ansScanner.nextInt();

    if(answerInput == result){
        System.out.println(winMessage);
    }
    else {
        System.out.println(lossMessage);
    }




    return 0;
}

}
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$
  1. Indentation: all of your methods are at the same indentation level of the class Main. This is frowned upon as it does not show that the methods are a part of the class Main.

  2. You are calculating variables like easyNum, mediumNum, easyWinMessageOutput regardless of whether they are going to be used. To fix this, why not create these variables in the methods easy(), medium(), and hard().

  3. use the default case of switch statements to remove this unnecessary if

    if(levelInput == 'e' || levelInput == 'm' || levelInput == 'h'){
        ...
    
    } else {
        System.out.println("Error! Please enter valid input E or M or H to select level");
    }
    

    becomes

    switch (levelInput){
        ...
        default:
            System.out.println("Error! Please enter valid input E or M or H to select level");
            break;
    }
    
  4. The random numbers of the math problem are generated in main, but the operator is generated in MathProblem. It would make more sense to generate them all together, as theses three together make up the problem.

  5. Since this is java, why not model MathProblem as an object that holds the two numbers and the operator. this class could provide a way to check the answer and get a win message and either have easy, medium and hard sub classes, or a factory that creates them. Most importantly, this will separate your user interface (prints and reads) from the logic of your program. This is crucial to writing clean, readable and reusable code.

\$\endgroup\$
3
\$\begingroup\$

Some thoughts:

  • Your idea to use methods is good, but using a class would help to cut down on complexity a lot more. You've got a lot of repetition in setting up the difficulty levels.

  • Likewise, you're doing all the setup for all three difficulty levels even though you're only ever using one. Avoid work you don't need!

  • It's nice to close resources like Scanner. It's easy if you use a try-with-resources block.

  • There's no reason to make multiple scanners.

  • It's counter-intuitive to use capital letters in your difficulty prompt but require lowercase letters in your logic.

  • Keep code that belongs together physically close. You ask for the user's difficulty, then your code goes off on a tangent and only uses the difficulty much farther down.

  • Your main method is too big. There's too much going on there to easily follow.

  • The level methods all do the same thing .. they just print out a different word first. Maybe put that print statement in the switch, then get rid of all three methods and just call MathProblem once from main.

  • MathProblem is not a good java method name. Java names are in camelCase, except for ClassNames.

  • Methods don't need to return something. Declare them void if they don't have anything to return.

  • For Random, it's nice to use the same instance as much as possible. It won't matter here, but in more complex code it's important for testing.

  • Using String#format() would make your question println a little easier to read.

Really, the big win here is moving all of the "difficulty" code into a class. Then you can leverage polymorphism in the rest of the code, which makes it a lot easier to work with. If I were to take a stab at rewriting your code to address the comments above, it might look something like:

public class Main {

    public static void main(final String[] args) {
        System.out.println("***************** Welcome to Game of Math ***********************");
        try (final Scanner inputScanner = new Scanner(System.in)) {
            final Random random = new Random();

            final Difficulty difficulty = askDifficulty(inputScanner, random);
            if (difficulty == null) {
                System.out.println("Error! Please enter valid input E or M or H to select level");
                return;
            }

            System.out.println(difficulty.name());
            askProblem(inputScanner, random, difficulty);
        };
    }

    private static Difficulty askDifficulty(final Scanner inputScanner, final Random random) {
        System.out.println("Enter || E for easy || M for medium and || H for hard");
        switch (inputScanner.next().toLowerCase().charAt(0)){
        case 'e':
            return new Difficulty(
                    "Easy", random, 10,
                    new String[] { "Correct", "Yes you are right", "Good", "Your basics is good", "Keep going" },
                    new String[] { "Bruhh thats wrong", "Nahh", "Wrong", "Boy u need to join primary school" });
        case 'm':
            return new Difficulty(
                    "Medium", random, 100,
                    new String[] { "Cool", "Bravo", "You are cool", "Good", "Oh yea", "oh Boy" },
                    new String[] { "Thats not look right", "No sorry", "Nope", "Sorry! thats inncorect" });
        case 'h':
            return new Difficulty(
                    "Hard", random, 10000,
                    new String[] { "Dammm you are correct", "Oh yea thats right", "Good fella",
                            "Your math is good", "you are a phenomena", "Cool bro", "Fab" },
                    new String[] { "Duhh", "mehhh", "nope", "no", "try again", "sorry! thats wrong" });
        default:
            return null;
        }
    }

    private static void askProblem(final Scanner scanner, final Random random, final Difficulty difficulty) {

        final int firstNumber = difficulty.number();
        final int secondNumber = difficulty.number();

        final String operations = "+-*";
        final char operation = operations.charAt(random.nextInt(operations.length()));

        final int actualAnswer;
        switch (operation) {
        case '+':
            actualAnswer = firstNumber + secondNumber;
            break;
        case '-':
            actualAnswer = firstNumber - secondNumber;
            break;
        case '*':
            actualAnswer = firstNumber * secondNumber;
            break;
        default:
            throw new IllegalStateException();
        }

        System.out.println(String.format("What is %d %c %d?", firstNumber, operation, secondNumber));

        final int userAnswer = scanner.nextInt();
        if (userAnswer == actualAnswer){
            System.out.println(difficulty.winMessage());
        } else {
            System.out.println(difficulty.loseMessage());
        }
    }

}

with the additional class:

class Difficulty {

    private final String name;
    private final Random random;
    private final int bound;

    private final String[] winMessages;
    private final String[] loseMessages;

    public Difficulty(
            final String name,
            final Random random,
            final int maxNumber,
            final String[] winMessages,
            final String[] loseMessages) {
        super();

        this.name = name;
        this.random = random;
        this.bound = maxNumber + 1;
        this.winMessages = Arrays.copyOf(winMessages, winMessages.length);
        this.loseMessages = Arrays.copyOf(loseMessages, loseMessages.length);
    }

    public String name() {
        return this.name;
    }

    public int number() {
        return this.random.nextInt(this.bound);
    }

    public String winMessage() {
        return this.winMessages[this.random.nextInt(this.winMessages.length)];
    }

    public String loseMessage() {
        return this.loseMessages[this.random.nextInt(this.winMessages.length)];
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ thanks, and how can I restart the program with r key in console \$\endgroup\$
    – Kartik
    May 17, 2018 at 18:53
  • \$\begingroup\$ @Kartik by writing code? \$\endgroup\$
    – Eric Stein
    May 17, 2018 at 19:56
  • \$\begingroup\$ okay, so I have to do it myself ig \$\endgroup\$
    – Kartik
    May 17, 2018 at 20:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.