Source Code

The following is the source code of the NumberGuessApp.java file, which contains the application and component code used to create the Guess-A-Number application. This source code is also available in the Echo3 download in the directory: NextApp_Echo3 / SourceCode / src / server-java-examples / numberguess.

package numberguess;

import nextapp.echo.app.ApplicationInstance;
import nextapp.echo.app.Button;
import nextapp.echo.app.Color;
import nextapp.echo.app.ContentPane;
import nextapp.echo.app.Extent;
import nextapp.echo.app.Insets;
import nextapp.echo.app.Label;
import nextapp.echo.app.ResourceImageReference;
import nextapp.echo.app.Column;
import nextapp.echo.app.TextField;
import nextapp.echo.app.Window;
import nextapp.echo.app.event.ActionEvent;
import nextapp.echo.app.event.ActionListener;
import nextapp.echo.app.layout.ColumnLayoutData;

/**
 * Guess-a-number Tutorial Application.
 */
public class NumberGuessApp extends ApplicationInstance {

    private Window window;
    
    /**
     * Displays a congratulatory message to the user when s/he has guessed
     * the correct number.
     * 
     * @param numberOfTries the number of tries it took the user to guess the
     *        correct answer.
     */
    void congratulate(int numberOfTries) {
        window.setContent(new CongratulationsPane(numberOfTries));
    }
    
    /**
     * @see nextapp.echo.app.ApplicationInstance#init()
     */
    public Window init() {
        window = new Window();
        window.setTitle("Echo Guess-A-Number");
        startNewGame();
        return window;
    }

    /**
     * Starts a new game:
     * Sets content of Window to a new GamePane.
     */
    void startNewGame() {
        // Set the content to be a new GamePane, so the 
        window.setContent(new GamePane());
    }
}

/**
 * A ContentPane which generates a random number and provides the
 * user opportunities to guess it.
 */
class GamePane extends ContentPane 
implements ActionListener {

    /** Randomly generated number between 1 and 100 inclusive. */
    private int randomNumber = ((int) Math.floor(Math.random() * 100)) + 1;
    
    /** The current lowest sensible guess, based on previous guesses. */
    private int lowerBound = 1;

    /** The current highest sensible guess, based on previous guesses. */
    private int upperBound = 100;
    
    /** The number of guesses made in the current game. */
    private int numberOfTries = 0;
    
    /** TextField into which guesses are entered. */
    private TextField guessEntryField;
    
    /** 
     * Label displaying the current "status".  Initially blank, 
     * this label will inform the user whether his/her last guess was too 
     * high, too low, or simply invalid.
     */ 
    private Label statusLabel = new Label();
    
    /**
     * Label indicating the total number of guesses made so far.
     */
    private Label countLabel = new Label("You have made no guesses.");
    
    /**
     * Label prompting the user to enter a new guess.  The text of
     * this label will change as the user makes guesses to reflect the updated
     * "sensible" range of possible guesses.
     */
    private Label promptLabel = new Label(
            "Guess a number between 1 and 100: ");
    
    /**
     * Creates a new GamePane.
     */
    GamePane() {
        super();
        
        Column layoutColumn = new Column();
        layoutColumn.setInsets(new Insets(30));
        layoutColumn.setCellSpacing(new Extent(10));
        add(layoutColumn);
        
        layoutColumn.add(new Label(
                new ResourceImageReference("/numberguess/TitleBanner.png")));
        layoutColumn.add(statusLabel);
        layoutColumn.add(countLabel);
        layoutColumn.add(promptLabel);
        
        guessEntryField = new TextField();
        guessEntryField.setForeground(Color.WHITE);
        guessEntryField.setBackground(Color.BLUE);
        ColumnLayoutData columnLayoutData = new ColumnLayoutData();
        columnLayoutData.setInsets(new Insets(20, 0));
        guessEntryField.setLayoutData(columnLayoutData);
        guessEntryField.setActionCommand("submit guess");
        guessEntryField.addActionListener(this);
        layoutColumn.add(guessEntryField);
        
        Button submitButton = new Button("Submit Your Guess");
        submitButton.setActionCommand("submit guess");
        submitButton.setForeground(Color.BLACK);
        submitButton.setBackground(Color.GREEN);
        submitButton.setWidth(new Extent(200));
        submitButton.addActionListener(this);
        layoutColumn.add(submitButton);
        
        Button newGameButton  = new Button("Start a New Game");
        newGameButton.setActionCommand("new game");
        newGameButton.setForeground(Color.WHITE);
        newGameButton.setBackground(Color.RED);
        newGameButton.setWidth(new Extent(200));
        newGameButton.addActionListener(this);
        layoutColumn.add(newGameButton);
    }
    
    /**
     * @see nextapp.echo.app.event.ActionListener#actionPerformed(
     *      nextapp.echo.app.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("new game")) {
            ((NumberGuessApp) ApplicationInstance.getActive()).startNewGame();
        } else if (e.getActionCommand().equals("submit guess")) {
            processGuess();
        }
    }
    
    /**
     * Processes a user's guess.
     */
    private void processGuess() {
        
        int guess;
        try {
            guess = Integer.parseInt(guessEntryField.getDocument().getText());
        } catch (NumberFormatException ex) {
            statusLabel.setText("Your guess was not valid.");
            return;
        }

        ++numberOfTries;

        if (guess == randomNumber) {
            ((NumberGuessApp) ApplicationInstance.getActive())
                    .congratulate(numberOfTries);
            return;
        }
        
        if (guess < 1 || guess > 100) {
            statusLabel.setText("Your guess, " + guess 
                    + " was not between 1 and 100.");
        } else if (guess < randomNumber) {
            if (guess >= lowerBound) {
                lowerBound = guess + 1;
            }
            statusLabel.setText("Your guess, " + guess 
                    + " was too low.  Try again:");
        } else if (guess > randomNumber) {
            statusLabel.setText("Your guess, " + guess 
                    + " was too high.  Try again:");
            if (guess <= upperBound) {
                upperBound = guess - 1;
            }
        }

        // Update number of tries label.
        if (numberOfTries == 1) {
            countLabel.setText("You have made 1 guess.");
        } else {
            countLabel.setText("You have made " + numberOfTries + " guesses.");
        }
        
        // Update prompt label to reflect the new sensible range of numbers.
        promptLabel.setText("Guess a number between " + lowerBound + " and " 
                + upperBound + ": ");
    }
}

/**
 * A ContentPane which presents a congratulatory message to the
 * player when the correct number has been guessed.
 */
class CongratulationsPane extends ContentPane
implements ActionListener {

    /**
     * Creates a new CongratulationsPane.
     * 
     * @param numberOfTries the number of tries it took the user to guess the
     *        correct answer.
     */
    CongratulationsPane(int numberOfTries) {
        Column layoutColumn = new Column();
        layoutColumn.setInsets(new Insets(30));
        layoutColumn.setCellSpacing(new Extent(30));
        add(layoutColumn);
        
        layoutColumn.add(new Label(new ResourceImageReference(
                "/numberguess/CongratulationsBanner.png")));
        layoutColumn.add(new Label("You got the correct answer in " 
                + numberOfTries + (numberOfTries == 1 ? " try." : " tries.")));

        Button button = new Button("Play Again");
        button.setForeground(Color.WHITE);
        button.setBackground(Color.RED);
        button.setWidth(new Extent(200));
        button.addActionListener(this);
        layoutColumn.add(button);
    }

    /**
     * @see nextapp.echo.app.event.ActionListener
     *      #actionPerformed(nextapp.echo.app.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        ((NumberGuessApp) ApplicationInstance.getActive()).startNewGame();
    }
}