Chapter 4. Implementing Conditional Logic

As has already been demonstrated in each of the game scripts that you have worked on in this book, it is virtually impossible to create Ruby scripts of any level of complexity without performing some degree of conditional analysis. This analysis might involve examining things like player input or the value of a randomly generated number. To perform this analysis, Ruby provides you with access to a number of conditional expressions, modifiers, and logical operators that you can use to compare different values and control the logical execution of different script statements. This will allow you to create Ruby scripts that are capable of altering their execution based on the data that they are presented with and will result in scripts that are adaptive and handle many different types of situations. In addition to showing you how to apply conditional logic within your Ruby scripts, this chapter will show you how to create your next computer game, the Ruby Typing Challenge game.

Specifically, you will learn how to:

  • Work with if expressions and modifiers

  • Work with unless expressions and modifiers

  • Use the case block to compare one condition against a range of values

  • Use different logical operators to perform different types of comparisons

  • Use the ternary operator to perform conditional analysis

Project Preview: The Ruby Typing Challenge Game

In this chapter, you will learn how to create a new computer game called the Ruby Typing Challenge game. This Ruby script will demonstrate how to apply conditional logic to analyze user input through the development of a computer typing test that evaluates the player’s typing skills.

The Ruby Typing Challenge game begins displaying a welcome screen as shown in Figure 4.1.

The welcome screen for the Ruby Typing Challenge game.

Figure 4.1. The welcome screen for the Ruby Typing Challenge game.

Next, the game prompts the player for permission to begin the test as demonstrated in Figure 4.2. The player is instructed to respond with a y/n answer.

Player confirmation is required to begin taking the test.

Figure 4.2. Player confirmation is required to begin taking the test.

If the player decides not to take the typing test, the screen shown in Figure 4.3 displays and the game will end once the player presses the Enter key.

The player has elected not to take the test.

Figure 4.3. The player has elected not to take the test.

If, on the other hand, the player elects to take the typing test, the instructions shown in Figure 4.4 display.

Instructions provide the player with information needed to understand how to take the test.

Figure 4.4. Instructions provide the player with information needed to understand how to take the test.

Next, the first of a series of five sentences is presented as demonstrated in Figure 4.5. In response, the player must type the sentence exactly as shown and then press the Enter key.

An example of one of the Ruby Typing Test game’s typing challenges.

Figure 4.5. An example of one of the Ruby Typing Test game’s typing challenges.

As soon as the player presses the Enter key, the game analyzes the player’s input to determine whether it exactly matches the game’s sentence. If the player’s input is identical to the game’s sentence, the screen shown in Figure 4.6 displays. If the player makes one or more typing mistakes, a different message displays notifying the player that she has failed to correctly type the sentence.

The player has correctly typed the challenge sentence.

Figure 4.6. The player has correctly typed the challenge sentence.

The game’s sentences grow longer as the test progresses. Once the player has typed in all five sentences, the game analyzes the player’s score and displays a message indicating whether or not the player has passed the test as demonstrated in Figure 4.7.

To pass the test the player must correctly type at least three sentences.

Figure 4.7. To pass the test the player must correctly type at least three sentences.

Once the player presses the Enter key, the screen showing the score is dismissed. Finally, a message displays thanking the player for taking the time to take the typing test as shown in Figure 4.8.

The game ends after thanking the player for taking the time to play.

Figure 4.8. The game ends after thanking the player for taking the time to play.

Using Conditional Logic to Create Adaptive Scripts

Using Ruby, you can create scripts that consist of a series of statements that are executed in sequential order, one after the other, without any alteration in the logical flow of the scripts. However, while this approach may work well with small scripts that perform simple tasks, scripts that process sequentially are not well suited to tasks that involve any level of complexity. For example, as you have already seen in all the game scripts that you have worked on in this book, some level of conditional execution is almost always required. This execution might involve prompting the player for permission to play a game and then either ending or continuing the game based on an analysis of the player’s response.

People use conditional logic all the time. Therefore, from a programming standpoint, it is a relatively easy concept to understand. For example, every morning people around the globe awake and must make a decision as to whether or not to go to work. Based on that decision, different courses of action must be taken. For example, take a look at Figure 4.9, which visually outlines the conditional logic involved in selecting from two alternatives.

