7
\$\begingroup\$

I'm working on code for an assignment and I was hoping you all could point me in the right direction.

Basically I had to write a program that will issue out a multiple choice test. I have 4 options, A, B, C, D and if the user accidentally chooses something other than my options I want it to ask the question over again.

I've messed around with loops and counters but I'm really hitting a standstill right here. I seem to be unable to get this to work so I'd like you to review my code as is. The code at it's current state here is working, although it does not do much.

I'm up for whatever critique, so if you see something a beginning Java student should do, please let me know.

public static void main(String[] args) {
    String[] multiChoice1;
    Scanner input = new Scanner(System.in);

    multiChoice1 = new String[5];
    multiChoice1[0] = "1. Which country currently emits the most greenhouse gases?\n";
    multiChoice1[1] = "blah blah";
    multiChoice1[2] = "blah blah";
    multiChoice1[3] = "blah blah";
    multiChoice1[4] = "blah blah";

    String userSelect1 = multiChoice1[0];

    if(userSelect1==multiChoice1[0]){
        System.out.println(multiChoice1[0]);
        System.out.println("A. United States");
        System.out.println("B. China");
        System.out.println("C. India");
        System.out.println("D. England");
        System.out.println();
        System.out.print("Your answer: ");
        String uSelect1 = input.next();

        switch (uSelect1.toUpperCase()){
            case "A":
                uSelect1 = "United States";
                System.out.println("Incorrect!\n\n");
                break;
            case "B":
                uSelect1 = "China";
                System.out.println("Correct!\n\n");
                scorePro++;
                score++;
                break;
            case "C":
                uSelect1 = "India";
                System.out.println("Incorrect!\n\n");
                break;
            case "D":
                uSelect1 = "England";
                System.out.println("Incorrect!\n\n");
                break;
            default: 
                uSelect1 = "Incorrect, choice.\n\n";
                break;
        }
    }
    // more multiple choice questions with similar structure
}
\$\endgroup\$
  • \$\begingroup\$ if you move your switch block into another method, maybe it will be easier for you to see the whole picture \$\endgroup\$ – Leo Oct 2 '14 at 1:22
  • \$\begingroup\$ And what exactly do you mean by "error check"ing your switch statement? Making sure it works correctly? \$\endgroup\$ – raptortech97 Oct 2 '14 at 1:37
  • \$\begingroup\$ I need to verify the user does not select something other then my options, and if they do select something else, I need to reissue the question. I'm just not sure what I should do. I've toyed with loops, but they are still a little beyond me. \$\endgroup\$ – momofierce Oct 2 '14 at 1:39
  • \$\begingroup\$ I'd suggest not to close this. It's far from perfect, but it's a bad fit for SO. All it's about is better coding (not style, but basics), writing proper methods, which can be reused somehow. So it stands, it does close to nothing, but it's not exactly broken. \$\endgroup\$ – maaartinus Oct 2 '14 at 2:00
  • \$\begingroup\$ "I want it to ask the question over again" therefore this question is not about working code. \$\endgroup\$ – Chris Martin Oct 2 '14 at 6:47
7
\$\begingroup\$

As you might have noted, methods which do printing are of no use in a bigger piece of code. While your lengthy method tries to say something to the user, it fails to communicate the outcome to the caller.

You could add some return value to the printing... but that's like adding insult to injury. Try to write methods computing something, call them, and react by some printing.

Try to start at the top level like

while (true) {
    printQuestion();
    char c = readInput();
    if (!isLegalInput(c)) continue; // i.e., jump to the loop start to ask again
    if (isCorrectAnswer(c)) {
        print("Correct!\n\n");
    } else {
        print("Inorrect!\n\n");
    }
}

Now, there's a s*load of methods to write... but all of them are pretty trivial. You may also find out that they need more arguments or whatever... there are many ways to go. Just don't print in methods which may need to be reused. Every method should do a single thing.

\$\endgroup\$
2
\$\begingroup\$

You never use uSelect1. Get rid of it. You don't care which incorrect answer the user chooses, so let's consolidate. If you went with a select statement, it would look like this:

switch(uSelect1.toUpperCase()) {
    case "B":
        score++;
        System.out.println("Correct!");
        break;
    case "A":
    case "C":
    case "D":
        System.out.println("Incorrect.");
        break;
    default:
        System.out.println("Unrecognized input");
}

Note that default is the default case, when the string is not otherwise matched. The chained A-C-D thing is something called switch statement fall through, but you don't need to worry about that. Also more that println is very nice because it adds that "\n" at the end for us.

A switch statement, however, is not the way to do this. The best way to do this would be to have a string variable correctSelection set to "B" so we can say

char selection = uSelect1.toUpperCase().charAt(0);
if (selection == 'B') {
    score++;
    System.out.println("Correct!");
} else if ('A' <= selection && selection <= 'D') {
    System.out.println("Incorrect");
} else {
    System.out.println("Bad Input");
}

Once you feel more comfortable with loops and arrays, this can be done a little more easily.

Also, your variable names are a little odd. What's with this u and 1 stuff? The user selected a letter, so call it a selectedLetter (I only used selection in the above code because I'm typing this on mobile.)

Good luck!

