Now that you've seen the basic concepts, it's time to put them to work. In this section we'll create a simple example application: a number guessing game. The object of the game is for the user to guess a randomly generated integer between 1 and 100 (inclusive) in the fewest number of tries. Each time the user makes an incorrect guess, the application will give the user a hint as to whether the guess was greater than or less than the correct number. When the user correctly guesses the number, a "Congratulations!" message will be displayed and the user will be given the option to play again.
Source Code: The number guessing game is provided as part of the standard Echo2 distribution. In the Echo2 archive, the source files for the game may be found in the folder NextApp_Echo2 / SourceCode / src / tutorialapp / numberguess. Of particular interest is the ApplicationInstance, located at NextApp_Echo2 / SourceCode / src / tutorialapp / numberguess / src / java / echo2tutorial / numberguess / NumberGuessApp.java. You will want to have a copy of the source code handy for this lesson.
The user interface code of the Guess-A-Number game is divided into three classes, all of which are found in the NumberGuessApp.java source file. The public class NumberGuessApp
provides the required ApplicationInstance
implementation. The GamePane
and CongratulationsPane
classes are both derived from the Echo ContentPane
component, and represent the number-guessing and end-of-game screens respectively.
State Management: In this example, the NumberGuessApp
also serves to manage the high-level state of the application, i.e., starting new games and displaying the end-of-game congratulations message. Two methods have been created to control this state, startNewGame()
and congratulate()
.
Initialization: The init()
method of the ApplicationInstance
simply creates the main Window
instance and invokes the startNewGame()
method to initialize a new game for the user.
Derived Components: The GamePane
and CongratulationsPane
classes both extend from ContentPane
. Each of these components overrides its constructor to configure itself by creating and adding child Component
s and setting properties upon instantiation. The practice of extending Component
s in this fashion is encouraged.
The GamePane
is a component which handles a single "number guessing session". On construction, a GamePane
generates the secret random number which must be guessed. It then adds a Column
container-component to itself to separate child Component
s vertically. Various Label
s indicating the status of the game, a TextField
into which guessed are entered, and a Button
to submit guesses are then added to the Column
. An additional Button
is added to provide the option to reset and start a new game.
Event Handling: The GamePane
class itself implements the ActionListener
interface. It will register itself as an ActionListener
on both its "Submit Guess" and "Start New Game" buttons. When the user clicks either of them, the actionPerformed()
method will be invoked and provided with an ActionEvent
describing the button click. The implementation will determine which button has been clicked by analyzing the "Action Command" provided by the ActionEvent
, which will correspond to the same value set on the Button
s when they were configured using the setActionCommand()
method.
Handling "Submit Guess" Button Clicks: If the actionPerformed()
method receives an event with the command "submit guess", indicating the "Submit Guess" button was clicked, then the processGuess()
method of the GamePane
is invoked. The processGuess()
method will then investigate the value entered in the guess-entry TextField
.
Processing Guesses: The processGuess()
method will first check if the entered guess is wholly invalid, i.e., if the user accidentally entered something other than a number, and displays an error message if necessary by adjusting the text of the "status label". If the guess is in fact a value between 1 and 100, the next question to be answered is whether or not it is correct. If the user has managed to pick the correct number, the congratulate()
method of the NumberGuessApp
is invoked. Otherwise, the method determines whether the guess was too high or too low and updates the Label
s that display the number of guesses made and the prompt message informing the user to make a guess between a range of sensible values.
Handling "New Game" Button Clicks: If the actionPerformed()
method receives an event with the command "new game", indicating the "Start a New Game" button was clicked, then the startNewGame()
method of NumberGuessApp
will be invoked. The startNewGame()
method would then destroy the current GamePane
and replace it with a new one (causing a new random number to be generated and zeroing out the number of failed attempts).
Obtaining the current ApplicationInstance: In order to either restart the game or display the congratulatory message screen, a method on the ApplicationInstance
must be invoked. There are two ways to obtain a reference to the relevant ApplicationInstance
: First, it can be obtained by invoking the getApplicationInstance()
method on any Component
that is currently "registered" to it, meaning that the Component
is part of a hierarchy that is being currently displayed in the ApplicationInstance
's user interface. The second method is to invoke the static method ApplicationInstance.getActive()
, which will return the ApplicationInstance
relevant to the current thread. In both cases the returned value must be cast to the appropriate derived type, i.e., NumberGuessApp
in this case. In the NumberGuessApp
class, the latter method of retrieving the ApplicationInstance
has been used.
The CongratulationsPane
is an extremely simple ContentPane
which simply displays a "Congratulations!" banner in addition to showing the user how many tries it to took for him/her to successfully guess the secret number. The pane provides a single button which may be used to start a new game. Event handling is accomplished using the identical means introduced in the discussion of the GamePane
.