/home/wpollock1/public_html/restricted/Java1/GuessingGame.java
// GuessingGame.java - A program that allows the user to guess a
// random number from 1 to 10. It uses the class java.util.Random to
// generate the numbers, and uses a swing simple GUI input method
// to read in the user value. The user is told if the guess is too low
// or too high.
//
// Written 9/2014 by Wayne Pollock, Tampa Florida USA.
// Updated 10/2019 by WP to use regular expressions to validate input.
// (Original version used a try-catch block surrounding Integer.parseInt.)
import java.util.Random;
import javax.swing.JOptionPane;
class GuessingGame {
private final static int MAX_RANGE = 10; // Values are in [1..MAX_RANGE]
private final static int MAX_ATTEMPTS = 4;
public static void main ( String [] args ) {
int rc = 0; // Return code from "Do you want to play again?" dialog.
Random randomNumberGenerator = new Random();
// Play the game at least once, then repeat as long as the user wants:
do {
// Generate a random integer in the range 1 through MAX_RANGE:
int numberToGuess = randomNumberGenerator.nextInt( MAX_RANGE ) + 1;
// Play a game. Set message to display in dialog (if they won
// or lost):
String message;
if ( playGame( numberToGuess ) )
message = "You won, Well done!";
else
message = "You lost (number was " + numberToGuess + ").";
message += "\nWould you like to play again?";
// Display won/lost dialog, with question:
rc = JOptionPane.showConfirmDialog( null, message,
"Choose one", JOptionPane.YES_NO_OPTION );
} while ( rc == JOptionPane.YES_OPTION );
}
/** The user must guess numberToGuess in four tries. Note the number
* to guess is passed in from main; this is because main must show
* the number if they don't guess it.
* @param numberToGuess A positive integer in the range 1..MAX_RANGE
* @return true if the user wins, false if they lose
*/
private static boolean playGame ( int numberToGuess ) {
int attempts = 0; // The number of attempts made so far.
String message = "What is your guess (1-" + MAX_RANGE + ")?";
// A for loop doesn't work well here; if the user's input is
// invalid, the number of attempts shouldn't increase. So this
// really is a sentinel type loop: Go until the user get it, or has
// four failed attempts.
while ( attempts < MAX_ATTEMPTS ) {
// Read in user input. This input dialog shows the number of
// guesses left in the title bar. It also includes a cancel button:
String input = JOptionPane.showInputDialog( null, message,
(MAX_ATTEMPTS - attempts) + " Guesses left",
JOptionPane.QUESTION_MESSAGE );
// If the user hits cancel, abort the program:
if ( input == null )
System.exit( 0 );
// Validate user's input as an integer, then convert:
if ( input.matches("\\d+") ) {
int guess = Integer.parseInt( input );
if ( guess < 1 || guess > MAX_RANGE ) {
message = "Guess is out of range!";
} else {
// Set the message to show it the user's guess is high or low:
if ( compareTo(guess, numberToGuess) < 0 )
message = "Too low!";
else if ( compareTo(guess, numberToGuess) > 0 )
message = "Too high!";
else
return true; // They guessed it!
++attempts;
}
} else {
// Set message, and don't count this as an attempt:
message = "Invalid choice! You must enter a number.";
}
message += " What is your guess (1-" + MAX_RANGE + ")?";
}
return false; // They lost!
}
/** Return negative, 0, or positive for guess <, ==, or > numberToGuess:
* Note this doesn't check for guesses outside the range of 1..MAX_RANGE.
* A general compareTo for int or long must account for underflow, so you
* need either two if-statements, or this:
* return (x < y) ? -1
* : ((x == y) ? 0
* : 1);
* @param guess The player's guess.
* @param numberToGuess The correct answer.
* @return <0 if guess is low, >0 if guess is high, or 0 if guess is correct
*/
private static int compareTo ( int guess, int numberToGuess ) {
return guess - numberToGuess;
}
}