Every programming language allows you to perform tests between two or more conditions. This ability is one of the cornerstones of programming logic. It lets you develop scripts that collect input from the user or the user's computer and compare it to one or more conditions. Using the results of the tests, you can alter the execution of your scripts and create dynamic scripts that can adjust their execution according to the data with which they're presented. In this chapter, you'll learn how to add conditional programming logic to your scripts. In addition to teaching the application of conditional logic, this chapter's game project also provides essential information for working with the Windows file system.
By the time that you have completed this chapter, you will have learned how to
In this chapter, you'll create a game that administers and scores a quiz based on various Star Trek TV shows and movies. The game will ask the player a series of questions and then assign a rank of Ensign, Lieutenant, Lieutenant Commander, Commander, Captain, or Admiral, based on the player's final score. In addition to displaying the final results, the game will also create a report that shows every question that was asked, the player's answer, the correct answer for any incorrectly answered question, the total number of questions answered correctly, and the player's assigned rank.
Figures 5.1 through 5.5 show some of the interaction between the player and the game.
Figure 5.1: The game's splash screen invites the user to take the quiz.
Figure 5.2: This dialog appears if the user decides not to play.
Figure 5.3: This figure shows an example of the types of questions asked by the game.
Figure 5.4: When the player finishes the questions, his or her score is tallied and a rank is assigned, based on the number of questions correctly answered
Figure 5.5: At the end of the game, a report that the user can reference for a detailed explanation of how they did on the quiz is generated.
During the development of this game, you will learn how to apply sophisticated conditional logic. You'll also learn how to work with a number of built-in VBScript functions. In addition, you'll learn a lot about the FileSystemObject, including how to use it to create a scorecard report for the Star Trek Quiz game.
In any programming language, you need to be able to test whether a condition is true or false in order to develop complex logical processes. VBScript provides two different statements that perform this function. These statements are
You've already seen short demonstrations of the If statement in earlier chapters of this book. This is because even the simplest scripts require some form of conditional logic.
The power and importance of these two statements cannot be overstated. For example, let's say you took a job from someone without exactly knowing what you'd be paid, and now you're done and are waiting to be paid. As you're waiting, you think about what you want to do with your new-found fortune. After a few moments, you decide that if you're paid $250, then you'll by a TV. If you're paid less, you think, you'll buy a radio instead. This kind of test lends itself well to an If statement. Let's rewrite this scenario into a more program-like format.
If your pay is equal to $250 Then Buy a TV Else Buy a Radio EndIf
As you can see, the logic is very straightforward and translates well from English into pseudo code. I highlighted portions of the example in order to point out the key VBScript language programming components that are involved. I'll go into greater detail about what each of these keywords means a little later in the chapter.
Back to our scenario: Perhaps after thinking about it a few more minutes, you decide that there are a number of things that you might do with your pay, depending on how much money you receive. In this case, you can use the VBScript Select Case statement to outline the logic of your decisions in pseudo code format.
Definition
Pseudo code is a rough, English-like outline or sketch of a script. By writing out the steps you think will be required to write a script in pseudo code, you provide yourself with an initial first-level script design that will serve as a basis for building the final product.
Select Case Your Pay Case If you get $250 you'll buy a TV Case If you get $200 you'll buy a VCR Case If you get $100 you'll buy a radio Case Else You'll just buy lunch End Select
Again, I have highlighted portions of the example to point out key VBScript language programming components involved. In the next two sections of this chapter, I'll break down the components of the If and Select Case statements into greater detail and show you exactly how they work.
The VBScript If statement lets you test two values or conditions and to alter the execution of the script based on the results of the test. The syntax of his statement is as follows:
If condition Then statements ElseIf condition-n Then statements . . . Else statements End If
Working with the If Statement
The If statement begins with the If keyword and ends with the End If. Condition represents the comparison being performed. For example, you might want to see if the value of an X is equal to 250, like this:
If X = 250 Then
The keyword Then identifies the beginning of a list of one or more statements. Statements is a placeholder representing the location where you would supply whatever script statements you want executed. For example, the following example displays a complete If statement that tests to see whether a variable has a value of 250, and if it does (that is, the test provides equal to true), a message is displayed:
If X = 250 Then WScript.Echo "Go and buy that TV!" End If
You may add as many statements as you wish between the Then and End If keywords.
If X = 250 Then WScript.Echo "Go and buy that TV!" WScript.Echo "Buy a TV Guide while you are at it." WScript.Echo "And do not forget to say thank you." End If
But what happens if the tested condition proves false? Well, in the previous test, nothing. However, by adding the Else keyword and one or more additional statements, the script is provided with an additional execution path.
If X = 250 Then WScript.Echo "Go and buy that TV!" WScript.Echo "Buy a TV Guide while you are at it." WScript.Echo "And do not forget to say thank you." Else WScript.Echo "OK. Just purchase the radio for today." End If
Figure 5.6 provides a flowchart view of the logic used in this example.
Figure 5.6: A flowchart outlining the logic behind a typical If statement
You can expand the If statement by adding one or more ElseIf keywords, each of which provides the ability to test another alternative condition. For example, look at the following VBScript Statements:
If X = 250 Then WScript.Echo "Go and buy that TV!" WScript.Echo "Buy a TV Guide while you are at it." WScript.Echo "And do not forget to say thank you." ElseIf X = 200 Then WScript.Echo "Buy the VCR" ElseIf X = 100 Then WScript.Echo "Buy the Radio." Else WScript.Echo "OK. Maybe you had best just eat lunch." End If
Nesting If Statements
Another way to use If statements is to embed them within one another. This allows you to develop scripts that test for a condition and then further test other conditions based on the result of the previous test. To see what I mean, look at the following example (I have bolded the embedded If statement to make it easier to see):
X = 250 If X = 250 Then If Weekday(date()) = 1 Then WScript.Echo "Its Sunday. The TV store is closed on Sundays." Else WScript.Echo "Go and buy that TV!" & vbCrLf & _ "Buy a TV Guide while you are at it." & vbCrLf & _ "And do not forget to say thank you." End IF Else WScript.Echo "OK. Just purchase the radio for today." End If
IN THE REAL WORLD
Flowchart development can be a big help in the development of complex scripts. Flowcharts help programmers formalize their thoughts before script development begins. Sometimes an automation task requires the development of several scripts, all of which must work together. Flowcharts provide a way of designing and documenting the logical flow between each script. Flowcharts can also facilitate script development when multiple programmers are involved, as they can be used to break a task down into discrete parts, each of which can then be assigned to a different person to work on.
In this example, the first statement performs a test to see whether the value assigned to a variable named X is equal to 250. If it's not equal to 250, the script skips all the statements located between the If X = 250 Then line and the Else line and displays the message "OK. Just purchase the radio for today." However, if the value of X is equal to 250, then the embedded If statement executes. This If statement begins by determining whether the current day of the week is Sunday, and if it is, the script informs the user that the TV store is closed. Otherwise, it tells the user to go and make the purchase.
TRICK |
The test performed by the If statement in the previous example deserves a little extra explanation. As you saw, it retrieved a numeric value representing the current day of the week. Here's how to break down the logic used by this statement: First, it executed the built-in VBScript Date() function. The value retrieved by this function was then used by the built-in VBScript Weekday() function to determinate the numeric value that represents the current day of the week. These values are 0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday, 5 = Friday, 6 = Saturday, and 7 = Sunday. Once this value was established, the If statement simply checked to see if it was equal to 7 (Sunday). As you can see, by taking advantage of built-in VBScripts functions you can perform some fairly complex tasks with minimal coding. It's a good idea to always check to see whether VBScript has a built-in function before attempting to write a piece of code to perform a generic task, such as date manipulation or checking. |
HINT |
By embedding, or nesting one If statement within another If statement, you can develop very complex programming logic. There's no limit on the number of If statements that you can embed within one another, although going more than a few layers deep can become confusing and difficult to follow. |
RockPaperScissors.vbs Revisited
Okay. You've now learned a lot about the If statement, including its syntax and various ways in which it can be used. One of the biggest challenges that I faced in coming up with the VBScript examples for the first four chapters of the book was how to create VBScript-based games without using VBScript programming statements that I had not yet covered. For the most part I was successful, but there was one exception: I just could not avoid using the If statement—though I tried to use it as little as possible. In most cases, this meant limiting the completeness of the games that were presented.
One such game was the RockPaperScissors.vbs game. Now that I've finally had the opportunity to provide a complete review of the If statement, let's revisit the game and see how we can make it better.
'Formally declare each variable used by the script before trying to use them Dim WshShell, Answer, CardImage 'Create an instance of the WScript object in order to later use the Popup method Set WshShell = WScript.CreateObject("WScript.Shell") 'Display the rules of the game WshShell.Popup "Welcome to Rock, Paper, and Scissors game. Here are the "& _ "rules of the game: 1. Guess the same thing as the computer "& _ "to tie. 2. Paper covers rock and wins. 3. Rock breaks "& _ "scissors and wins. 4. Scissors cut paper and win." 'Prompt the user to select a choice Answer = InputBox("Type either Paper, Rock, or Scissors.", "Let's play a game!") 'Time for the computer to randomly pick a choice Randomize GetRandomNumber = Round(FormatNumber(Int((3 * Rnd) + 1))) 'Assign a value to the randomly selected number If GetRandomNumber = 3 then CardImage = "rock" If GetRandomNumber = 2 then CardImage = "scissors" If GetRandomNumber = 1 then CardImage = "paper" 'Display the game's results so that the user can see if he won WshShell.Popup "You picked: "& Answer & Space(12) & "Computer picked: "& _ CardImage
Figure 5.7 shows the output of a complete game as the script currently is written.
Figure 5.7: Playing Rock, Paper, and Scissors
First off, let's update the scripts by adding the script template that was introduced back in Chapter 3.
'************************************************************************* 'Script Name: RockPaperScissors-2.vbs 'Author: Jerry Ford 'Created: 11/16/02 'Description: This script revisits the RockPaperScissors.vbs script, first 'introduced in Chapter 2, and updates it using advanced conditional logic. '*************************************************************************
Next, let's rewrite the Dim statement by adding another variable called Results.
Dim WshShell, Answer, CardImage, Results
Results will be used later in the scripts to store the results of the game (that is, who wins and who loses). Next let's add the following statement to the script:
Set WshShell = WScript.CreateObject("WScript.Shell")
This statement creates an instance of the WshShell object. This object's Quit() method will be used later in the script to terminate its execution in the event that the user fails to provide a valid selection (that is, the player does not pick rock, paper, or scissors).
Now that the variables and objects to be used by the script have been defined, let's assign a default value of None to the Results variable, like this:
Results = "None"
Unless the player provides a correction selection, this value will remain equal to None throughout the script's execution, and will eventually cause the script to terminate and display an error message. However, if the player supplies a correct response, the response will be assigned to the Results variable and then will be analyzed by the script.
The original RockPaperScissors.vbs script displayed the game's instructions in one popup dialog, and then prompted the player to specify a selection of rock, paper, or scissors in a second popup dialog. This works, but using two popup dialogs is a bit clunky. Let's modify the scripts to display the game's directions and collect the player's input at the same time, like this:
Answer = InputBox("Please type either paper, rock, or scissors." & vbCrLf & _ vbCrLf & "Rules:" & vbCrLf & vbCrLf & _ "1. Guess the same thing as the computer to tie." & vbCrLf & _ "2. Paper covers rock and wins." & vbCrLf & _ "3. Rock break scissors and wins." & vbCrLf & _ "4. Scissors cut paper and win." & vbCrLf, "Let's play a game!")
As you can see, I used the VBScript InputBox() function to display the popup dialog, and I formatted the instructions for better presentation using the vbCrLf constant.
The next two sections of the script remain the same as in the original script.
Randomize GetRandomNumber = Round(FormatNumber(Int((3 * Rnd) + 1))) If GetRandomNumber = 3 then CardImage = "rock" If GetRandomNumber = 2 then CardImage = "scissors" If GetRandomNumber = 1 then CardImage = "paper"
As explained in Chapter 2, the first pair of statements results in the selection of a random number with a value between 1 and 3. The next three lines assign a value of rock, paper, or scissors to each of these values. The rest of the script will be comprised of all new code. Instead of simply displaying the player's and the script's selection of rock, paper, or scissors and then leaving it up to the player to figure out who won, the script now performs the analysis. To begin, add the following lines to the bottom of the script:
If Answer = "rock" Then If GetRandomNumber = 3 Then Results = "Tie" If GetRandomNumber = 2 Then Results = "You Win" If GetRandomNumber = 1 Then Results = "You Lose" End If
This set of statements executes only if the player typed rock. Three If statements then compare the user's selection to the script's randomly selected decisions and determine the results of the game. Now replicate this collection of statements two times, and then modify each set as follows in order to add tests for the selection of both scissors and paper:
If Answer = "scissors" Then If GetRandomNumber = 3 Then Results = "You Lose" If GetRandomNumber = 2 Then Results = "Tie" If GetRandomNumber = 1 Then Results = "You Win" End If If Answer = "paper" Then If GetRandomNumber = 3 Then Results = "You Win" If GetRandomNumber = 2 Then Results = "You Lose" If GetRandomNumber = 1 Then Results = "Tie" End If
Now add the following statements to the script:
If Results = "None" Then WshShell.Popup "Sorry. Your answer was not recognized. "& _ "Please type rock, paper, or scissors in all lowercase letters." WScript.Quit End If
These statements only execute if the player fails to provide a correct response when playing the game. If this happens, the value of Results is never changed and will still be set equal to None as assigned at the beginning of the script. In this case, the WshShell object's Popup() and Quit() methods are used to display an error message and then end the game.
Now let's wrap this script up by adding these last few lines of code.
WshShell.Popup "You picked: "& space(12) & Answer & vbCrLf & vbCrLf & "Computer picked: "& _ space(2) & CardImage & vbCrLf & vbCrLf & "================" & vbCrLf & vbCrLf & _ "Results: "& Results
These statements are only executed if the player provided a valid response. They used the WshShell objet's Popup() method to display the results of the game, including both the player's and the script's selections.
The fully assembled script should now look like the following:
'************************************************************************* 'Script Name: RockPaperScissor-2.vbs 'Author: Jerry Ford 'Created: 11/16/02 'Description: This script revisits the RockPaperScissors.vbs script first 'introduced in Chapter 2 and updates it using advanced conditional logic. '************************************************************************* 'Perform script initialization activities Dim WshShell, Answer, CardImage, Results Set WshShell = WScript.CreateObject("WScript.Shell") Results = "None" 'Prompt the user to select a choice Answer = InputBox("Please type either Paper, Rock, or Scissors." & vbCrLf & _ vbCrLf & "Rules:" & vbCrLf & vbCrLf & _ "1. Guess the same thing as the computer to tie." & vbCrLf & _ "2. Paper covers rock and wins." & vbCrLf & _ "3. Rock break scissors and wins." & vbCrLf & _ "4. Scissors cut paper and win." & vbCrLf, "Let's play a game!") 'Time for the computer to randomly pick a choice Randomize GetRandomNumber = Round(FormatNumber(Int((3 * Rnd) + 1))) If GetRandomNumber = 3 then CardImage = "rock" If GetRandomNumber = 2 then CardImage = "scissors" If GetRandomNumber = 1 then CardImage = "paper" 'When you select rock If Answer = "rock" Then If GetRandomNumber = 3 Then Results = "Tie" If GetRandomNumber = 2 Then Results = "You Win" If GetRandomNumber = 1 Then Results = "You Lose" End If 'When you select scissors If Answer = "scissors" Then If GetRandomNumber = 3 Then Results = "You Lose" If GetRandomNumber = 2 Then Results = "Tie" If GetRandomNumber = 1 Then Results = "You Win" End If 'When you select paper If Answer = "paper" Then If GetRandomNumber = 3 Then Results = "You Win" If GetRandomNumber = 2 Then Results = "You Lose" If GetRandomNumber = 1 Then Results = "Tie" End If If Results = "None" Then WshShell.Popup "Sorry. Your answer was not recognized. "& _ "Please type rock, paper or scissors in all lowercase letters." WScript.Quit End If WshShell.Popup "You picked: " & space(12) & Answer & vbCrLf & vbCrLf & "Computer picked: " & _ space(2) & CardImage & vbCrLf & vbCrLf & "================" & vbCrLf & vbCrLf & _ "Results: "& Results
Save and execute the script. Figure 5.8 shows the initial popup dialog displayed by the script.
Figure 5.8: The new version of RockPaper Scissors.vbs displays a friendlier initial dialog.
Figure 5.9 shows the results of a typical game.
Figure 5.9: The results of a typical game of the new version of RockPaper Scissors.vbs
The If statement provides a great tool for testing two expressions. Using ElseIf you can modify the If statement to perform additional tests. VBScripts supplies another statement, called Select Case, that also lets you perform comparative operations. Functionally, it's not really very different from the If statement. However, the Case Select statement is better equipped to perform large numbers of tests against a single expression.
The syntax of the Select Case statement is as follows:
Select Case expression Case value statements . . . Case value statements Case Else statements End Select
The Select Case statement begins with Select Case, and then specifies the expression to be compared against one or more values specified in Case statements that follow the Select Case statement and precede the End Select statement. Optionally, a Case Else statement can also be added to provide an alternative course of action should none of the Case statement's values match up against the expression specified by the Select Case statement.
Look at the following example:
Select Case answer Case "rock" If GetRandomNumber = 3 Then Results = "Tie" If GetRandomNumber = 2 Then Results = "You Win" If GetRandomNumber = 1 Then Results = "You Lose" Case "scissors" If GetRandomNumber = 3 Then Results = "You Lose" If GetRandomNumber = 2 Then Results = "Tie" If GetRandomNumber = 1 Then Results = "You Win" Case "paper" If GetRandomNumber = 3 Then Results = "You Win" If GetRandomNumber = 2 Then Results = "You Lose" If GetRandomNumber = 1 Then Results = "Tie" Case Else WshShell.Popup "Sorry. Your answer was not recognized. "& _ "Please type rock, paper, or scissors in all lowercase letters." WScript.Quit End Select
Here I have rewritten most of the logic implemented in the RockPaperScissors.vbs script. As the following complete script shows, not only did I reduce the number of lines of code required by the script to work, but I also improved the script's readability:
'************************************************************************* 'Script Name: RockPaperScissors-3.vbs 'Author: Jerry Ford 'Created: 11/16/02 'Description: This script revisits the RockPaperScissors-2.vbs script, 'replacing some of the If statement's logic with a Case Select statement. '************************************************************************* 'Perform script initialization activities Dim WshShell, Answer, CardImage, Results Set WshShell = WScript.CreateObject("WScript.Shell") Results = "None" 'Prompt the user to select a choice Answer = InputBox("Please type either Paper, Rock, or Scissors." & vbCrLf & _ vbCrLf & "Rules:" & vbCrLf & vbCrLf & _ "1. Guess the same thing as the computer to tie." & vbCrLf & _ "2. Paper covers rock and wins." & vbCrLf & _ "3. Rock break scissors and wins." & vbCrLf & _ "4. Scissors cut paper and win." & vbCrLf, "Let's play a game!") 'Time for the computer to randomly pick a choice Randomize GetRandomNumber = Round(FormatNumber(Int((3 * Rnd) + 1))) If GetRandomNumber = 3 then CardImage = "rock" If GetRandomNumber = 2 then CardImage = "scissors" If GetRandomNumber = 1 then CardImage = "paper" Select Case answer Case "rock" If GetRandomNumber = 3 Then Results = "Tie" If GetRandomNumber = 2 Then Results = "You Win" If GetRandomNumber = 1 Then Results = "You Lose" Case "scissors" If GetRandomNumber = 3 Then Results = "You Lose" If GetRandomNumber = 2 Then Results = "Tie" If GetRandomNumber = 1 Then Results = "You Win" Case "paper" If GetRandomNumber = 3 Then Results = "You Win" If GetRandomNumber = 2 Then Results = "You Lose" If GetRandomNumber = 1 Then Results = "Tie" Case Else WshShell.Popup "Sorry. Your answer was not recognized. "& _ "Please type rock, paper, or scissors in all lowercase letters." WScript.Quit End Select WshShell.Popup "You picked: "& space(12) & Answer & vbCrLf & vbCrLf & "Computer picked: "& _ space(2) & CardImage & vbCrLf & vbCrLf & "================" & vbCrLf & vbCrLf & _ "Results: "& Results
Up to this point in the book every example of the If or a Select Case statement that you have seen has involved a single type of comparison, equality. This is a very powerful form of comparison, but there will be times when your scripts will need to test for a wider range of values. For example, suppose you wanted to write a script that asked the user to type in their age so that you could determine whether the user was old enough to play your game (say you didn't want a user to play the game if he or she was younger than 19). It would be time-consuming to write a script that used a 100 If statements, or 1 Select Case statement with 100 corresponding Case statements, just to test a person's age. Instead, you could save a lot of time by comparing the user's age against a range of values. To accomplish this task, you could use the VBScript Less Than operator as follows:
UserAge = InputBox("How old are you?") If UserAge < 19 Then MsgBox "Sorry but you are too young to play this game." WScript.Quit() Else MsgBox "OK. Let's play!" End If
In this example, the VBScript InputBox() function was used to collect the user's age and assign it to a variable called UserAge. An If statement then checks to see if UserAge is less than 19, and if it is, the game is stopped. Another way you could write the above example is using the VBScript Less Than or Equal To operator, like this:
If UserAge <= 18 Then
If you use the Less Than or Equal To operator, this statement will not execute if the user is 18 or fewer years old. VBScript also supplies Greater Than and Greater Than or Equal To operators, allowing you to invert the logic used above.
UserAge = InputBox("How old are you?") If UserAge > 18 Then MsgBox "OK. Let's play!" Else MsgBox "Sorry but you are too young to play this game." WScript.Quit() End If
Table 5.1 lists VBScript comparison operators.
Operator |
Description |
---|---|
= |
Equal |
<> |
Not equal |
< |
Less than |
> |
Greater than |
<= |
Less than or equal to |
>= |
Greater than or equal to |
VBScript does not impose an order or precedence on comparison operators like it does with arithmetic operators. Instead, each comparison operation is performed in the order in which it appears, going from left to right.
Now let's return to where we began this chapter, by developing the Star Trek Quiz game. In this program, you will create a VBScript that presents the player with a quiz about Star Trek. The game will present questions, collect the player's answers, score the final results, assign a rank to the player based on his or her score, and finally create a summary text report. By working your way though this project, you will get the opportunity to work more with both the If and Select Case statements. You'll also learn how to work with a number of built-in VBScript functions. Finally, you'll learn a lot about how to work with the VBScript FileSystemObject object.
The project will be developed in two stages, each of which has a number of steps. In Stage 1 you will develop a full working version of the game. In Stage 2, you will expand the script to include the logic that creates and saves the scorecard report. The steps involved in these two stages are outlined next.
The following steps outline the process you'll need to go through to complete the first stage of this game development:
Beginning the Star Trek Game Quiz Game
Let's begin this script by opening your script editor and cutting and pasting in your script template from another script. Then go back and modify the template with information relevant to the Star Trek Quiz game.
'************************************************************************* 'Script Name: StarTrekQuiz.vbs 'Author: Jerry Ford 'Created: 11/17/02 'Description: This script creates a Star Trek Quiz game. '************************************************************************* 'Perform script initialization activities Option Explicit
Setting Up Constants and Variables
The next step is to define the variables and constants that will be used by the script.
Dim PlayGame, SplashImage, AnswerOne, AnswerTwo, AnswerThree, AnswerFour Dim AnswerFive, NumberCorrect, FederationRank, FsoObject, ScoreRpt Const cTitlebarMsg = "The Star Trek Quiz Game" 'Start the user's score at zero NumberCorrect = 0
The NumberCorrect variable will be used to count the number of quiz answers that the player gets right. I set NumberCorrect equal to zero here to ensure that it has a value because it is always possible that the player will miss every answer and that this variable might not otherwise get set. I'll explain what each of these variables is used for as we go through the rest of the script development process.
Creating a Splash Screen
Let's create a spiffy splash screen that asks the user if he or she wants to play the game. As you can see, I added a graphic to spice things up a bit. Graphic development of this type takes a little time, as well as some trial and error.
'Display the splash screen and ask the user if he or she wants to play SplashImage = space(11) & "********" & vbCrLf & _ " ******************" & space(20) & "**************************" & _ space(20) & vbCrLf & _ "*" & space(35) & "*" & space(18) & "**" & space(46) & "*" & vbCrLf & _ "******************" & space(20) & "*************************" & vbCrLf & _ space(31) & "******" & space(26) & "***" & vbCrLf & _ space(34) & "******" & space(22) & "***" & vbCrLf & _ space(37) & "******" & space(17) & "***" & vbCrLf & _ space(26) & "****************************" & vbCrLf & _ space(26) & "*******************************" & vbCrLf & _ space(26) & "******************************" & vbCrLf & _ space(26) & "****************************" & vbCrLf & vbCrLf & vbCrLf &_ space(10) & "Would you like to boldly go where no one has gone before?" PlayGame = MsgBox(SplashImage, 36, cTitlebarMsg)
The splash screen is created using the VBScript InputBox() function. It displays the invitation to play the game as well as Yes and No buttons. The value of the button the user clicks is assigned to the PlayGame variable (that is, PlayGame will be set equal to 6 if the player clicks on the Yes button).
Now let's check to see if the user wants to play the game.
If PlayGame = 6 Then 'User elected to play the game 'Insert statements that make up the game here . . . Else 'Userdoesn't want to play MsgBox "Thank you for taking the Star Trek Quiz Jerry Ford 2002." & _ vbCrLf & vbCrLf & "Live long and prosper!", , cTitlebarMsg WScript.Quit() End If
As you can see, the first statement checks to see if the user clicked on the Yes button. I left some room to mark the area where you will need to add the statements that actually make up the game, in case the user does want to play. If the user clicked on No, then the VBScript displays a "thank you" message and terminates its execution using the WScript object's Quit() method.
Display Quiz Questions and Collect the Player Answers
The next step is to add the questions that make up the game. The quiz will be made up of the following questions:
The statements that display and grade the first quiz questions are as follows:
AnswerOne = InputBox("What was the Science Officer's name in the "& _ "original Start Trek series?", cTitlebarMsg) If LCase(AnswerOne) = "spock" Then NumberCorrect = NumberCorrect + 1 End If
First the VBScript InputBox() function is used to display the question. The answer typed by the user is then assigned to a variable named AnswerOne. Next, an If statement is used to interrogate the player's answer and determine whether it's correct. The VBScript LCase() function is used to convert to all lowercase the answer that the player types. This way, it doesn't matter how the player types in the answer. For example, SPOCK, spock, SpOcK and Spock would all end up as spock. Finally, if the player provides the correct answer, then the value of NumberCorrect is increased by 1.
As you can see, the second quiz question, shown next, is processed exactly like the first question. The only difference is the content of the question itself and the name of the variable used to store the player's answer to the question.
AnswerTwo = InputBox("What Star Trek villain appeared in both the "& _ "original series and a Star Trek movie?", cTitlebarMsg) If LCase(AnswerTwo) = "khan" Then NumberCorrect = NumberCorrect + 1 End If
The statements that make up and process the quiz's third question are shown next. As you can see, I have altered the logic a bit by adding an ElseIf statement in order to accommodate either of two possible answers to this question.
AnswerThree = InputBox("What was the numeric designation of Voyager's "& _ "on-board Borge?", cTitlebarMsg) If CStr(AnswerThree) = "7" Then NumberCorrect = NumberCorrect + 1 ElseIf CStr(AnswerThree) = "7 of 9" Then NumberCorrect = NumberCorrect + 1 End If
The statements that make up the fourth question follow the same pattern as the first two questions.
AnswerFour = InputBox("Name the only Star Trek character to regularly "& _ "appear on two series and at least two Star Trek movies?", cTitlebarMsg) If LCase(AnswerFour) = "worf" Then NumberCorrect = NumberCorrect + 1 End If
The construction of the fifth question, shown next, merits some additional examination. First of all, the fourth statement uses the VBScript LCase() function to convert the player's answer to all lowercase. The VBScript Instr() function then takes the answer and searches the string "kirkpicardsiscojanewayarcher" to see if it can find a match. This string contains a list of last names belonging to various Star Fleet captains.
AnswerFive = InputBox("What is the last name of your favorite "& _ "Captain?", cTitlebarMsg) If Len(AnswerFive) > 3 Then If Instr(1, "kirkpicardsiscojanewayarcher", LCase(AnswerFive), 1) <> 0 Then NumberCorrect = NumberCorrect + 1 End If End If
So the InStr() function begins its search starting with the first character of the string to see if it can find the text string that it's looking for (that is, either kirk, picard, janeway, sisco or archer). The syntax of the Instr() function is as follows:
InStr([start, ]string1, string2[, compare])
Start specifies the character position in the script, from left to right, where the search should begin. String1 identifies the string to be searched. String2 identifies the text to search for, and compare specifies the type of search to be performed. A value of 0 specifies a binary comparison, and a value of 1 specifies a textual comparison.
The InStr() function returns the location of the beginning location of a matching text string. If it does not find a matching text string in the list, then it will return to zero, in which case the user provided the wrong answer. Otherwise, it will return the starting character position where the search string was found. If the search string is found in the list, then the value returned by the InStr() function will be greater than 1, in which case the value of NumberCorrect will be incremented by 1.
However, it is always possible that the player doesn't know the name of one Star Ship captain, and that he or she will just type a character or two, such as the letter "A." Since the letter "A" is used in at least one of the captain's last names, the player would end up getting credit for a correct answer to the question. Clearly, this is not good. To try to keep the game honest, I used the VBScript Len() function to make sure that the user provided at least a four-character name (that is, the length of the shortest last name belonging to any captain). This way, the player must know at least the first four characters of a captain's last name to get credit for a correct answer.
Scoring the Player's Rank
At this point, the script has enough logic to display all five questions and determine which ones the player got correct. In addition, it has been keeping track of the total number of correct answers. What you need to do next is add logic to assign the player a rank based on the number of correctly answered questions. This can be done using a Select Case statement, like this:
Select Case NumberCorrect Case 5 'User got all five answers right FederationRank = "Admiral" Case 4 'User got 4 or 5 answers right FederationRank = "Captain" Case 3 'User got 3 of 5 answers right FederationRank = "Commander" Case 2 'User got 2 of 5 answers right FederationRank = "Lieutenant-Commander" Case 1 'User got 1 of 5 answers right FederationRank = "Lieutenant" Case 0 'User did not get any answers right FederationRank = "Ensign" End Select
The variable NumberCorrect contains the number of answers that the player has correctly answered. The value of this variable is then compared against six possible cases, each of which represents a different score the player could have gotten from the game. When a match is found, the player's rank is assigned based on the values listed in Table 5.2.
Number of Correctly Answered Questions |
Federation Rank |
---|---|
0 |
Admiral |
4 |
Captain |
3 |
Commander |
2 |
Lieutenant-Commander |
1 |
Lieutenant |
0 |
Ensign |
Displaying the Player's Score and Rank
The last thing the game does is display the player's score and rank in a popup dialog.
MsgBox "You answered "& NumberCorrect & "out of 5 correct." & vbCrLf & _ vbCrLf & "Your Star Fleet rank is : "& FederationRank, , cTitlebarMsg
As you can see, there is not much to this last statement. All you need to do is to use the VBScript MsgBox() function, the NumberCorrect, and FederationRank variables, as well as the vbCrLf constant, to display the message for the player to see.
Assembling the Script
Okay, let's take a look at how the script looks now. Run it and make sure that everything is working as advertised before moving on to Stage 2.
'************************************************************************* 'Script Name: StarTrekQuiz.vbs 'Author: Jerry Ford 'Created: 11/17/02 'Description: This script creates a Star Trek Quiz game. '************************************************************************* 'Perform script initialization activities Option Explicit Dim PlayGame, SplashImage, AnswerOne, AnswerTwo, AnswerThree, AnswerFour Dim AnswerFive, NumberCorrect, FederationRank, FsoObject, ScoreRpt Const cTitlebarMsg = "The Star Trek Quiz Game" 'Start the user's score at zero NumberCorrect = 0 'Display the splash screen and ask the user if he or she wants to play SplashImage = space(11) & "********" & vbCrLf & _ " ******************" & space(20) & "**************************" & _ space(20) & vbCrLf & _ "*" & space(35) & "*" & space(18) & "**" & space(46) & "*" & vbCrLf & _ " ******************" & space(20) & "*************************" & vbCrLf & _ space(31) & "******" & space(26) & "***" & vbCrLf & _ space(34) & "******" & space(22) & "***" & vbCrLf & _ space(37) & "******" & space(17) & "***" & vbCrLf & _ space(26) & "****************************" & vbCrLf & _ space(26) & "*******************************" & vbCrLf & _ space(26) & "******************************" & vbCrLf & _ space(26) & "****************************" & vbCrLf & vbCrLf & vbCrLf &_ space(10) & "Would you like to boldly go where no one has gone before?" PlayGame = MsgBox(SplashImage, 36, cTitlebarMsg) If PlayGame = 6 Then 'User elected to play the game AnswerOne = InputBox("What was the Science Officer's name in the "& _ "original Start Trek series?", cTitlebarMsg) If LCase(AnswerOne) = "spock" Then NumberCorrect = NumberCorrect + 1 End If Else 'User doesn't want to play MsgBox "Thank you for taking the Star Trek Quiz Jerry Ford 2002." & _ vbCrLf & vbCrLf & "Live long and prosper!", , cTitlebarMsg WScript.Quit() End If AnswerTwo = InputBox("What Star Trek villain appeared in both the "& _ "original series and a Star Trek movie?", cTitlebarMsg) If LCase(AnswerTwo) = "khan" Then NumberCorrect = NumberCorrect + 1 End If AnswerThree = InputBox("What was the numeric designation of Voyager's "& _ "on-board Borge?", cTitlebarMsg) If CStr(AnswerThree) = "7" Then NumberCorrect = NumberCorrect + 1 ElseIf CStr(AnswerThree) = "7 of 9" Then NumberCorrect = NumberCorrect + 1 End If AnswerFour = InputBox("Name the only Star Trek character to regularly "& _ "appear on 2 series and at least 2 Star Trek movies?", cTitlebarMsg) If LCase(AnswerFour) = "worf" Then NumberCorrect = NumberCorrect + 1 End If AnswerFive = InputBox("What is the last name of your favorite "& _ "Captain?", cTitlebarMsg) If Len(AnswerFive) > 3 Then If Instr(1, "kirkpicardsiscojanewayarcher", LCase(AnswerFive), 1) <> 0 Then NumberCorrect = NumberCorrect + 1 End If End If Select Case NumberCorrect Case 5 'User got all five answers right FederationRank = "Admiral" Case 4 'User got 4 or 5 answers right FederationRank = "Captain" Case 3 'User got 3 of 5 answers right FederationRank = "Commander" Case 2 'User got 2 of 5 answers right FederationRank = "Lieutenant-Commander" Case 1 'User got 1 of 5 answers right FederationRank = "Lieutenant" Case 0 'User did not get any answers right FederationRank = "Ensign" End Select MsgBox "You answered "& NumberCorrect & "out of 5 correct." & vbCrLf & _ vbCrLf & "Your Star Fleet rank is : "& FederationRank, , cTitlebarMsg
Now that the first stage is completed, you should have a fully functional game. Now let's outline the steps required to incorporate a reporting capability to the game.
Defining New Variables and the FileSystemObject
In order to create and save a scorecard report for the game, you'll need to add two new variables to the script. (I bolded these variables to make them easier to see.)
Dim PlayGame, SplashImage, AnswerOne, AnswerTwo, AnswerThree, AnswerFour Dim AnswerFive, NumberCorrect, FederationRank, FsoObject, ScoreRpt
The first variable, FsoObject, will be used to instantiate an instance of the VBScript FileSystemObject. The script will then be able to use the methods belonging to this object to create and write the game's report.
Next, add the following statement to the script somewhere after the script's two Dim statements:
Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject")
This statement uses the WScript object's CreateObject() method to instantiate the FileSystemObject.
Adding a Report Header
Now skip down in your script to just after the If PlayGame = 6 Then statement and add the following statements:
Set ScoreRpt = FsoObject.OpenTextFile("C:TempStarTrekQuiz.txt", 2, "True") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine("Star Trek Game Quiz") ScoreRpt.Write("===================================================") ScoreRpt.WriteLine("===================================================") ScoreRpt.WriteBlankLines(2)
You want to place these statements within this If statement because there's no point in executing them if the user elects not to play the game. The first statement opens a file named StarTrekQuiz.txt in a folder named Temp on the C: drive using the FileSystemObject object's OpenTextFile() method.
The format of the OpenTextFile() method is as follows:
object.OpenTextFile(filename[, iomode[, create[, format]]])
Filename is the name and path of the file to be opened or created. Iomode must be one of the following three constants: ForReading, which has a value of 1, ForWriting, which has a value of 2, or ForAppending, which has a value of 8. Create is optional. It specifies whether a new file will be created if one does not already exist. Specify a value of True to create a new file, if necessary, or specify False to prevent a new file from being created. Format specifies one of the following values: True, False, or UseDefault. The first of these three values saves the file in Unicode format. The second saves the file in ASCII format, and the third option stores the file using the operating system's default format.
As the first statement is currently written, the file C:TempStarTrekQuiz.txt is opened in ForWriting mode and will be automatically created if it does not already exist.
The other previously listed statements use three different FileSystemObject methods to write text headers to the file, as explained in the following list:
Reporting the Results of Each Question
Next you'll need to add a number of statements to each question presented by the quiz in order to record the player's activities. Using the first question as an example, I have highlighted the additional code that needs to be added.
AnswerOne = InputBox("What was the Science Officer's name in the "& _ "original Start Trek series?", cTitlebarMsg) ScoreRpt.Write("1. What was the Science Officer's name in the original") ScoreRpt.WriteLine(" Start Trek series?") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: " & AnswerOne) ScoreRpt.WriteBlankLines(1) If LCase(AnswerOne) = "spock" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.WriteLine("The correct answer is spock") End If ScoreRpt.WriteBlankLines(2)
The first five new statements write the question, a blank line, and the player's answer, followed by another blank line.
The code in the If statement that follows has been modified to record whether the player provided a correct or incorrect answer and, if necessary, writes the correct answer. Finally, two more blank lines are written to help make the report more readable.
Adding a Finishing Header
Next let's add two more blank lines to the report, followed by a another header that will separate the main body of the report from the final total and rank assignment entries.
ScoreRpt.WriteBlankLines(2) ScoreRpt.Write("===================================================") ScoreRpt.WriteLine("===================================================") ScoreRpt.WriteBlankLines(1)
You can add these statements just before or after the Select Case statement.
Finishing the Report
The final step in generating the report is to write the player's overall score and rank.
ScoreRpt.WriteLine("Overall score: "& NumberCorrect & "out of 5 cor- rect") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine("Federation Rank: "& FederationRank)
All that remains to be done now is to close the file that contains the report.
ScoreRpt.Close()
Place these last four statements just above the final Else statement in the script.
Okay, now we have added the reporting logic to our game and it's ready to go. Save it and then give it a whirl.
'************************************************************************* 'Script Name: StarTrekQuiz.vbs 'Author: Jerry Ford 'Created: 11/17/02 'Description: This script creates a Star Trek Quiz game. '************************************************************************* 'Perform script initialization activities Option Explicit Dim PlayGame, SplashImage, AnswerOne, AnswerTwo, AnswerThree, AnswerFour Dim AnswerFive, NumberCorrect, FederationRank, FsoObject, ScoreRpt Const cTitlebarMsg = "The Star Trek Quiz Game" Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject") 'Start the user's score at zero NumberCorrect = 0 'Display the splash screen and ask the user if he or she wants to play SplashImage = space(11) & "********" & vbCrLf & _ " ******************" & space(20) & "**************************" & _ space(20) & vbCrLf & _ "*" & space(35) & "*" & space(18) & "**" & space(46) & "*" & vbCrLf & _ " ******************" & space(20) & "*************************" & vbCrLf & _ space(31) & "******" & space(26) & "***" & vbCrLf & _ space(34) & "******" & space(22) & "***" & vbCrLf & _ space(37) & "******" & space(17) & "***" & vbCrLf & _ space(26) & "****************************" & vbCrLf & _ space(26) & "******************************" & vbCrLf & _ space(26) & "*****************************" & vbCrLf & _ space(26) & "****************************" & vbCrLf & vbCrLf & vbCrLf &_ space(10) & "Would you like to boldly go where no one has gone before?" PlayGame = MsgBox(SplashImage, 36, cTitlebarMsg) If PlayGame = 6 Then 'User elected to play the game Set ScoreRpt = FsoObject.OpenTextFile("C:TempStarTrekQuiz.txt", 2, "True") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine("Star Trek Game Quiz") ScoreRpt.Write("===================================================") ScoreRpt.WriteLine("===================================================") ScoreRpt.WriteBlankLines(2) 'Ask the first question AnswerOne = InputBox("What was the Science Officer's name in the "& _ "original Start Trek series?", cTitlebarMsg) ScoreRpt.Write("1. What was the Science Officer's name in the original") ScoreRpt.WriteLine("Start Trek series?") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: "& AnswerOne) ScoreRpt.WriteBlankLines(1) If LCase(AnswerOne) = "spock" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.WriteLine("The correct answer is spock") End If ScoreRpt.WriteBlankLines(2) 'Ask the second question AnswerTwo = InputBox("What Star Trek villain appeared in both the "& _ "original series and a Star Trek movie?", cTitlebarMsg) ScoreRpt.Write("2. What Star Trek villain appeared in both the original") ScoreRpt.WriteLine(" series and a Star Trek movie??") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: "& AnswerTwo) ScoreRpt.WriteBlankLines(1) If LCase(AnswerTwo) = "khan" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.WriteLine("The correct answer is khan") End If ScoreRpt.WriteBlankLines(2) 'Ask the third question AnswerThree = InputBox("What was the numeric designation of Voyager's "& _ "onboard Borge?", cTitlebarMsg) ScoreRpt.Write("3. What was the numeric designation of Voyager's") ScoreRpt.WriteLine("onboard Borge?") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: "& AnswerThree) ScoreRpt.WriteBlankLines(1) If CStr(AnswerThree) = "7" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") ElseIf CStr(AnswerThree) = "7 of 9" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.WriteLine("The correct answer is either 7 or '7 of 9'") End If ScoreRpt.WriteBlankLines(2) 'Ask the fourth question AnswerFour = InputBox("Name the only Star Trek character to regularly "& _ "appear on 2 series and at least 2 Star Trek movies?", cTitlebarMsg) ScoreRpt.Write("4. Name the only Star Trek character to regularly") ScoreRpt.WriteLine("appear on 2 series and at least 2 Star Trek movies?") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: "& AnswerFour) ScoreRpt.WriteBlankLines(1) If LCase(AnswerFour) = "worf" Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.WriteLine("The correct answer is worf") End If ScoreRpt.WriteBlankLines(2) 'Ask the fifth question AnswerFive = InputBox("What is the last name of your favorite "& _ "Captain?", cTitlebarMsg) ScoreRpt.WriteLine("5. What is the last name of your favorite Captain?") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine(" Your Answer: " & AnswerFive) ScoreRpt.WriteBlankLines(1) If Len(AnswerFive) > 3 Then If Instr(1, "kirkpicardsiscojanewayarcher", LCase(AnswerFive), 1) <> 0 Then NumberCorrect = NumberCorrect + 1 ScoreRpt.WriteLine(" Correct") Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.Write("The correct answer is either kirk, picard, sisco,") ScoreRpt.WriteLine(" janeway or archer") End If Else ScoreRpt.Write(" Incorrect - ") ScoreRpt.Write("The correct answer is either kirk, picard, sisco, janeway") ScoreRpt.WriteLine(" or archer") End If ScoreRpt.WriteBlankLines(2) ScoreRpt.Write("===================================================") ScoreRpt.WriteLine("===================================================") ScoreRpt.WriteBlankLines(1) 'Determine the user's rank based on the number of correct answers Select Case NumberCorrect Case 5 'User got all five answers right FederationRank = "Admiral" Case 4 'User got 4 or 5 answers right FederationRank = "Captain" Case 3 'User got 3 of 5 answers right FederationRank = "Commander" Case 2 'User got 2 of 5 answers right FederationRank = "Lieutenant-Commander" Case 1 'User got 1 of 5 answers right FederationRank = "Lieutenant" Case 0 'User did not get any answers right FederationRank = "Ensign" End Select 'Tell the user how he or she scored MsgBox "You answered "& NumberCorrect & "out of 5 correct." & vbCrLf & _ vbCrLf & "Your Star Fleet rank is : "& FederationRank, , cTitlebarMsg ScoreRpt.WriteLine("Overall score: "& NumberCorrect & "out of 5 correct") ScoreRpt.WriteBlankLines(1) ScoreRpt.WriteLine("Federation Rank: "& FederationRank) ScoreRpt.Close() Else 'User doesn't want to play MsgBox "Thank you for taking the Star Trek Quiz Jerry Ford 2002." & _ vbCrLf & vbCrLf & "Live long and prosper!", , cTitlebarMsg WScript.Quit() End If
This chapter covered a lot of ground. You learned how to use the If and Case Select statements in a number of different ways. Using this new information, you updated the Rock, Paper, and Scissors game and created the Start Trek Quiz game. In addition, you leaned how to create VBScripts that could generate reports and log files.
Part I - Introducing the WSH and VBScript
Part II - Learning VBScript & WSH Scripting
Part III - Advanced Topics
Part IV - Appendices