-2

Code:

package FisherTCh5Sec4to5;

import java.util.Scanner;

public class FisherTCh5Sec4to5 {

public static int generateRandomInt(int lowerLimit, int upperLimit){
    int range = (upperLimit - lowerLimit) + 1;
    int randomInt = (int) Math.random() * range + lowerLimit;
    return randomInt;
}//end generate random int

public static int collectInteger(String purpose, int minimum, int maximum){
    Scanner in = new Scanner(System.in);
    int userInt = 0;
    boolean done = false;
    do {
        System.out.printf(purpose);
        if (in.hasNextInt()){
            userInt = in.nextInt();

            if (userInt >= minimum && userInt <= maximum){
                done = true;
            } else System.out.printf("That number isn't in the desired range.\n");

        } else System.out.printf("Sorry...I can't use that input.\n");

        //Clear input stream
        in.nextLine();

    } while (!done);
    in.close();
    return userInt;
}// end method


public static void main(String[] args) {

    // Variables 
    final int LOWER_LIMIT = 1;
    final int UPPER_LIMIT = 10;
    boolean done = false;
    String playAgain = "";
    int count = 0;
    int wins = 0;

    // Open input stream
    Scanner in = new Scanner(System.in);

    do {
        // Use collectInteger to get a number
        int userInput = collectInteger("Let's play a game! Try and guess my number (between 1 and 10): ", LOWER_LIMIT, 
                UPPER_LIMIT);

        // use generateRandomInt to get a number
        int randomInt = generateRandomInt(LOWER_LIMIT, UPPER_LIMIT);

        // If statement to decide a win or loss
        if (userInput == randomInt){
            System.out.printf("Congrats you win! My number was %d.\n", randomInt);
            wins++;
        } else System.out.printf("Sorry...my number was %d.\n", randomInt); 


        // Ask user to play again
        System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
        playAgain = in.next();
        if (playAgain.equals("c")){
            done = false;
        } else done = true;

        count ++;

    } while(done = false);  

    // Print and calculate win percentage 
    double winPercent = (wins / count) * 100;
    System.out.printf("Wow! Your win percentage was %.2f%%.\n", winPercent);

    // close input stream
    in.close();


}//end main

}//end class

Everything is working beautifully except for the "Would you like to play again" portion. It won't let me read in the user input I think. Any ideas?

Pang
  • 9,564
  • 146
  • 81
  • 122
fishertrav
  • 11
  • 2

2 Answers2

1

Your first call to in.close() inside collectInteger() also closes your System.in input stream. This is not reopened when you instantiate a new Scanner. Don't believe me? Test it with

System.out.println( System.in.available() ); // Inside try/catch

You have a few options...

  1. ONE instance of Scanner inside main() – pass the scanner as an argument to collectInteger(). Inside collectInteger() you will need to replace in.close() with in.reset(). Close the scanner inside main when you no longer need it (or System.in).
  2. Global variable - private static Scanner in = new Scanner( System.in ); – You will not need to pass it as a parameter but creates tighter coupling. Again - close it only when you no longer need System.in
  3. Keep multiple Scanners but only close the one inside main – Not recommended but the stream will close in jvm shutdown.

I would also surround any IO operations with try/catch/finally...

try
{
    // open resource
    // read/write operation
}
catch( /*specific exception(s)*/ )
{
    // handle exception
}
finally
{
    // close resource
}

Another issue:

boolean done = false; // Currently redundant 

do {
        ...


        // Ask user to play again
        System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
        playAgain = in.next();
        if (playAgain.equals("c")){
            done = false;  // Already initialized to false
        } else done = true;

        count ++;

    } while(done = false);

Could be changed to:

boolean done = false;

do {
        ...


        // Ask user to play again
        System.out.print("Would you like to continue? (\"c\" to continue \"q\" to quit): ");
        playAgain = in.next();
        if (playAgain.equals("q")){  // CHANGE
            done = true;             // CHANGE
        } 

        count ++;

    } while(!done);                  // CHANGE
wfunston
  • 96
  • 1
  • 4
0

The line in.close(); in collectInteger closes the input from System.in. Remove that line and it should work.

Also this line: while(done = false);

Should be changed to:while(done == false); or while(!done);

Reasoning: By using one equal sign, you are setting done to false every time the loop condition is checked. This means the loop never iterates as the condition is always false.

AussieGuy
  • 21
  • 2