Choosing between different courses of action.

Figure 4.9. Choosing between different courses of action.

This same basic logic can easily be applied to the development of a computer program or script. For example, take a look at Figure 4.10.

A graphical representation of the conditional logic used to determine whether or not to start game play.

Figure 4.10. A graphical representation of the conditional logic used to determine whether or not to start game play.

Hint

Hint

Figures 4.9 and 4.10 are both examples of simple flowcharts. A flowchart is a tool used to graphically represent some or all of a script’s logical flow. Flowcharts are often created by programmers to outline the overall design of the logic involved in designing a computer program or script prior to beginning work on it. By first creating a flowchart, programmers provide themselves with a high-level outline of the overall logic involved. This gives programmers the ability to focus on the overall process required to create the program and helps to identify logical errors in the program’s design before investing time in program development and testing.

Flowcharts are often used in large projects involving the combined efforts of many programmers. Once created, flowcharts can be used to identify different parts of a program or project, making the division of work easier while also helping to ensure that each programmer has a good understanding of how the part of the program or project he is assigned fits into the overall scheme of things.

As you can see, Figure 4.10 outlines two separate and distinct courses of action, of which only one will be followed, based on the user’s response as to whether or not to begin game play. The logic outlined in the flowchart can be directly translated into script statements, as demonstrated here:

puts "Would you like to play a game? (y/n) "
answer = STDIN.gets
answer.chop!

if answer == "n"
  puts "Sorry to hear that. Please return and play again soon."
else
  puts "OK, let's play!"
  .
  .
  .
end

Here, the puts method is executed and passed a text string that is used to display a message that prompts the player to respond with a value of y or n to indicate whether to continue game play. The player indicates her decision by keying in the appropriate response and pressing the Enter key.

The key point to understand regarding the application of conditional programming logic is that when it comes right down to it, all that is happening is an evaluation of whether a tested condition is true or false. Based on the result of the analysis, the appropriate set of program statements is then executed.

Ruby provides programmers with access to several ways of applying conditional logic, each of which is designed to address a specific type of situation. A list of available options for applying conditional logic is outlined here.

  • The if modifier. A conditional evaluation appended to the end of Ruby statements to conditionally control the execution of the statement.

  • The unless modifier. A conditional evaluation appended to the end of Ruby statements that performs the opposite type of evaluation as the if modifier.

  • The if expression. Used to create complex conditional evaluations spread out over multiple lines.

  • The unless expression. Used to create complex conditional evaluations spread out over multiple lines that perform the opposite type of evaluation as an if expression.

  • Case. A conditional evaluation that performs a series of conditional tests, each of which is compared to a single value.

  • The Ternary Operator. An operator that facilitates the inclusion of a conditional expression within another statement.

Performing Alternative Types of Comparisons

Up to this point in the book, all the comparison operations that have been demonstrated have used the == comparison operator. Like other modern programming languages, Ruby provides programmers with access to a range of comparison operators. For example, instead of setting up a comparison test that evaluates whether one value is equal to another, you might want to know whether one value is greater than or less than another value. This type of analysis uses comparison operators. Table 4.1 provides a list of the comparison operators supported by Ruby.

Table 4.1. Ruby Comparison Operators

Operator

Description

==

Equal

!=

Not equal

<

Less than

<=

Less than or equal to

>

Greater than

>=

Greater than or equal to

The rest of this chapter will provide you with examples of how to work with the comparison operators shown in Table 4.1.

Conditional Logic Modifiers

One quick and easy way that Ruby allows you to integrate conditional logic into your Ruby scripts is through the use of conditional logic modifiers. Using Ruby’s modifiers, you can append a conditional check onto the end of other Ruby statements to control the conditional execution of the statement.

The if Modifier

Using the if modifier, you can attach a conditional test to the end of a Ruby statement to control the execution of that statement. This conditional test consists of the if keyword followed by an expression formulated using a comparison operator as demonstrated in the following example.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

puts "You must be 18 or older to play this game!" if answer.to_i < 18

Here, the user is prompted to specify her age. The value of the number that is supplied by the user is then analyzed to determine whether it is less than 18. If it is, the puts statement to which the modifier has been appended is executed. However, if the number entered by the user is 18 or greater, the execution of the puts statement is skipped.

