-1

So I added the yes or no statement prints out but it doesn't allow the user to type it in. How do I fix that and can I nest a while loop inside a do-while loop?

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

public class HiLo {
    public static void main(String[] args) {
        Random random = new Random();
        Scanner input = new Scanner(System.in);
        final int MAX = 100;
        int answer = random.nextInt(MAX) + 1;
        int guess = -1;
        int numberOfGuesses = 0;
        String cont;

        System.out.println("Guess a number between 1 and " + MAX + ": ");

        do {
            while (guess != answer) {
                numberOfGuesses++;
                guess = input.nextInt();

                if (guess == 101) {
                    break;
                } else if (guess > answer) {
                    System.out.println("Too High");
                    System.out.println("\nGuess again ");
                } else if (guess < answer) {
                    System.out.println("Too Low");
                    System.out.println("\nGuess again: ");
                } else {
                    System.out.println("Correct! The number was " + answer + ".");
                    System.out.println("It took you " + numberOfGuesses + " guesses.");
                }
            }

            System.out.println("\nWould you like to play again (yes/no)?");
            cont = input.nextLine();
        } while (cont.equals("yes");

        input.close();
    }
}
Mr. Polywhirl
  • 31,606
  • 11
  • 65
  • 114
  • Does this answer your question? [Scanner is skipping nextLine() after using next() or nextFoo()?](https://stackoverflow.com/questions/13102045/scanner-is-skipping-nextline-after-using-next-or-nextfoo) – matt Apr 07 '20 at 17:48
  • `Scanner`s have a lot of little caveats. You do nextInt and it leaves a newline character in the buffer. You do nextLine, and it returns immediately with the remaining input (probably a blank line). – matt Apr 07 '20 at 17:48

3 Answers3

0

Well, as I look to your looping logic it could be maintained and working as charm, you just need to move the initialization steps from the outside, to the inside do-while loop, in the beginning.

That way, at each start of the game, everything will work.

Also you're forgetting to go to next line before reading the user choice of yes/no, as you were reading just ints, at the end your a line ahead of the line containing the verdict yes/no

I tried this code in an online compiler, and it's working :

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

public class Main{

     public static void main(String []args){

        Random random = new Random();
        Scanner input = new Scanner(System.in);
        final int MAX = 100;

        System.out.println("Guess a number between 1 and " + MAX + ": ");
        String cont = new String();
        do {
            System.out.println("Let's play");
            //Initializations here
            int answer = random.nextInt(MAX) + 1;
            int guess = -1;
            int numberOfGuesses = 0;


            while (guess != answer) {
                numberOfGuesses++;
                guess = input.nextInt();

                if (guess == 101) {
                    break;
                } else if (guess > answer) {
                    System.out.println("Too High");
                    System.out.println("\nGuess again ");
                } else if (guess < answer) {
                    System.out.println("Too Low");
                    System.out.println("\nGuess again: ");
                } else {
                    System.out.println("Correct! The number was " + answer + ".");
                    System.out.println("It took you " + numberOfGuesses + " guesses.");
                }
            }

            System.out.println("\nWould you like to play again (yes/no)?");
            input.nextLine();//You have to go to the next line...
            cont = input.nextLine();
        } while (cont.equals("yes"));
        System.out.println("\nThanks for playing !");
        input.close();
     }
}
  • Glad that I helped you sir. Just mark it as correct answer if you see that it is. Thanks. – Il Saggio Vecchino Apr 07 '20 at 17:54
  • Actually I tried it, and it fixes one of the problems I had which is great (allows the user to type a yes or no). But it doesn't loop back and restart the program, can you help me fix that? – Ashwattha Shinde Apr 07 '20 at 18:03
  • I tried it in different online interpreters and it's working, I just added a message telling you to play again when you type `yes` to prove that it's iterating again. – Il Saggio Vecchino Apr 07 '20 at 18:12
  • So basically if the user quits the program or guesses the number correctly, the program will prompt the user if they want to play again with a yes or no question. Then it takes in the response and if the response is yes, the game should start again. The problem is that even if I type yes, it keeps asking me whether I want to play again. – Ashwattha Shinde Apr 07 '20 at 18:13
  • I think that you're using other code than mine sir ! Be sure to use the one I provided. – Il Saggio Vecchino Apr 07 '20 at 18:14
  • @AshwatthaShinde I have this working, see the last statement of the `play` method in [my response](https://stackoverflow.com/a/61086488/1762224). – Mr. Polywhirl Apr 07 '20 at 18:22
  • Ok, ill try it again. I might have typed something wrong. – Ashwattha Shinde Apr 07 '20 at 18:30
  • @IlSaggioVecchino Yeah it's working. My bad, I might have done something wrong. Thanks for your help man, I appreciate it! – Ashwattha Shinde Apr 07 '20 at 18:34
  • You're welcome sir ! Just don't forget the "correct answer" – Il Saggio Vecchino Apr 07 '20 at 18:36
0

I would organize this into a class with methods first. This breaks down each piece of logic and makes it easier to read.

  1. Start a "play" loop
  2. Inside the "play" loop, have a "guess" loop
  3. Store the "continue" state in a known constant
  4. Only check if they are correct after they made the max number of guesses.
  5. Seed the Random object with the current system time

Also, I added a DEBUG flag to display the answer.

Update: The program is ignoring or not even asking for your "yes" input, because you were previously asking it for integers. You will need to clear/flush/reset the scanner's buffer by calling nextLine. Switching from integer to string leaves some data in the buffer. So your program will use the left-over character data in the buffer before it prompts you for your input.

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

public class HiLo implements Runnable {
    private static boolean DEBUG = true; // Disable to not show the answer...
    private static final int MAX_NUMBER = 100;
    private static final int MAX_GUESSES = 5;
    private static final String YES = "YES";

    private final Random rand;

    public HiLo() {
        this.rand = new Random(System.currentTimeMillis());
    }

    public static void main(String[] args) {
        new Thread(new HiLo()).start();
    }

    @Override
    public void run() {
        Scanner scan = new Scanner(System.in);
        String cont = "";
        do {
            play(scan);
            System.out.print("\nWould you like to play again (yes/no)? ");
            cont = scan.nextLine();
            System.out.println();
        } while (cont.equalsIgnoreCase(YES));
        scan.close();
    }

    public void play(Scanner scan) {
        boolean correct = false;
        int numberOfGuesses = 0;
        int answer = rand.nextInt(MAX_NUMBER) + 1;

        if (DEBUG) System.out.printf("The answer is: %d%n", answer);

        System.out.printf("Guess a number between 1 and %d%n", MAX_NUMBER);

        while (numberOfGuesses < MAX_GUESSES && !correct) {
            numberOfGuesses++;
            correct = makeGuess(scan, answer, numberOfGuesses);
        }

        if (numberOfGuesses <= MAX_GUESSES && correct) {
            System.out.printf("Correct! The number was %d. It took you %d guesses.%n", answer, numberOfGuesses);
        } else {
            System.out.printf("Sorry, but you did not guess: %d", answer);
        }
        scan.nextLine(); // Reset...
    }

    public boolean makeGuess(Scanner scan, int answer, int currentGuesses) {
        System.out.print("Guess: ");
        int guess = scan.nextInt();

        if (guess == answer) {
            return true;
        }

        if (currentGuesses < MAX_GUESSES) {
            if (guess > answer) {
                System.out.print("Too High, ");
            } else {
                System.out.print("Too Low, ");
            }
        }

        return false;
    }
}

Sample Output

The answer is: 64
Guess a number between 1 and 100
Guess: 50
Too Low, Guess: 75
Too High, Guess: 60
Too Low, Guess: 65
Too High, Guess: 64
Correct! The number was 64. It took you 5 guesses.

Would you like to play again (yes/no)? yes

The answer is: 88
Guess a number between 1 and 100
Guess: 50
Too Low, Guess: 90
Too High, Guess: 80
Too Low, Guess: 85
Too Low, Guess: 87
Sorry, but you did not guess: 88

Would you like to play again (yes/no)? no
Mr. Polywhirl
  • 31,606
  • 11
  • 65
  • 114
  • Thank you! Quick question what does the @override do? – Ashwattha Shinde Apr 07 '20 at 18:35
  • @AshwatthaShinde The `@Override` annotation just lets the compiler or anyone viewing the code know that the method is being implemented or overridden from its interface or parent class. For more info see: [Predefined Annotation Types](https://docs.oracle.com/javase/tutorial/java/annotations/predefined.html) I chose to implement the `Runnable` class (which has a `run` method), but you do not really need to do this. It just makes the class look better in terms of flow. – Mr. Polywhirl Apr 07 '20 at 18:42
  • You could get rid of the `Runnable` interface, remove the `Override` annotation, and replace the main body with `new HiLo().run()` and it would still work. All I really did was just start the program on a new thread. – Mr. Polywhirl Apr 07 '20 at 18:46
0

Use Scanner:nextLine instead of Scanner:nextInt. Check Scanner is skipping nextLine() after using next() or nextFoo()? to learn more about it.

Do it as follows:

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

public class HiLo {
    public static void main(String[] args) {
        Random random = new Random();
        Scanner input = new Scanner(System.in);
        final int MAX = 100;
        int answer = random.nextInt(MAX) + 1;
        int guess = -1;
        int numberOfGuesses = 0;
        String cont = "yes", inputStr = "";
        do {
            System.out.print("Guess a number between 1 and " + MAX + ": ");
            inputStr = input.nextLine();
            if (inputStr.matches("\\d+")) {// Allow only digits
                guess = Integer.parseInt(inputStr);
                if (guess < 1 || guess > 100) {
                    break;
                }
                if (guess != answer) {
                    numberOfGuesses++;
                }
                if (guess > answer) {
                    System.out.println("Too High! Guess again ");
                } else if (guess < answer) {
                    System.out.println("Too Low! Guess again.");
                } else {
                    System.out.println("Correct! The number was " + answer + ".");
                    System.out.println("It took you " + numberOfGuesses + " guesses.");
                }
                System.out.print("Would you like to play again (yes/no)?");
                cont = input.nextLine();
            } else {
                System.out.println("This is an invalid entry. Please try again.");
            }
        } while (cont.equalsIgnoreCase("yes"));
        System.out.println("Goodbye!");
    }
}

A sample run:

Guess a number between 1 and 100: 10
Too Low! Guess again.
Would you like to play again (yes/no)?yes
Guess a number between 1 and 100: 30
Correct! The number was 30.
It took you 1 guesses.
Would you like to play again (yes/no)?no
Goodbye!

Some other notes:

  1. Use String::equalsIgnoreCase instead of String::equals to match strings in all cases.
  2. The regex, \\d+ is used to restrict a string to have only digits which can be then converted into int using Integer::parseInt.
Arvind Kumar Avinash
  • 50,121
  • 5
  • 26
  • 72