\$\endgroup\$
  • \$\begingroup\$ Ahh thank you. I've been looking over my stuff and trying to consolidate and the uSelect statement in each case didn't seem to have a purpose either. To be quite frank I was going off an example in class but I failed to realize that was set up like that because it actually set that input to something. Thank you for your help! \$\endgroup\$ – momofierce Oct 2 '14 at 2:16
2
\$\begingroup\$

It is possible to remove switch or if/else blocks. The resulting code is shown below:

static final int QUESTION = 0;
static final int ANSWER = 1;
static final int START_OF_CHOICES = 2;

//init questions, answers, and choices
static String[][] multiChoice = new String[][]{
    {"1. Which country currently emits the most greenhouse gases?", "B", "A. United States", "B. China", "C. India", "D. England"},
    {"2. Question 2?", "C", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"},
    {"3. Question 3?", "A", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"},
    {"4. Question 2?", "D", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"}};

public static void main(String[] args) {
    Scanner input = new Scanner(System.in);

    //loop through each question
    for (int questionIndex = 0; questionIndex < multiChoice.length; questionIndex++) {
        //print current question as well as its choices
        printQuestion(questionIndex);
        do {
            //display instruction for input. It's good to put hint like A  - D so that the user will now what to enter
            System.out.print("\nYour Answer [A - D]: ");

        } while (!isCorrectAnswer(questionIndex, input.next().charAt(0)));  //continue asking for answer if the user entered an incorrect one
    }
}

//method that checks whether the user's answer is correct for a particular question
static boolean isCorrectAnswer(int questionNum, char userAnswer) {
    //true if matched, false otherwise
    boolean rightAnswer = (userAnswer + "").equalsIgnoreCase(multiChoice[questionNum][ANSWER]);
    //equivalent to if rightAnswer is true then display "Correct", else, display "Incorrect"
    System.out.println(rightAnswer ? "Correct!\n" : "Incorrect!\n");

    return rightAnswer;
}

//method that prints a specific question and its choices
static void printQuestion(int questionNum) {
    System.out.println(multiChoice[questionNum][QUESTION]);
    int lastColumn = multiChoice[questionNum].length;
    for (int x = START_OF_CHOICES; x < lastColumn; x++) {
        System.out.println("\t" + multiChoice[questionNum][x]);
    }
}

Code Explanation:

First, use a two-dimensional array. Each row holds details about the question, answer, and choices. The number of rows is equal to the number of questions. Dedicate column 0 for question, column 1 for answer, and columns 2 - 5 for choices. A sample array content is shown below:

String[][] multiChoice = new String[][]{
    {"1. Which country currently emits the most greenhouse gases?", "B", "A. United States", "B. China", "C. India", "D. England"},
    {"2. Question 2?", "C", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"},
    {"3. Question 3?", "A", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"},
    {"4. Question 2?", "D", "A. Option 1", "B. Option 2", "C. Option 3", "D. Option 4"}};

For instance, in row 0, the question is "1. Which country currently emits the most greenhouse gases?"; the answer is "B"; and the choices are "A. United States", etc.

Since you have fix index dedicated to hold a particular value (column 0 is always question), it is a good practice to declare it as a constant inorder to make your code more readable and reliable (less error in encoding).

final int QUESTION = 0; //question is always at column 0
final int ANSWER = 1; //answer is always at column 1
final int START_OF_CHOICES = 2; //start of choices is always at index 2

Second, breakdown your main process into sub-processes. For each sub-process, handle them independently. In case that there are required fixes to be done in your code, you only modify the sub-process(es) responsible for them.

Sub-processes:

  • print question and display its choices
  • check answer and display appropriate message based on the answer

Then, you plug these processes into your main program flow:

  1. Initialize items (questions, answers, and choices).
  2. For each item

    a. print question and display its choices

    b. ask user's answer

    c. Check user's answer. While it is incorrect, go back to b.

\$\endgroup\$
0
\$\begingroup\$

I think you should do this task by using recursion, where you will have to create a method to test the conditions by putting the switch inside the method, if the input is other than the provided options the default section will be executed and it will call the the method again and again until the user input the correct option from the provided list. following code will help you :)

public class SwithcTest {
    static String multiChoice1[] = {"B"};
    static int scorePro;
    static int score;
    public static void main(String[] args) {
        test();
    }

    public static void test(){
        Scanner input = new Scanner(System.in);
        String userSelect1 =  multiChoice1[0];

    if(userSelect1.equals(multiChoice1[0])){
        System.out.println(multiChoice1[0]);
        System.out.println("A. United States");
        System.out.println("B. China");
        System.out.println("C. India");
        System.out.println("D. England");
        System.out.println();
        System.out.print("Your answer: ");
        String uSelect1 = input.next();

        switch (uSelect1.toUpperCase()){
            case "A":
                uSelect1 = "United States";
                System.out.println("Incorrect!\n\n");
                break;
            case "B":
                uSelect1 = "China";
                System.out.println("Correct!\n\n");
                scorePro++;
                score++;
                break;
            case "C":
                uSelect1 = "India";
                System.out.println("Incorrect!\n\n");
                break;
            case "D":
                uSelect1 = "England";
                System.out.println("Incorrect!\n\n");
                break;
            default: 
                uSelect1 = "Incorrect, choice.\n\n";
                System.out.println("Please select an option from the provided options!!!");
                test();
        }

    }

    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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