An advantage of appending conditional modifiers to the end of script statements is that it helps you to write compact script statements and thus to reduce the overall size of your script files. A disadvantage of this approach is that modifiers only work with individual statements. If you need to control the execution of multiple lines of code, you will be better off using conditional expressions as demonstrated later in this chapter.

The unless Modifier

As an alternative to the if modifier, you might want to use the unless modifier. The unless modifier is the logical opposite of the if modifier. As such, there is nothing that you can accomplish using the unless modifier that you cannot accomplish with the if modifier. Therefore, its use is really just a matter of preference.

To see the unless modifier in action, take a look at the following example.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

puts "You must be 18 or older to play this game!" unless answer.to_i > 17

As you can see, this example is nearly identical to the previous example, except instead of using the if modifier, the unless modifier has been substituted. In addition, the less than comparison operator was replaced with the greater than operator and the number 18 has been replaced with the number 17. Both this and the preceding example produce the same result.

Working with if and unless Expressions

Using if and unless expressions, you can spread out conditional statements over multiple lines, making these forms of conditional tests even more powerful than their modifier equivalents. As such, you can use conditional expressions to group together and control the execution of large numbers of statements, making your scripts easier to read and maintain.

Building if Expressions

Unlike if modifiers, if expressions are capable of controlling the execution of more than one statement, making them even more powerful and useful. The if expression supports a very flexible syntax that provides the ability to use the expression in a number of different ways. A high-level outline of the if expression’s syntax is provided here:

if condition then
  statements
elsif condition then
  statements
.
.
.
else
  statements
end if

condition represents an expression that is to be tested. statements represents one or more script statements that are to be conditionally executed. elsif represents an option keyword that when used allows additional conditional tests to be performed. else is another optional keyword that when specified allows you to identify an alternate set of programming statements that are to be executed when none of the preceding conditions that have been tested evaluates as being true.

Replacing if Modifiers with if Expressions

To better understand how to work with this powerful and extremely useful expression, you need to see examples of it in action. Earlier in this chapter, the following example was presented to demonstrate the use of the if modifier.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

puts "You must be 18 or older to play this game!" if answer.to_i < 18

Using the if expression, this example could be rewritten as shown here.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

if answer.to_i < 18 then
  puts "You must be 18 or older to play this game!"
end

As you can see, this version of the example is more longwinded than the if modifier example. However, as demonstrated in the next code block, you can use the if expression to include any number of statements inside the opening if and closing end statements, allowing the conditional execution of any number of statements.

if answer.to_i < 18
  puts "You must be 18 or older to play this game!"
  puts "Goodbye."
  exit
end

Hint

Hint

Note the use of the exit method in the previous example. The exit method is provided by the kernel class. This method forces the immediate termination of a Ruby script.

Creating Single-Line if Expressions

As has been stated, the syntax support of the if expression is very flexible, allowing for many formats. For example, the following example demonstrates how to format an if expression that fits on a single line.

x = 10
if x == 10 then puts "x is equal to 10" end

When used in this format, the if expression is very similar to the if modifier, except that in the case of the if modifier, the conditional logic that is executed is appended to the end of the statement instead of being defined at the beginning of the statement as demonstrated here.

x = 10
puts "x is equal to 10" if x == 10

Providing an Alternative Course of Action

In addition to executing one or more script statements when a test condition evaluates as being true, you can modify an if expression to execute one or more statements in the event the test condition evaluates as being false. To accomplish this, you need to add the optional else keyword to the expression as demonstrated here.

x = 10
if x == 10 then
  puts " x is equal to 10"
else
  puts " x does not equal 10"
end

Here, either of two puts statements executes depending on whether or not the value assigned to x is equal to 10.

Checking for Alternative Conditions

There will be times when you will need to examine a series of conditions to find out which one of them evaluates as being true. One way of accomplishing this is to define a series of statements as demonstrated here.

if x == 10 then puts "x is 10"  end
if x == 15 then puts "x is 15"  end
if x == 20 then puts "x is 20"  end
if x == 25 then puts "x is 25"  end

