Lawrence Technological University
College of Arts and Science
Department of Mathematics and Computer Sciences

### Ruby Demonstration with Mr. Stanford Henry for Communication Media Arts, Spring 2011

This is a version of an old game program that asks the capitals of the states in the U.S.A. The game is constructed in the same way you might have made it with blank 3 × 5 cards. Here is the outline of our pattern:

1. Prepare the cards by writing the question (the name of the state) on the front and writing the answer (the corresponding capital city) on the back.
2. Shuffle the deck of cards.
3. Set the score to zero.
4. Pick up each card in turn and ask the question from the front of the card. The response will be one of these four possibilities
• If the player is tired of the game then just stop,
• otherwise if the player has no clue then show them the correct answer and go on to the next card,
• otherwise if the player gives the correct answer then acknowledge the correct answer and add 1 to the score and go on to the next card,
• otherwise the answer must be wrong so admonish the user and deduct 1 from the score and read the same question again.
5. Display the score.

This problem is made easier by using a few programming concepts:

• Storing key-value (or question-answer) pairs in hashes or associative arrays. The more familiar sort of array is subscripted by a number like, a0 or `a[0]`. If we have an array or a list of flash cards, then we would like to be able to find the value or answer of "Lansing" by writing an expression with the subscript or key of "Michigan" like, cardsMichigan or `cards["Michigan"]`.
• Randomness can make a game more fun. Putting the deck of flash cards in a random order can be done with a single method in Ruby, `shuffle`. The `rand` method produces a random number. If `bads` is a list of negative remarks that the student programmer can customize, `bads[rand bads.size]` would select one of those insults at random.
• "Here" documents are chunks of text between matching tags that are to be displayed just as they are typed. e.g. Consider the list of the rules of our game:
```<<HELP_TEXT # HELP_TEXT is the opening tag.
Rules:
1. Answer "quit" to give up and exit the game.
...
5. There are #{cards.size} cards or questions in the flash card deck.
HELP_TEXT         # HELP_TEXT is the matching closing tag.
```
• String concatenation with the "+" builds longer strings out of shorter ones by joining them end-to-end. String interpolation with #{some-expression-with-variables} builds strings by inserting the result of some-expression-with-variables, inside the string. e.g. `5. There are #{cards.size} cards` will become `5. There are 50 cards` in our example. (You may notice that the "here" document is just another kind of string, i.e. Because `5. There are #{cards.size} cards` is written between the here document tags it will work just the same as if it were written between double quotes like, `"5. There are #{cards.size} cards"`.

A draft of our game in Ruby. Feel free to change it in any way you wish. When you make changes, please also make comments (sentences after a "#") to help those who come after to understand what you did and why you did it. Even though this is not an English class, please use proper spelling and punctuation and grammar in your comments. This demonstration was tested with Ruby 1.8.7 as it comes standard with OS X 10.6 Snow Leopard, and with Ruby 1.9.2 as installed on Windows with the Windows Installer from ruby-lang.org. During the Windows installation be sure and check the boxes for adding Ruby to the path for executables and for associating Ruby with the `.rb` and `.rbw` file extensions. To try this program out on Windows, copy `qanda.rb` below to Notepad and then save it as `qanda.rb` -- being sure to select "all files" instead of just ".txt" files as you click on the "Save" button so that the file is not accidentally saved as `qanda.rb.txt`. Then you can run the program simply by typing `qanda.rb` at the prompt in the Command Window followed by the "Enter" key.

```# qanda.rb
# A Ruby simulation of a deck of flash cards.
# The title for this deck:
title = "Know Your U.S. State Capitals"
# The question format:
question_format = "What is the capital of "
# The deck of cards can be expressed as a list of key => value pairs.
# "Montgomery" on the back of the card with "Alabama" on the front with
# the expression: cards["Alabama"]
cards = {
"Alabama" => "Montgomery",      "Montana" => "Helena",
"Arizona" => "Phoenix",	  "Nevada" => "Carson City",
"Arkansas" => "Little Rock",	  "New Hampshire" => "Concord",
"California" => "Sacramento",	  "New Jersey" => "Trenton",
"Colorado" => "Denver",	  "New Mexico" => "Santa Fe",
"Connecticut" => "Hartford",	  "New York" => "Albany",
"Delaware" => "Dover",	  "North Carolina" => "Raleigh",
"Florida" => "Tallahassee",	  "North Dakota" => "Bismarck",
"Georgia" => "Atlanta",	  "Ohio" => "Columbus",
"Hawaii" => "Honolulu",	  "Oklahoma" => "Oklahoma City",
"Idaho" => "Boise",		  "Oregon" => "Salem",
"Illinois" => "Springfield",	  "Pennsylvania" => "Harrisburg",
"Indiana" => "Indianapolis",	  "Rhode Island" => "Providence",
"Iowa" => "Des Moines",	  "South Carolina" => "Columbia",
"Kansas" => "Topeka",		  "South Dakota" => "Pierre",
"Kentucky" => "Frankfort",	  "Tennessee" => "Nashville",
"Louisiana" => "Baton Rouge",	  "Texas" => "Austin",
"Maine" => "Augusta",		  "Utah" => "Salt Lake City",
"Maryland" => "Annapolis",	  "Vermont" => "Montpelier",
"Massachusetts" => "Boston",	  "Virginia" => "Richmond",
"Michigan" => "Lansing",	  "Washington" => "Olympia",
"Minnesota" => "Saint Paul",	  "West Virginia" => "Charleston",
"Mississippi" => "Jackson",	  "Wisconsin" => "Madison",
"Missouri" => "Jefferson City", "Wyoming" => "Cheyenne"}
# Some help text:
help_text = <<HELP_TEXT
Rules:
1. Answer "quit" to give up and exit the game.
2. Answer "punt" to skip the question.
3. Each correct answer scores 1 point.
4. Each wrong answer loses 1 point.
5. There are #{cards.size} cards or questions in the flash card deck.
HELP_TEXT
# A list for negative feedback.
# Before starting, shuffle the order of questions (keys) in the card deck.
questions = cards.keys.shuffle
# Display welcome and brief instructions.
puts "Welcome to " + title + "!"
puts help_text
# Do the whole shuffled deck, one question at a time.
# Reset the score:
correct = 0
questions.each do |question|
print question_format + question + "? ==> "
# Get the answer from the keyboard and strip away extra spaces and
# ignore capitalization mistakes.
# Make the special case of Minnesota's capital a little more flexible.
end
# Use an if-else-if structure to handle the 4 mutually exclusive cases:
if answer == "quit"                          # 1. User giving up, so exit.
puts "Goodbye."
break # Skip the rest of the questions.
# Note: There are two ways to skip a question.
elsif answer == "punt" or answer.empty?      # 2. Punting, so next question.
puts "The correct answer is " + cards[question] + "."
elsif answer == cards[question].downcase     # 3. Correct, so next question.
puts "Correct!"