BACK TO THE GUESS A NUMBER GAME


Let's get started on the development of this chapter's game project, the Guess a Number game. To create this game, you follow the same five development steps that you've used to create previous chapter projects.

Designing the Game

The Guess a Number game is played on a single window. This game collects the player's input by adding radio buttons and a check box to the user interface. In addition, instead of displaying output using MessageBox::Show, the game displays information messages for the player to read in a TextBox control located on the user interface.

The advantage of collecting player input and displaying game output on the user interface is that it makes the game run more smoothly. The player doesn't have to constantly stop and respond to pop-up windows as the game runs. To create the user interface, you have to learn how to work with several new types of controls, including the GroupBox, RadioButton, and CheckBox controls.

The Guess a Number game is made up of one form and the 17 controls listed in Table 6.2.

Table 6.2: Form Controls for the Guess a Number Game

Control Type

Control Name

Description

GroupBox1

grpRange

Contains radio buttons, a check box, and a button, which control the game's configuration settings

GroupBox2

grpScore

Displays the number of games won by the player and contains a button that resets the score

RadioButton 1

rbnControl10

Sets the range of game numbers to 1 through 10

RadioButton2

rbnControl100

Sets the range of game numbers to 1 through 100

RadioButton3

rbnControl1000

Sets the range of game numbers to 1 through 1000

CheckBox1

chkVerbose

Determines the level of messaging displayed by the game

Label1

lblGamesWon

Identifies the TextBox control where the total number of games won is displayed

Label2

lblInstructions

Identifies the TextBox control where the player enters guesses

Label3

lblFeedback

Identifies the TextBox control where game output is displayed

Button1

btnDefaults

Resets default RadioButton and CheckBox control settings

Button2

btnReset

Resets the number of games won back to 0 to start a new game session

Button3

btnCheckGuess

Processes the player's guess to see if the player guessed low, high, or won the game

Button4

btnNewGame

Starts a new game

TextBox1

txtGamesWon

Displays the number of games that the player has won

TextBox2

txtInput

Collects and displays player guesses

TextBox3

txtOutput

Displays output messages generated during gameplay

StatusStrip1

stsControl

Displays information messages during gameplay

Step 1: Creating a New Visual C++ Project

The first step in creating the Guess a Number game is to open Visual C++ and create a new project, as outlined here:

  1. If you have not already done so, start up Visual C++ 2005 Express, click on File, and select New Project. The New Project dialog box appears.

  2. Select Windows Application template.

  3. Type Guess a Number as the name of your new application in the Name field located at the bottom of the New Project window.

  4. Click on OK to close the New Project dialog box.

Visual C++ now creates a new project for you and displays a new form upon which you can design the game's user interface.

Step 2: Creating the User Interface

The first step in laying out the user interface is adding controls to the form and moving and resizing them to the appropriate locations. The following function outlines the overall steps involved in creating the game's user interface. As you go through each step, make sure that you reference Figure 6.9 so that you know where to place each control.

  1. Start by adding two GroupBox controls to the form. Position and resize them, as shown in Figure 6.8.

    Hint 

    A GroupBox control is a container that organizes other controls. The GroupBox control displays a caption, set using its Text property, and displays a visible border.

  2. Add three RadioButton controls to the form and move them into the first GroupBox control.

    Hint 

    A RadioButton control allows you to collect True/False or On/Off information. RadioButton controls are used together in groups to give users the ability to pick between mutually exclusive choices.

  3. Add a CheckBox control to the form and move it to the right of the last RadioButton control.

    Hint 

    A CheckBox control lets you collect True/False or On/Off information. Unlike RadioButton controls, you can use CheckBox controls individually. When selected, the CheckBox control displays an x.

  4. Add a Button control to the first GroupBox control and resize it.

  5. Add a Label, a TextBox, and a Button control to the second GroupBox and resize and position them.

  6. Add two additional Label controls and position them toward the middle of the form.

  7. Add a TextBox control to the right of the first Label control and increase its width by approximately 30 percent.

  8. Add another TextBox control underneath the second Label control and resize it until it spans the length of the form.

  9. Add two more Button controls to the bottom area of the second GroupBox.

  10. Finally, add a StatusStrip control to the bottom of the form and select a StatusLabel from its drop-down list.

image from book
Figure 6.8: Completing the interface design for the Guess a Number game.

The overall layout of your new application's form is now complete.

Step 3: Customizing Form and Control Properties

It is time for you to customize various properties belonging to the form and the controls that you have placed on it. Begin by changing the form properties listed in Table 6.3.

Table 6.3: Property Changes for Form1

Property

Value

Name

frmMain

Cursor

Hand

FormBorderStyle

Fixed3D

StartPosition

CenterScreen

Text