The objective of these statements is to find out which of four possible values has been assigned to x. If you prefer, you could use the if expression’s optional elsif keyword to rewrite this example as shown here.

if x == 10 then puts "x is 10"
elsif x == 15 then puts "x is 15"
elsif x == 20 then puts "x is 20"
elsif x == 25 then puts "x is 25"
end

Hint

Hint

If you need to execute more than one statement when a matching condition is found, you would need to reformat the previous example as shown here.

if x == 10 then
  puts "x is 10"
elsif x == 15 then
  puts "x is 15"
elsif x == 20 then
  puts "x is 20"
elsif x == 25 then
  puts "x is 25"
end

You could also include the optional else keyword to provide an alternative course of action should none of the preceding tests evaluate as being true.

if x == 10 then puts "x is 10"
elsif x == 15 then puts "x is 15"
elsif x == 20 then puts "x is 20"
elsif x == 25 then puts "x is 25"
else puts "The value of x is unknown"
end

Trick

Trick

If you want to save a few keystrokes when keying in your script statements, Ruby allows you to replace the then keyword with the : character as demonstrated here.

if x == 10 : puts "x is 10"
elsif x == 15 : puts "x is 15"
elsif x == 20 : puts "x is 20"
elsif x == 25 : puts "x is 25"
end

Creating unless Expressions

Just like the if modifier and the unless modifier, the unless expression is the polar opposite of the if expression. As such, there is nothing that you can accomplish with an if expression that you cannot accomplish with an unless expression. For example, take a look at the following if expression.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

if answer.to_i < 18
  puts "You must be 18 or older to play this game!"
end

To convert it to an unless expression, all you need to do is replace the if keyword with the unless keyword and then replace the < operator with the > operator as shown here. Also note that the number 18 has been replaced with the number 17.

print "Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!

unless answer.to_i > 17
  puts "You must be 18 or older to play this game!"
end

Obviously, when it comes right down to it, the decision whether to use an if expression or an unless expression is really just a matter of personal preference.

Using Case Blocks to Analyze Data

In addition to the if and unless modifiers and expressions, Ruby also provides you with access to the case block as a means of comparing a series of expressions against a single expression to see whether any of the expressions being evaluated result in equivalent value. Although you can accomplish the same thing using an if expression that includes a series of elsif statements, the case block is better suited for situations where you need to compare a single condition to a whole range of possible matches. The syntax for the case block is outlined here:

case expression
  when value
    statements
       .
       .
       .
  when value
    statements
  else
    statements
end

As you can see, the case block includes one or more when statements. The expression that is evaluated is compared to the value associated with one or more when statements. If a match occurs with one of the with statements, any statements associated with that when statement are executed. If none of the when statements matches the value of the expression being evaluated, the statements belonging to the optional else statement (if present) are executed.

Trick

Trick

As is the case with the if expression, you can replace the then keyword with a colon (:).

As a quick example of how to set up a case block, take a look at the following statements.

x = 10

case x

  when 1
    puts "*"
  when 5
    puts "*****"
  when 10
    puts "**********"
  else
    puts "No stars"

end

Here, the value assigned to x is compared to a series of values specified in a case block. Since the value of x is 10, the puts "**********" will be executed. Had none of the when statements contained a matching value, the puts statement associated with the else keyword would have executed. In most cases, you will find that it takes fewer lines of code to set up a case block than an equivalent if expression using multiple elsif keywords.

If you want, you can omit the specification of an expression on the open case statement when setting up a case block as demonstrated here.

puts "
Welcome to the vacation calculator!

"

print "How many years have you worked for the company? 

: "
answer = STDIN.gets
answer.chop!
answer = answer.to_i

case
  when (answer.between?(1, 5))
    puts "You are entitled to 1 week of vacation per year."
  when (answer.between?(6, 10))
    puts "You are entitled to 2 weeks of vacation per year."
  when (answer.between?(11, 15))
    puts "You are entitled to 3 weeks of vacation per year."
  when (answer.between?(16, 20))
    puts "You are entitled to 4 weeks of vacation per year."
  else
    puts "You are entitled to 5 weeks of vacation per year."
End

Here, a series of unique expressions has been specified for each when statement. The statements belonging to the first expression that evaluates as true will be executed and the rest of the statements are skipped.

