0

I'm new here, and to code in general. What I'm trying to accomplish is to create a simple guessing game that prompts a user for a number, and checks that number against a computer generated number between 1 and 100. I've tried to make it so the player can continue guessing until they get the correct answer, as well as display a counter to let the player know how many guessing attempts they have made. The problem is, the program won't terminate after the correct answer has been given, and I can't figure out what I'm doing wrong. I'll paste the entire code at the bottom for reference, but I feel like the problem lies within the following statement in the "determineAnswer" method:

} else if (userAnswer == computerNumber) {
        message = "Correct"
                + "\nNumber of Guesses: " + count;
        success++;

I'm trying to use the value of the integer "success" as the condition to terminate the do/while loop, but even though I try to increment the value, the loop continues as if the value is being continuously reset. If that's the case, I can't see where I've gone wrong. Again, I'm quite new at this but I would appreciate any input.

import javax.swing.JOptionPane;

public class GuessingGame {

    public static void main(String[] args) {
        // generate a random number from 1 to 100
        int computerNumber = (int) (Math.random() * 100 + 1);
        // declare other variables
        int success = 0;
        int count = 0;
        // display the correct guess for testing purposes
        System.out.println("The correct guess would be " + computerNumber);
        // prompt user for a guess
        do {           
            count++;
            String response = JOptionPane.showInputDialog(null,
                    "Enter a guess between 1 and 100");
            int userAnswer = Integer.parseInt(response);
            // display result
            JOptionPane.showMessageDialog(null, determineGuess(userAnswer, computerNumber, success, count));
        } while (success == 0);

    }

    public static String determineGuess(int userAnswer, int computerNumber,int success, int count) {
        String message = null;        
        if (userAnswer <= 0 || userAnswer > 100) {
            message = "Invalid guess"
                    + "\nNumber of Guesses: " + count;
        } else if (userAnswer == computerNumber) {
            message = "Correct"
                    + "\nNumber of Guesses: " + count;
            success++;
        } else if (userAnswer > computerNumber) {
            message = "Incorrect, Too High"
                    + "\nNumber of Guesses: " + count;
        } else if (userAnswer < computerNumber) {
            message = "Incorrect, Too Low"
                    + "\nNumber of Guesses: " + count;
        }
        return message;
    }
}
khelwood
  • 55,782
  • 14
  • 81
  • 108
  • 3
    do { .. } while (success == 0); nowhere in your do block do you update the value of success. What did you expect to happen? – Stultuske Nov 26 '18 at 08:59
  • 1
    Why is `success` an integer? Can you plot success on a number line? It should be a boolean field, and the convention is to name them so that they read like english `while (!isSuccessful)` – Michael Nov 26 '18 at 09:01
  • 1
    `main` and `determineGuess` each have a `success` variable. They're different variables. Altering the one in `determineGuess` doesn't alter the one in `main`. – khelwood Nov 26 '18 at 09:03
  • 2
    Anyway! Fundamentally, it looks like you don't understand that Java is [pass-by-value](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value). When you pass `success` to `determineGuess`, you create a copy of that integer into a new variable. The main method does not have visibility of any updates to the copy. Therefore `success` is not updated as you are expecting – Michael Nov 26 '18 at 09:04
  • @Michael Thank you, I'm looking more into pass-by-value and its a lot clearer for me now. Appreciate the help – Joshua Revels Nov 26 '18 at 09:58

3 Answers3

2

You do not update the value of success and every time the loop runs, it will be getting success value as 0 and thus it is causing infinite loop.

int success = 0;
    int count = 0;
    // display the correct guess for testing purposes
    System.out.println("The correct guess would be " + computerNumber);
    // prompt user for a guess
    do {           
        count++;
        String response = JOptionPane.showInputDialog(null,
                "Enter a guess between 1 and 100");
        int userAnswer = Integer.parseInt(response);
        // display result
        JOptionPane.showMessageDialog(null, determineGuess(userAnswer, computerNumber, success, count));
success=1;
    } while (success == 0);
Pooja Aggarwal
  • 1,163
  • 6
  • 14
1

In Java everything is pass by value.

In this case have passed primitive (int) to method and then changing its value and expecting same to reflect in calling method. Java doesn't work like that

public class SuccessTest {
public static void main(String[] args) {
    int success = 0;
    updateSuccess(success);
    System.out.println(success); //will print 0
}

private static void updateSuccess(int success) {
    //changing value of success here will not reflect in main method 
    success=2;
    System.out.println(success);//will print 2
}
}

In order to make this work declare success as class level variable

private static int success = 0;

then no need to pass this success to determineGuess method, now if you update value of success in determineGuess method it will be available in main method

Vipul
  • 816
  • 4
  • 11
  • 26
0

The reason that the success variable is not being updated in the main method is that it does not have access to any changes to the determineGuess method's success variable. They are two separate variables in separate scopes.

determineGuess receives success as an int method parameter. In Java, types such as int, char and float are pass-by-value: this means that the value is essentially copied when it is given to a method or set as a variable, so that if you modify the copied value, the original one is not modified. (actually, all types are pass-by-value, but the contents of an object is by reference).

There are a few ways of updating the success variable for the main method, two of which are:

  1. Make success a field in the class, that way it is accessible by all methods in the class. Because you are doing all of this in main, for now you will need success to be static: private static int success = 0;. A better way can be to make everything non-static, and have main instantiate a GuessingGame object and then call a run method on it.
  2. Return a value from determineGuess that will let you know what category the answer fits into: success, incorrect, too high or too low. You would then have a second method that uses this output to select the message to display. If main sees that the output is success, it updates its success variable. This might be better, but is more involved.

For this simple example, I suggest option 1. In fact, because you only check for one success, the success variable can just be a boolean value. This would make your code the following (with modifications):

import javax.swing.JOptionPane;

public class GuessingGame {
    // Determines whether the user has successfully guessed the number
    private static boolean success = false;

    public static void main(String[] args) {
        // Generate a random integer between 1 and 100 inclusive
        int computerNumber = (int) (Math.random() * 100 + 1);
        // Count the number of guesses that the user makes, to report it to them
        int count = 0;
        // FIXME: only for testing purposes, remove this
        System.out.println("The correct guess would be " + computerNumber);
        do {           
            count++;
            String response = JOptionPane.showInputDialog(null, "Enter a guess between 1 and 100");
            int userAnswer = Integer.parseInt(response);
            JOptionPane.showMessageDialog(null, determineGuess(userAnswer, computerNumber, count));
        } while (!success);
    }

    public static String determineGuess(int userAnswer, int computerNumber, int count) {        
        if (userAnswer <= 0 || userAnswer > 100) {
            return "Invalid guess\nNumber of Guesses: " + count;
        } else if (userAnswer == computerNumber) {
            success = true;
            return "Correct\nNumber of Guesses: " + count;
        } else if (userAnswer > computerNumber) {
            return "Incorrect, Too High\nNumber of Guesses: " + count;
        } else if (userAnswer < computerNumber) {
            return "Incorrect, Too Low\nNumber of Guesses: " + count;
        }
        return null;
    }
}

If you were to go with option 2, then you might have an enum GuessOutcome { INCORRECT, SUCCESS, TOO_LOW, TOO_HIGH } that you return from determineGuess. You would then have a getOutcomeMessage(GuessOutcome outcome) method with a switch (outcome) { ... } to select which message to display. If outcome == GuessOutcome.SUCCESS, then success = true. In this version, success can be a local variable to main.

Billy Brown
  • 2,272
  • 23
  • 25