Guess a Number

Next, make the changes shown in Table 6.4 to the GroupBox controls.

Table 6.4: Property Changes for the GroupBox Controls

Control

Property

Value

GroupBox1

Name

grpRange

 

Text

Select Range

GroupBox2

Name

grpScore

 

Text

Score

Make the changes shown in Table 6.5 to the RadioButton controls.

Table 6.5: Property Changes for the RadioButton Controls

Control

Property

Value

RadioButton1

Name

rbnControl10

 

Text

Range: 1 to 10

RadioButton2

Name

rbnControl100

 

Checked

True

 

Text

Range: 1 to 100

RadioButton3

Name

rbnControl1000

 

Text

Range: 1 to 1000

Make the changes shown in Table 6.6 to the Button controls.

Table 6.6: Property Changes for the Button Controls

Control

Property

Value

Button1

Name

btnDefaults

 

Text

Reset Defaults

Button2

Name

btnReset

 

Text

Reset Score

Button3

Name

btnCheckGuess

 

Enabled

False

 

Text

Check Guess

Button4

Name

btnNewGame

 

Text

NewGame

Make the changes shown in Table 6.7 to the CheckBox control.

Table 6.7: Property Changes for the CheckBox Control

Property

Value

Name

chkVerbose

Checked

True

CheckState

Checked

Text

Verbose Messaging

Make the changes shown in Table 6.8 to the Label controls.

Table 6.8: Property Changes for the Label Controls

Control

Property

Value

Label1

Name

lblGamesWon

 

Font.Bold

True

 

Text

No. of Games Won:

Label2

Name

lblInstructions

 

Font.Bold

True

 

Font.Size

10

 

Text

Enter Your Guess:

Label3

Name

lblFeedback

 

Font.Bold

True

 

Text

Feedback and Results

Make the changes shown in Table 6.9 to the TextBox controls.

Table 6.9: Property Changes for the TextBox Controls

Control

Property

Value

TextBox1

Name

txtGamesWon

 

ReadOnly

True

 

TabStop

False

TextBox2

Name

txtInput

 

Enabled

False

TextBox3

Name

txtOutput

 

ReadOnly

True

 

TabStop

False

Make the changes shown in Table 6.10 to the StatusStrip control.

Table 6.10: Property Changes for the StatusStrip Control

Object

Property

Value

StatusStrip1

Name

stsControl

 

SizingGrip

False

toolstripStatus1

Name

stsLabel

 

Text

Game Ready!

That's it. At this point, you have configured all the form and control properties that need to be set at design time.

Step 4: Adding a Little Programming Logic

Begin by double-clicking on the form. This activates the Code Editor. Locate the block of code shown in the next program listing and add the statements shown in bold:

 private:     /// <summary>     /// Required designer variable     /// </summary>     Int16 intRandomNumber;     Int16 intTextGamesWon; 