Trick

Trick

Note the use of the between? method in each of the expressions in the previous example. Each of Ruby’s numeric classes supports this method, which returns a value of true or false depending on whether or not a number is within a specified range.

Using the Ternary Operator

Ruby provides you with an additional option, known as the ternary operator (?:), available for setting up conditional logic. Using the ternary operator, you can evaluate the value of two different expressions and make variable assignments as a result of that comparison. The syntax required to work with the ternary operator is

variable = expression ? true_result : false_result

Here, variable is assigned the value returned by the statement. expression represents the expression that is evaluated. true_result is the value that is assigned if the expression evaluates as true and false_result is the value returned if the expression evaluates as being false. To get a better understanding of how to work with the ternary operator, take a look at the following example.

print "

Enter your age and press Enter:  "
answer = STDIN.gets
answer.chop!
answer = answer.to_i

result = answer < 18 ? "denied!" : "approved!"

puts "

Your access has been " + result + "

"

Here, the user is prompted to enter her age. The statement that contains the ternary operator evaluates the expression answer < 18. If the user enters a value of 17 or less, the expression evaluates as true, and a value of "denied!" is assigned to a variable named result. On the other hand, if the user enters a value that is 18 or higher, the expression evaluates as being false and a value of "approved!" is assigned to result.

Nesting Conditional Statements

Some situations require more complicated analysis than can be accomplished using an individual conditional modifier expression. In these situations, you may need to perform one conditional evaluation based on the result of another evaluation. One way of addressing this type of challenge is to embed one conditional statement inside another through a process called nesting. To get a better understanding of how nesting works, take a look at the following example.

redStatus = "Go"
blueStatus = "Go"
greenStatus = "Go"

if redStatus == "Go" then
  if blueStatus == "Go" then
    if greenStatus == "Go" then
      puts "All systems are go. Prepare for launch!"
    end
  end
end

Here, a series of three if expressions has been set up. If the first expression evaluates as false, the remaining if expressions are skipped. Otherwise, the second if expression is executed. If the second if expression proves false, the third if expression is skipped. Otherwise, it is executed. Nesting also works just as effectively for unless expressions.

Trap

Trap

Although there is no limitation on how deeply you can nest conditional statements within one another, going more than two or three deep will result in script code that is difficult to read and maintain.

Combining and Negating Logical Comparison Operations

Like most modern programming languages, Ruby also supports the use of a number of logical, or Boolean, operators. These operators are listed in Table 4.2.

Table 4.2. Ruby Boolean Operators

Operator

Type

Example

and

Evaluates as true if both comparisons evaluate as true

x > 1 and x < 10

&&

Evaluates as true if both comparisons evaluate as true

x > 1 && x < 10

or

Evaluates as true if either comparison evaluates as true

x = 1 or x = 10

||

Evaluates as true if either comparison evaluates as true

x = 1 || x = 10

not

Reverses the value of a comparison

not (x > 5)

!

Reverses the value of a comparison

! (x > 5)

As you can see, the and and && operators are essentially identical. The only difference between the two is that the and operator has a higher level of precedence than the && operator. Likewise, the or and || operators work identically, the only difference being precedence, with or having higher precedence than ||. The and and && operators evaluate the second operand only if the first operand is true. The or and || operators evaluate the second operand only if the first operand is false.

To get a better understanding of how to work with these operators, let’s look at a few examples. For starters, take a look at the following statements.

print "Enter your age and press Enter:  "
reply = STDIN.gets
reply.chop!
reply = reply.to_i

puts "You are eligible to play this game!" if reply >= 18 && reply <= 65

Here, the if modifier at the end of the last statement uses the && operator to determine whether the value assigned to reply is both greater than or equal to 18 and less than or equal to 65. If both expressions evaluate as true, the puts statement executes. Otherwise, the puts statement is skipped.

Hint

Hint

If you want, you can enclose expressions within parentheses to make things easier to understand as demonstrated here:

puts "You are eligible to play this game" if (reply >= 18) && (reply <= 65)

Next, let’s look at an example that uses the || operators.

print "What is your rank?: "
rank = STDIN.gets
rank.chop!
rank = rank.to_i

puts "Access is permitted." if rank == 1 || rank == 3

