LEARN TO PROGRAM WITH SMALL BASIC: An Introduction to Programming with Games, Art, Science, and Math (2016)
6. GETTING USER INPUT
To perform useful tasks or give you useful information, some programs need input from you. For example, in Microsoft Word you enter text, click buttons to make it look good, and enter a filename to save it. In a web browser, you click links or enter a URL or search term to find a web page. In drawing programs, you draw by clicking and dragging the mouse. When you use a program and give it information that helps it do its job, that information is called user input.
Programs need a way to ask users for input, process that input, and respond correctly. Programs that do this are interactive. In this chapter, you’ll make your programs interactive by giving them the capability to accept and react to user input, which will be in the form of strings and numbers.
Talking to the Computer
Until now, all the information your programs needed was in the source code. For example, look at the program in Listing 6-1.
1 ' CircleArea.sb
2 radius = 5
3 area = 3.1416 * radius * radius
4 TextWindow.WriteLine("Area = " + area)
Listing 6-1: Finding the area of a circle
This program uses a fixed value of 5 for the radius in line 2. This is called hard-coded data. Hard-coded data is part of the program. If you want to change that data, you must change the source code. For example, to find the area of a circle using a different radius, you’d open the file, change the radius value in your code, save the file, and run the new code. It’s a pain to do this every time you want to change the value of a variable. And if you give this code to someone who doesn’t know how to program, it won’t be very useful.
Your Number, Please?
Clearly, it’d be best if you could calculate the area of any circle without having to change the source code. So let’s explore how to read values directly input by users. We want our program to ask the user to enter a value for the radius and then use that value in the calculation. To do this, you’ll use the TextWindow method ReadNumber(). Replace line 2 in Listing 6-1 with the following statement:
radius = TextWindow.ReadNumber()
When this statement runs, a flashing cursor appears in the text window, as shown in Figure 6-1. The cursor is the program’s way of saying, “It’s your turn to type. I’m waiting. Don’t make me come over there!”
Figure 6-1: Running the ReadNumber() method
When the user types a number and presses ENTER, the input is stored for the rest of the program to use. Whatever number the user entered is now stored in the radius variable.
Run the program and try to enter a character other than a number. What happens? The program won’t accept anything that’s not a number! That’s why the method is named ReadNumber().
Introducing Yourself to Your Computer
A program can also accept user input in the form of text, or strings. Let’s imagine we want to greet the player with their name. We’ll store the player’s name in a variable called userName but use a new TextWindow method called Read(). Run the following program, and enter your name when you see the cursor:
userName = TextWindow.Read()
TextWindow.Write("Hello " + userName + ". ")
TextWindow.WriteLine("It's really nice to meet you.")
The first statement accepts the text the user entered in the text window and stores that text in userName. The program then greets the user with their name.
So what’s the difference between Read() and ReadNumber()? Read() works exactly like ReadNumber(): they both show a flashing cursor and wait for the user to type input and press ENTER. In fact, you can even use Read() to get numbers from a user. But ReadNumber() will accept only a number from a user, so we recommend you use it when you need your user to enter a number.
Writing Prompts for Input
A flashing cursor without instructions doesn’t tell your user what kind of data to input (like a number, a name, an address, or favorite type of monkey). Unless your program is written for a magician or a mind reader like Professor X, you should provide some instructions before you allow your program to accept input from Read() or ReadNumber(). To do this, you’ll display a prompt, which is a message that tells the user what kind of data to enter.
From Listing 6-1, replace line 2 with these two lines:
TextWindow.Write("Please enter a radius; then press <Enter>: ")
radius = TextWindow.ReadNumber()
First, we call the Write() method and pass it a message to display. In this program, the message you pass is a prompt telling your user to enter a value for the radius and then press ENTER. You end the prompt with a colon to show the user that the program’s waiting for keyboard input. (You don’t need the colon, but it’s clearer to your user.) Use Write() instead of WriteLine() to keep the cursor on the same line as the prompt. After you call Write(), you call ReadNumber() to accept the number input by the user and store it in the variable radius.
After adding these two statements, run your program to see something like Figure 6-2.
Figure 6-2: The text window waiting for input from your user
When Small Basic runs the statement radius = TextWindow.ReadNumber(), it waits for the user to enter a number and press ENTER. The program won’t read what the user types until they press ENTER. When the user presses ENTER, the program grabs the user input and assigns it to the radiusvariable. The program then continues with the statement after the ReadNumber() method.
Now that you’ve accepted the radius from your user, all that’s left is to compute the area and display the result. Listing 6-2 shows the complete program.
1 ' CircleArea3.sb
2 TextWindow.Write("Please enter a radius; then press <Enter>: ")
3 radius = TextWindow.ReadNumber()
5 area = 3.1416 * radius * radius
6 TextWindow.WriteLine("Area = " + area)
Listing 6-2: Letting the user enter the radius
Let’s see what the output looks like if you enter a radius of 8:
Please enter a radius; then press <Enter>: 8
Area = 201.0624
Try it out for yourself!
A Moment of Silence, Please (Pause)
At times you may need to display some instructions to your user (like explaining the rules of Hide and Go Tickle) and then wait for them to read those instructions. For example, you might display the instructions followed by “Press any key to continue ...” and then wait for the user to press a key to show that they’re ready to continue. You can do this by using the Pause() method.
To see this method in action, let’s write a program that converts the computer into a wisdom machine. Each time the user presses a key, the computer displays a new bit of wisdom. The program is shown in Listing 6-3.
1 ' WisdomMachine.sb
2 TextWindow.WriteLine("WISDOM OF THE DAY")
4 TextWindow.WriteLine("A friend in need is a friend indeed.")
7 TextWindow.WriteLine("A hungry man is an angry man.")
10 TextWindow.WriteLine("Love your enemies. They hate that.")
Listing 6-3: Demonstrating the Pause() method
After showing the first wise saying (line 4), the program calls Pause() to give the user time to read it (line 5). This call displays “Press any key to continue ...” and waits for the user to press a key. When the user presses a key, the program displays the next bit of wisdom (line 7) and pauses again (line 8). The program continues to do this until the last statement is executed. Add more wise sayings to this program, and then share it with someone!
What if you want to display a statement other than “Press any key to continue ...,” such as “Press any key to see the next line of wisdom ...”? Well, Small Basic provides you with the PauseWithoutMessage() method for this purpose. You can write a custom prompt using Write() orWriteLine() as usual, and then call PauseWithoutMessage() to wait for the user. Try it out. Replace the calls to Pause() in lines 5 and 8 of Listing 6-3 with these statements:
TextWindow.WriteLine("Press any key to see the next line of wisdom...")
Your program runs the same way as before but uses a more descriptive prompt.
Working with User Input
Let’s put your new knowledge to use by writing a couple of programs that read input from a user, process the input, and display the output back to the user.
Converting Fahrenheit to Celsius
Next, you’ll create a program that converts a temperature from degrees Fahrenheit to degrees Celsius. The program prompts the user for the temperature in Fahrenheit and then converts it to Celsius using this formula:
C = (5 ÷ 9) × (F – 32)
Run the program in Listing 6-4 several times to see how it works. To use the degree symbol, press and hold the ALT key, type 248 on your numeric keypad, and then release the ALT key.
1 ' Fahrenheit2Celsius.sb
2 TextWindow.Write("Enter a temperature in °F: ")
3 F = TextWindow.ReadNumber()
4 C = (5 / 9) * (F - 32)
5 C = Math.Round(C) ' Rounds to nearest integer
6 TextWindow.WriteLine(F + " °F = " + C + " °C")
Listing 6-4: Converting Fahrenheit to Celsius
First, the program prompts the user to enter a temperature. When they press ENTER, their input is assigned to the variable F. Your program then converts the value stored in F to Celsius and stores the result in variable C (which is all done in line 4). Next, the program uses Math.Round() on line 5 to take the current value of C, round it to the nearest integer, and store the rounded value in C, which replaces the old value of C. You’ll learn more about the Round() method in Chapter 7, but we use it here to make the program’s output easier to read. Finally, your program displays the output (line 6).
TRY IT OUT 6-1
Try to guess what the following program does. Run it to check your answer:
TextWindow.Write("How old are you? ")
age = TextWindow.ReadNumber()
TextWindow.WriteLine("In ten years, you'll be " + (age + 10))
TextWindow.WriteLine("Wow! You'll be so old!")
Let’s write a program that finds the average of four numbers provided by the user. There are a couple of ways to do this; the first is to use five variables, as shown in Listing 6-5.
1 ' Avg1.sb
2 TextWindow.Write("Enter 4 numbers. ")
3 TextWindow.WriteLine("Press <Enter> after each one:")
4 n1 = TextWindow.ReadNumber()
5 n2 = TextWindow.ReadNumber()
6 n3 = TextWindow.ReadNumber()
7 n4 = TextWindow.ReadNumber()
8 avg = (n1 + n2 + n3 + n4) / 4
9 TextWindow.WriteLine("Average = " + avg)
Listing 6-5: Finding the average of four numbers
Look at the output when we enter 10, 20, 15, and 25:
Enter 4 numbers. Press <Enter> after each one:
Average = 17.5
The program prompts the user to enter four numbers and press ENTER after each number. It reads these numbers, one by one, and saves them in four variables: n1, n2, n3, and n4 (lines 4–7). It then computes the average of these numbers, saves the average in the variable avg (line 8), and displays the result (line 9).
Listing 6-6 shows a different way to write this program. Enter this program, and then run it. This time you’ll use just one variable named sum.
1 ' Avg2.sb
2 TextWindow.Write("Enter 4 numbers. ")
3 TextWindow.WriteLine("Press <Enter> after each one:")
4 sum = TextWindow.ReadNumber()
5 sum = sum + TextWindow.ReadNumber()
6 sum = sum + TextWindow.ReadNumber()
7 sum = sum + TextWindow.ReadNumber()
8 TextWindow.WriteLine("Average = " + (sum / 4))
Listing 6-6: Finding the average of four numbers using an accumulator
To understand how the program works, let’s say the user entered the numbers 10, 20, 15, and 25 in response to the prompt. So, in line 4, sum becomes 10. In line 5, the second number (20) is added to the first number (10) and saved to the sum variable (totaling 30). In lines 6–7, the third number (15) and fourth number (25) are added and saved to sum (totaling 70). The program then displays the average, which is sum / 4, to the user (line 8).
Because of how the sum variable keeps adding input to itself (or accumulating), it’s known as an accumulator (also known as a running sum). (This might be similar to how you accumulate hairbands or Pokémon cards, but these numbers only take up computer memory and don’t clutter your room.)
Next, let’s write a simple program that makes silly sentences using the words in Shakespeare’s famous quote: “To be or not to be: that is the question.” You’ll ask the user to enter two verbs and a noun, and then you’ll use these entries to replace the words be, be, and question in Shakespeare’s quote. Listing 6-7 shows the complete program.
1 ' Silly.sb
2 TextWindow.Write("Please enter a verb: ")
3 verb1 = TextWindow.Read()
5 TextWindow.Write("Please enter another verb: ")
6 verb2 = TextWindow.Read()
8 TextWindow.Write("Now, please enter a noun: ")
9 noun = TextWindow.Read()
11 TextWindow.Write("To " + verb1)
12 TextWindow.Write(" or not to " + verb2 + ":")
13 TextWindow.Write(" that is the " + noun + ".")
Listing 6-7: Silly Shakespeare lines
When we ran this code, we entered eat, swim, and cow. This is the output:
Please enter a verb: eat
Please enter another verb: swim
Now, please enter a noun: cow
To eat or not to swim: that is the cow.
Try it out, and then come back. We’ll wait. Are you back? Was your output funnier than ours? Well, go show someone!
TRY IT OUT 6-2
Write an interactive Mad Libs–style program in which you ask the user to enter the name of their favorite princess (such as Snow White), something evil, the name of a school for princesses, something yummy, a name for a short wizard, something so valuable that they’d never sell it, a verb, small creatures, and a superhero’s power.
Then display the following story for the user, and replace the bracketed terms with the user’s input:
“Princess [PrincessName] was traveling through the forest when suddenly the evil [SomethingEvil] jumped out at her and offered her an apple. Princess [PrincessName] refused, because her mother sent her to [NameOfSchool], where she learned that you don’t take unwrapped food from strangers (it could be poisoned). So Princess [PrincessName] continued through the woods until she came upon a house made of [SomethingYummy]! Not wanting to damage private property, she kept walking. Next, Princess [PrincessName] came upon a spinning wheel where a short man named [ShortWizard’sName] tempted her to use a magic spinning wheel to make gold (in exchange for her [SomethingValuable]). But Princess [PrincessName]’s mother had already told her that an evil fairy had cast a spell on her when she was a baby and that she’d [Verb] forever if she pricked her finger on a spinning wheel. So Princess [PrincessName] kept walking and arrived safely home to a cottage with seven [SmallCreatures], where she locked herself in her room for the rest of her life because she had the power of [SuperHeroPower].”
Then make your own interactive story program with a new character (like a hero, ninja, pirate, or My Little Pony), and share it!
If you get stuck, check out http://nostarch.com/smallbasic/ for the solutions and for more resources and review questions for teachers and students.
1. Using Small Basic, you can easily turn your computer into a number wizard! Open the file Magician.sb from this chapter’s folder and run it. Explain how the program works.
2. Make a silly Mad Libs–style game using the phrase, “One man’s trash is another man’s treasure.” Another version of the phrase is, “One man’s loss is another man’s gain.” For your version, ask the user for two living creatures and two different nouns. Then have your program output in this format: “One [Creature1]’s [Noun1] is another [Creature2]’s [Noun2].”
3. Eve’s mom is having a garage sale. Because Eve wants to earn some money, she sets up a table to sell lemonade, cookies, and her homemade greeting cards as the customers come up the driveway (she’s a genius salesperson, so she sells a lot). Help Eve count the money her customers give her by creating a program that asks Eve to enter the number of dollars, quarters, dimes, nickels, and pennies she earned. Then have it convert them into a total dollar amount, and display that amount in dollars and cents (like $23.34). Try your program using the following amounts to make sure it works:
a. 35 dollars, 3 quarters, 3 pennies
b. 2 dollars, 1 quarter, 2 pennies
c. 10 dollars, 1 nickel, 3 pennies
d. 6 dollars, 1 quarter, 3 pennies
e. 3 dollars, 2 quarters, 1 dime, 1 nickel, 3 pennies
f. 1 dollar, 2 dimes, 1 nickel, 4 pennies