The intRandomNumber variable is used throughout the application to store the game's randomly generated secret number. The intTextGamesWon variable keeps track of the number of games won. Next, modify the form's Load event function, as shown next:

 System::Void frmMain_Load(System::Object^ sender, System::EventArgs^  e) {         //Clear game variables and text         intRandomNumber = 0;         intTextGamesWon = 0;         txtGamesWon->Text = intTextGamesWon.ToString();         //Set focus on new game button         btnNewGame->Focus(); } 

The first two statements set the value of intRandomNumber and intTextGamesWon to 0. This ensures that the game won't access some random value in memory when these values are first used. The next statement initializes the display of the txtGamesWon text box, setting it to the value of intTextGamesWon. The last statement places focus on the btnNewGame control.

Next, we need to add logic to the btnDefaults control to reset the game's default settings, as controlled by the RadioButton and CheckBox controls located in the first GroupBox control. Do so by modifying the click event function for the btnDefaults control, as shown next:

 private: System::Void btnDefaults_Click(System::Object^ sender, System::EventArgs^  e) {         //Reset all game defaults         rbnControl100->Checked = true;         chkVerbose->Checked = true;         //Set focus on text input         txtInput->Focus(); } 

The first statement selects the RadioButton that represents the range of 1 to 100. The second statement selects (by placing an x inside) the chkVerbose CheckBox control, and the third statement sets the focus to the txtInput control (to save the player the trouble of having to put it there before typing the next guess).

Next, let's add logic to the btnReset control so that the player can reset the value that tracks the number of games won to 0 at any time. Also, take note that the value is first assigned to the variable and then converted so that the txtGameWon->Text text property can display it:

 private: System::Void btnReset_Click(System::Object^ sender, System::EventArgs^ e) {         //Reset the game score         intTextGamesWon = 0;         txtGamesWon->Text = intTextGamesWon.ToString(); } 

Next, add the following statements to the TextChanged event for the txtInput control:

 private: System::Void txtInput_TextChanged(System::Object^ sender, System::EventArgs^  e) {         //Toggle appropriate buttons when         //  text is being entered for the         //  guess         btnCheckGuess->Enabled = true;         btnNewGame->Enabled = false; } 

The TextChanged event is triggered automatically whenever the user keys something into the TextBox control that is associated with the event. It is used in the Guess a Number game to control when the btnCheckGuess button is enabled and when the btnNewGame button is disabled.

Now we need to add logic to the application that randomly generates the game's secret number. To do so, I have decided to create a new function named GenerateRandomNumber() and place the logic to generate the random number in it. You can't automatically generate this function by double-clicking on an object in the Form Designer. Instead, you need to key it in entirely by hand, as shown next. You'll learn more about how to work with functions in Chapter 8, "Enhancing Code Structure and Organization," including how to create your own custom functions. For now, just key in the function, as shown here:

 private: Void GenerateRandomNumber( Void ) {          //Get a random number based on the          //  current time          DateTime moment = DateTime::Now;          Random^ randNumGen =                   gcnew Random( moment.Millisecond );          Int32 intUpperLimit = 0;          //Check to see which radio button is          //  checked to determine upper          //  limit of random number          if( rbnControl10->Checked == true )            intUpperLimit = 10;          if( rbnControl100->Checked == true )            intUpperLimit = 100;          if( rbnControl1000->Checked == true )            intUpperLimit = 1000;          //Get the number based on the upper range          intRandomNumber = randNumGen->Next( intUpperLimit ); } 

When called by the btnNewGame control's click event function, the GenerateRandomNumber function first gets the computer's current time. Then it instantiates a new Random object called randNumGen and checks to see which RadioButton control is currently selected so that it knows which range to use when generating the game's secret number. After that, the function executes the randNumGen object's Next() method so that it can generate the random number. The Next() method is passed the value stored in the intUpperLimit variable so that it can specify the maximum range from which the random number should be selected (between 0 and the value of intRandomNumber).

Trick 

The Random object's Next() method generates a random number. If called without passing it parameters, the Next() method generates a positive whole number. If passed a single integer value, the Next() method generates a random number between zero and the value of the integer argument. If passed two integer values, the Next() method generates a random number within the specified range.

Now let's add the code required for the click event belonging to the btnCheckGuess control, as shown here:

 private: System::Void btnCheckGuess_Click(System::Object^ sender. System::EventArgs^  e) { //Check the player's guesses //Declare variable to store current guess Double dblPlayerGuess = 0; //Declare variable to continuously keep //  track of player guesses static Int32 intNoOfGuesses = 0; //First, check to see if text has been entered if( txtInput->Text->Length > 0 ) {   //Try to convert the number and store it in   //  the dblPlayerGuess variable; if the player   //  accidentally enters text or a fraction,   //  the Double::TryParse method fails gracefully   if( Double::TryParse( txtInput->Text, dblPlayerGuess ) )   {     //Enable button     btnCheckGuess->Enabled = true;     //Check whether player guess equals number     if( dblPlayerGuess == intRandomNumber )     {       txtInput->Text = "";       intNoOfGuesses += 1;       //Check whether verbose messaging is on       if( chkVerbose->Checked == true )       {         //Create the message string         txtOutput->Text =         String::Concat( "Congratulations! "         "You've won the Guess A Number Game! "         "Number of guesses made = ",         intNoOfGuesses.ToString() );       }       else         txtOutput->Text =         "Congratulations!";             //Reset number of guesses             intNoOfGuesses = 0;             //Disable text input             txtInput->Enabled = false;             //Update number of games won             intTextGamesWon += 1;             txtGamesWon->Text =               intTextGamesWon.ToString();             //Enable the New Game button             btnNewGame->Enabled = true;             //Disable the check guess button             btnCheckGuess->Enabled = false;             //Enable all of the radio buttons             rbnControl10->Enabled = true;             rbnControl100->Enabled = true;             rbnControl1000->Enabled = true;             //Enable the two reset buttons             btnDefaults->Enabled = true;             btnReset->Enabled = true;             stsLabel->Text = "Get Ready!"; }           }           //Is player guess less than number?           if( dblPlayerGuess < intRandomNumber )           {             //Clear text             txtInput->Text = "";             //Increase guess count             intNoOfGuesses += 1;             //Check if verbose messaging is on             if( chkVerbose->Checked == true )             {               //Create the message string               txtOutput->Text =               String::Concat( "The number that "               "you entered was too low. "               "Please enter a higher number "               "and try again. "               "Number of guesses made = ",              intNoOfGuesses.ToString() );            }            else              txtOutput->Text =              "Too low.";          }          //Is player guess is greater than number          if( dblPlayerGuess > intRandomNumber )          {            //Clear text            txtInput->Text = "";            //Increase guess count            intNoOfGuesses += 1;            //Check whether verbose messaging is on            if( chkVerbose->Checked == true )            {              //Create the message string              txtOutput->Text =              String::Concat( "The number that "              "you entered was too high. "              "Please enter a lower number "              "and try again. "              "Number of guesses made = ",              intNoOfGuesses.ToString() );            }            else              txtOutput->Text =              "Too high.";          }        }        else        {         if( chkVerbose->Checked == true )         {           //Create the message string           txtOutput->Text =           String::Concat( "Sorry, you "           "entered a non-numeric guess. "           "Please enter a number and "           "try again. " );         }         else           txtOutput->Text =           "Numeric input required.";        }      }      else      {       if( chkVerbose->Checked == true )       {         //Create the message string         txtOutput->Text =         String::Concat( "Sorry, but ",         "a number is required to. ",         "play. Please enter a ",         "number and try again." );       }       else         txtOutput->Text =         "No input provided.";      }      txtInput->Focus(); } 

As you can see, this function is rather long and contains the bulk of the application's programming logic. It begins by declaring two variables. The first variable is dblPlayerGuess and is used to store and process the input provided by the player. A new value will be assigned to this variable each time the player clicks on the Button control labeled Check Guess. Therefore, it is declared as a local variable. However, the second variable, which is named intNoOfGuesses, is defined as a static variable, making its lifetime last for as long as the game runs. This allows it to maintain a count of the number of guesses that the player makes during each game.

Next, an if...else block is set up that determines which statements in the function execute based on whether the player entered input. If no input was provided, an error message is displayed in the txtOutput control. Otherwise, a second nested if...else block executes and checks whether the input that the player supplied is numeric. If the input is not numeric, an error message is displayed in the txtOutput control. If the input is numeric, one of three nested if blocks executes. The first if block checks whether the player won the game by guessing the secret number. The second if block checks whether the player's guess was too low, and the third if block checks whether the player's guess was too high.

If the player's guess was too high or too low, an error message is displayed in the txtOutput control. The message that is displayed depends on whether the chkVerbose control is checked. If the player guesses correctly, she wins the game, and a congratulatory message is displayed in the txtOutput control. In addition, the following actions are taken to prepare the game for another play:

  • The value of intNoOfGuesses is reset to 0.

  • The value indicating the number of games won is incremented, converted, and stored in the txtGamesWon control's text property.

  • The Check Guess button is disabled, and the New Game button is enabled.

  • The game's RadioButton controls are enabled, allowing the player to make changes to them if desired.

  • The game's Reset Default button is also enabled.

  • The message displayed in the game's StatusStrip control is updated.

Last but not least, it is time to add some code to the btnNewgame control's click event function, as shown here:

 private: System::Void btnNewGame_Click(System::Object^ sender, System::EventArgs^  e) {         //Set conditions for new game         //Generate a new random number         this->GenerateRandomNumber();         txtOutput->Text         txtInput->Text = "";         //Set starting game buttons         btnNewGame->Enabled = false;         btnCheckGuess->Enabled = true;         //Enable text input         txtInput->Enabled = true;         //Turn off radio buttons         rbnControl10->Enabled = false;         rbnControl100->Enabled = false;         rbnControl1000->Enabled = false;         //Disable the two reset buttons         btnDefaults->Enabled = true;         btnReset->Enabled = true;         //Set status strip text         stsLabel->Text = "Enter your guess.";         txtInput->Focus(); } 

When clicked, the code for the button causes the GenerateRandomNumber function to be called. Note that it uses the format this->GenerateRandomNumber(). The keyword this was used so that the form could refer to (and hence access) one of its own elements. Next, the function clears any text display in the txtInput and txtOutput controls. Following this, the btnNewGame control is disabled, and the btnCheckGuess control is enabled. Then the txtInput control is enabled to allow the player to enter a guess, and the game's RadioButton control and btnReset control are disabled, preventing the player from making configuration changes while a new game is being played. Finally, an instructional message is displayed on the game's StatusStrip control, and the cursor is placed in the txtInput control.

Step 5: Testing the Execution of the Guess a Number Game

That's it. The Guess a Number game is ready to run. Press F5 to see how it works. If you have errors, double-check your typing. Otherwise, pass it on to your friends and ask them to play and to report any problems back to you if they run into anything faulty.




Microsoft Visual C++ 2005 Express Edition Programming for the Absolute Beginner 2006
Microsoft Visual C++ 2005 Express Edition Programming for the Absolute Beginner 2006
ISBN: 735615381
EAN: N/A
Year: 2005
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net