Here, the last statement shown above uses the || operator to determine if the value assigned to rank is equal to 1 or to 3. If either (or both) or these expressions proves true, the associated puts statement executes. If neither expression proves true, the puts statement is skipped.

This final example demonstrates how to work with the ! operator, which negates or reverses the value returned from a conditional expression.

randomNo = 1 + rand(10)

print "What number am I thinking of? 

:  "
answer = STDIN.gets
answer.chop!

puts "Wrong! My number was " + randomNo.to_s if ! (answer.to_i == randomNo)

Here, a random number between 1 and 10 is generated using the rand method and assigned to a variable named randomNo. The user is then prompted to try and guess the randomly generated number. The player’s answer is then converted to an integer and compared to the value or randomNo. If these two values are not equal, the associated puts statement executes. Otherwise, it does not execute.

Back to the Ruby Typing Challenge Game

Okay, now it is time to turn your attention back to the development of this chapter’s game project, the Ruby Typing Challenge game. As you work on creating this script, focus on the conditional expression to control the script’s overall controlling logic and its use in evaluating the accuracy of the player’s typing.

Designing the Game

The development of the Ruby Typing Challenge game will be completed in 13 steps as outlined here.

  1. Open your text or script editor and create a new file.

  2. Add comment statements to the beginning of the script file to document the script and its purpose.

  3. Define a Screen class representing the console window.

  4. Define a Test class representing the typing test.

  5. Develop a method in the Test class that displays a greeting message.

  6. Develop a method in the Test class that displays test instructions.

  7. Develop a method in the Test class that presents typing challenge sentences.

  8. Develop a method in the Test class that displays test results.

  9. Initialize script objects.

  10. Prompt the player for permission to start the typing test.

  11. Develop the overall programming logic responsible for analyzing the player response.

  12. Manage early game termination.

  13. Execute methods required to deliver the typing test.

Remember to follow along carefully and not to skip any steps or parts of steps as you work your way through.

Step 1: Creating a New Ruby File

The first step in creating the Ruby Typing Challenge game is to open your text or code editor and create a new Ruby script file. Assign the script a filename of TypingChallenge.rb and save it in the folder where you have decided to store all your Ruby script files.

Step 2: Documenting the Script and Its Purpose

Now that you have created a new script file, the next step is to add the following comment statements to it. These statements document the name of the script and its purpose.

#--------------------------------------------------------------------------
#
# Script Name: TypingChallenge.rb
# Version:     1.0
# Author:      Jerry Lee Ford, Jr.
# Date:        October 2007
#
# Description: This Ruby script demonstrates how to apply conditional logic
#              in order to analyze user input and control script execution
#              through the development of a computer typing test that
#              evaluates the player's typing skills.
#
#--------------------------------------------------------------------------

Step 3: Defining a Class Representing the Console Window

Now it is time to define the first of two new classes. The first class is named Screen. This is accomplished by adding the following statements to the end of the script file.

# Define custom classes ---------------------------------------------------

#Define a class representing the console window
class Screen
  def cls  #Define a method that clears the display area
    puts ("
" * 25)  #Scroll the screen 25 times
    puts "a"  #Make a little noise to get the player's attention
  end

  def pause    #Define a method that pauses the display area
    STDIN.gets  #Execute the STDIN class's gets method to pause script
                #execution until the player presses the Enter key
  end

end

The first method defined in the class is the cls method. The method contains two statements. The first statement writes 25 blank lines to the console window to clear the screen. The second statement processes a string that contains the a escape character, in order to play an audible beep sound, notifying the player each time the terminal screen is cleared.

Step 4: Defining a Class Representing the Typing Test

The next step in the development of the Ruby Typing Challenge game is to begin the definition of a new class that will represent the game’s typing test. This is accomplished by adding the following statements to the end of the script file. This class will be named Test and will eventually be populated with four methods.

#Define a class representing the typing test
class Test

end

Step 5: Defining the display_greeting Method

Now it is time to begin developing the methods belonging to the Test class. The script statements that make up this class’s first method are shown here and should be inserted in between the class’s opening and closing statements.

#This method displays the 8-ball greeting message
def display_greeting

  Console_Screen.cls  #Clear the display area

  #Display a welcome screen
  print "		 Welcome to the Ruby Typing Challenge game!" +
  "












Press Enter to " +
             "continue. 

: "

Console_Screen.pause       #Pause the game

end

This method, named display_greeting, is responsible for displaying the game’s welcome screen.

Step 6: Defining the display_instructions Method

The script statements for the Test class’s next method are shown here and should be added to the end of the class definition, immediately following the previously defined method.

#Define a method to be used to present test instructions
def display_instructions

  Console_Screen.cls       #Clear the display area
  puts "			Instructions:

"  #Display a heading

  #Display the game's instructions
  puts %Q{    This test consists of a series of 5 typing challenges.
  Each challenge sentence is presented one at a time. To respond
  correctly, you must retype each sentence exactly as shown and press
  the Enter key. Your grade will be displayed at the end of the test.
  









  Press Enter to continue.

}

  Console_Screen.pause       #Pause the game

End

This method, named display_instructions, is responsible for displaying a text string containing instructions for playing the game.

Step 7: Defining the present_test Method

The script statements for the Test class’s third method are shown here and should be added to the end of the class definition.

#Define a method to be used to present typing challenges
def present_test(challenge)

  Console_Screen.cls       #Clear the display area
  print challenge + "

: "  #Display the challenge sentence
  result = STDIN.gets  #Collect the player's input
  result.chop!         #Remove the end of line marker

  #Analyze the player input and see if it is correct
  if challenge == result then

    #Keep track of the number of correctly retyped challenge sentences
    $noRight += 1
    Console_Screen.cls       #Clear the display area
    #Keep the player informed
    print "Correct!

Press Enter to continue."
    Console_Screen.pause       #Pause the game

  else

    Console_Screen.cls       #Clear the display area
    #Keep the player informed
    print "Incorrect!

Press Enter to continue."
    Console_Screen.pause       #Clear the game

  end

end

This method, named present_test, is responsible for displaying sentences passed to it as string arguments and for collecting and storing player input. Next, an if expression has been set up to analyze the player’s input to see whether it matches the original sentence. If the player input matches the original sentence, the value of $noRight is incremented by one to keep track of the number of correctly typed sentences. In addition, a text string is displayed that notifies the player of the match.

If, on the other hand, the player makes a typing mistake when keying in the sentence, the value of $noRight is not incremented and a different text string is displayed, notifying the player of her mistake.

Step 8: Defining the determine_grade Method

The script statements for the Test class’s final method are shown here and should be added to the end of the class definition.

#Define a method to be used to display test results
def determine_grade

  Console_Screen.cls       #Clear the display area

  #To pass the test the player must correctly retype 3 sentences
  if $noRight >= 3 then

    #Inform the player of the good news
    print "You retyped " + $noRight.to_s + " sentence(s) correctly. "
    puts "You have passed the typing test!

Press Enter to continue."

  else  #The player has failed the test

    #Inform the player of the bad news
    print "You retyped " + $noRight.to_s + " sentence(s) correctly. "
    puts "You have failed the typing test!

Press Enter to continue."

  end

end

This method, named determine_grade, is responsible for determining whether the player has passed the typing test. To pass, the player must correctly type in at least three sentences. To determine the player’s score, an if expression has been set up to evaluate the value assigned to $noRight to see if it is greater than or equal to three. If it is, a text string is displayed notifying the player that she has passed.

If, on the other hand, the value of $noRight is not greater than or equal to three, the else portion of the if expression is executed, informing the player that she has failed the test.

Step 9: Initializing Script Objects

Now it is time to initialize instances of both the Screen and the Test classes. This is accomplished by adding the following statements to the end of the script file.

# Main Script Logic -------------------------------------------------------

# Initialize global variable that will be used to keep track of the number
#of correctly retyped sentences
$noRight = 0

Console_Screen = Screen.new  #Instantiate a new Screen object
Typing_Test = Test.new        #Instantiate a new Test object

#Execute the Test object's display_greeting method
Typing_Test.display_greeting

In addition to instantiating the Console_Screen and Typing_Test objects, these statements initialize a global variable named $noRight, which will be used to keep track of the number of correctly typed sentences and also execute the Test class’s display_greeting method.

Step 10: Getting Permission to Begin the Test

The next step in the development of the Ruby Typing test game is to add programming logic that prompts the player for permission to start the test. This is accomplished by adding the following statements to the end of the script file.

#Execute the Screen object's cls method in order to clear the screen
 Console_Screen.cls

#Prompt the player for permission to begin the test
print "Would you like to test your typing skills? (y/n)

: "

answer = STDIN.gets  #Collect the player's response
answer.chop!  #Remove any extra characters appended to the string

#Loop until the player enters y or n and do not accept any other input.
until answer == "y" || answer == "n"

  Console_Screen.cls  #Clear the display area

  #Prompt the player for permission to begin the test
  print "Would you like to test your typing skills? (y/n)

: "

  answer = STDIN.gets  #Collect the player's response
  answer.chop!  #Remove any extra characters appended to the string

end

Step 11: Developing the Controlling Logic Required to Administer the Test

At this point, all that remains to be done is to develop the controlling logic responsible for analyzing the player’s response when prompted for permission to begin the test. This is accomplished by adding the following statements to the end of the script file.

#Analyze the player's response
if answer == "n"  #See if the player elected not to play

else  #The player wants to take the test

end

The code statements from the next step will need to be embedded into the first part of the above if expression and the statements from the last step will need to be embedded at the end of the if expression (between the else and end statements).

Step 12: Managing Early Game Termination

This next set of script statements is executed in the event the player responds with a value of n when prompted for permission to start the typing test and therefore should be placed in between the opening if statement and the else statement that you added to the script in the previous step.

Console_Screen.cls  #Clear the display area

#Invite the player to return and play again
puts "Okay, perhaps another time.

"

These statements clear the screen and then display a text message encouraging the player to return and take the test at another time.

Step 13: Executing the Typing Test

This final set of script statements is responsible for administering the typing test and should be embedded into the bottom half of the if expression that you added to the script file in step 11.

#Execute the Test object's display_instructions method
Typing_Test.display_instructions
#Display typing challenges and grade each answer by calling on the
#Test object's present_test method
Typing_Test.present_test "In the end there can be only one."
Typing_Test.present_test "Once a great plague swept across the land."
Typing_Test.present_test "Welcome to Ruby Programming for the Absolute" +
" Beginner."
Typing_Test.present_test "There are very few problems in the world " +
"that enough M&Ms cannot fix."
Typing_Test.present_test "Perhaps today is a good day to die. Fight " +
"beside me and let us die together."

#Notify the player of the results by executing the Test object's
# determine_grade method
Typing_Test.determine_grade

Console_Screen.pause       #Pause the game

Console_Screen.cls  #Clear the display area
#Thank the player for taking the typing test
puts "Thank you for taking the Ruby Typing Challenge.

"

As you can see, these statements consist of a series of calls to methods belonging to the Typing_Test and Console_Screen objects. The first method that is called is the display_instructions method. This is followed by five separate calls to the present_test method. Each of these calls passes a different text string to the method, which displays the sentence and then prompts the player to retype it. Next, the determine_grade method is called. This method determines whether the player passed or failed the test. Finally, the screen is cleared and a message is displayed thanking the player for taking time to play the Ruby Typing Challenge game.

Running Your New Ruby Script Game

All right! You now have everything that you need to build and execute the Ruby Typing Challenge game. Go ahead and save and then run your new Ruby script. As long as you have followed along carefully and have not mistyped anything or accidentally skipped the keying in of any statements, everything should work as advertised. In the event you run into any errors, carefully review them and look for clues regarding where things may have gone awry. If necessary, go back and review the entire script and look for mistyped or missing script statements.

Summary

In this chapter you learned different ways of implementing conditional logic in your Ruby scripts. This included learning how to work with if and unless modifiers and expressions. This chapter showed you how to use the ternary operator to perform conditional analysis. You also learned how to use the case statement to match one value up against a range of possible options and to use different types of logical operations to perform different types of comparisons. Last, you learned how to combine and negate logical comparison operations using Ruby Boolean operators.

Now, before you move on to Chapter 5, “Working with Loops,” I suggest you set aside a little extra time to make a few improvements to the Ruby Typing Challenge game by implementing the following list of challenges.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset