String Processing - Learn to Program with Scratch: A Visual Introduction to Programming with Games, Art, Science, and Math (2014)

Learn to Program with Scratch: A Visual Introduction to Programming with Games, Art, Science, and Math (2014)

Chapter 8. String Processing

A string is a series of characters that is treated as a single unit. You can write programs to combine, compare, sort, encrypt, and otherwise manipulate strings. Here’s what you’ll learn in this chapter:

§ How Scratch stores strings

§ How to use the string manipulation blocks available in Scratch

§ Several string processing techniques

§ How to write interesting programs that process strings

We’ll start with a detailed look at the string data type, and then we’ll write procedures to manage and manipulate strings. Those procedures will remove and replace characters, insert and extract substrings, and randomize character order. After that, we’ll use these procedures and apply these techniques to write some fun and practical applications.

Revisiting the String Data Type

As I mentioned in Chapter 5, Scratch has three data types: Boolean, number, and string. At its simplest, a string is just an ordered sequence of characters. These characters can include letters (both upper- and lowercase), digits, and other symbols that you can type on your keyboard (+, -, &, @, and so on). You can use strings in your programs to store names, addresses, phone numbers, book titles, and more.

In Scratch, the characters of a string are stored sequentially. For example, if you have a variable called name, executing the command set name to Karen would store the characters as illustrated in Figure 8-1.

A string is stored as a sequence of characters.

Figure 8-1. A string is stored as a sequence of characters.

You can access individual characters of a string with the letter of operator. For example, the block letter 1 of name returns the letter K, and letter 5 of name returns the letter n. Scratch also provides the length of operator, which returns the number of characters in a string. If you use these two operators with repeat blocks, you can count characters, examine multiple characters, and do many other useful things, as I’ll demonstrate in the following subsections.

Counting Special Characters in a String

Our first example script, shown in Figure 8-2, counts how many vowels are in an input string. It asks the user to enter a string, and then it counts and displays the number of vowels in that string.

VowelCount.sb2

Vowel-counting program

Figure 8-2. Vowel-counting program

The program checks each letter in the input string one by one and looks for vowels. Every time it finds a vowel, it increments a variable named vowelCount by 1. The script uses a variable named pos (short for position) to track the position of the character being checked. Let’s explore this script in more detail.

First, the script asks the user to enter a sentence ①. Scratch should save the user’s string automatically in the built-in answer variable. Then it sets vowelCount to 0 (since it hasn’t seen any vowels yet) and sets pos to 1 to access the first letter of the input string.

Next, a repeat loop ② checks every letter in the input string. The length of operator reports the number of characters in the input string, which is how many times the loop should repeat.

On each pass, the loop uses ch (short for character) to check one character of the input string ③. In the first iteration of the loop, ch is set to the first letter of answer. The second iteration sets ch to the second letter, and so on, until the loop reaches the end of the string. The pos variable is used to access the desired character.

The if block then checks whether the examined character is a vowel ④. If the character is a vowel, whether capital or lowercase, vowelCount is increased by 1.

After checking one character, the loop increments pos by 1 ⑤ and starts over to read the next character. When all the letters in the input string have been checked, the loop terminates, and the program displays the number of vowels it counted using the say block.

The techniques used in this example will be applied many times in the rest of this chapter. Load the script VowelCount.sb2, run it several times, and make sure you understand it thoroughly.

Comparing String Characters

Our second example checks whether an integer entered by the user is a palindrome. A palindrome is a number (or text string) that reads the same backward and forward. For example, 1234321 and 1122332211 are palindromes. Likewise, Racecar, Hannah, and Bob are a few text palindromes. To illustrate our palindrome-testing algorithm, let’s say that the input number is 12344321, as illustrated in Figure 8-3.

Palindrome.sb2

Using two variables to check whether or not a number is a palindrome

Figure 8-3. Using two variables to check whether or not a number is a palindrome

To check whether the number is a palindrome, we need to compare the first and eighth digits, the second and seventh digits, the third and sixth digits, and so on. If any comparison produces a false result (meaning that the two digits are not equal), then the number is not a palindrome. A program that implements this palindrome test algorithm is shown in Figure 8-4.

This program tests whether an integer input by the user is a palindrome.

Figure 8-4. This program tests whether an integer input by the user is a palindrome.

The script accesses the digits to be compared with two variables (pos1 and pos2 in Figure 8-3) that move in opposite directions. The first variable (pos1) starts at the first digit and moves forward, while the second variable (pos2) starts at the last digit and moves backward. The number of required comparisons is at most one-half the digits in the input number. With an input of 12344321, we need at most four comparisons because the input number has eight digits. (The same logic applies if the input integer has an odd number of digits, since the digit in the middle of the number need not be compared.) Once the program determines whether or not the user’s number is a palindrome, it displays a message with the result.

TRY IT OUT 8-1

Load Palindrome.sb2 and run it to understand how it works. Because of the way Scratch handles decimal repeat counts, if the input number has an odd number of digits, the script performs one extra comparison of the two digits that surround the middle digit. Try to fix the program to perform the correct number of repeats when the input number has an odd number of digits.

Palindrome.sb2

In the next section, we’ll explore some of the most common operations on strings and see some strategies for writing string manipulation procedures in Scratch.

String Manipulation Examples

The letter of operator only lets you read the individual characters of a string. If you want to insert characters into (or remove characters from) a string, you have to do all the work yourself.

In Scratch, you can’t alter the characters in a string, so the only way to change a string is to create a new one. For example, if you want to capitalize the first letter in the string “jack”, you need to create a new string that contains the letter J followed by the rest of the letters, ack. The idea is to use the letter of operator to read the letters of the original string and append theses letters to the new string, as needed, using the join operator.

In this section, we’ll develop some simple applications that demonstrate common string manipulation techniques.

Igpay Atinlay

What if our sprites could speak a secret language? In this section, we’ll teach them a coded language called pig latin. Our rules for creating pig latin words will be simple. To convert a word into pig latin, move the first letter to the end and add the letters ay. So, the word talk becomes alktay,fun becomes unfay, and so on. Now that you know the rules, can you tell what the title of this section originally said?

PigLatin.sb2

The strategy we’ll use to convert a word into pig latin is illustrated in Figure 8-5, using the word scratch.

How to translate an English word into pig latin

Figure 8-5. How to translate an English word into pig latin

We’ll first append all the letters (except the first), one by one, from the input word to the output word ①. We then add the first letter in the input word to the output ②, followed by ay ③. Our PigLatin procedure that implements these steps is shown in Figure 8-6.

The procedure uses three variables to create our coded words. The variable outWord holds the output string as it’s assembled. A counter called pos (for position) tells the script which character from the original string to append to outWord. Finally, a variable named ch holds one character from the input string. The procedure takes the word you want to translate into pig latin as a parameter, named word.

The PigLatin procedure

Figure 8-6. The PigLatin procedure

First, the procedure creates an empty string for outWord and sets pos to 2 ①. (An empty string is string that does not contain any characters; its length is 0.) The procedure then uses a repeat block to append all letters but the first from the input string (word) to the output string (outWord) ②. We skipped the first character, so the repeat count is one less than the length of the input string. For each loop iteration, one character of word is appended to outWord. At the end of the loop, the first letter of word is appended to outWord ③, along with the letters ay ④.

TRY IT OUT 8-2

Load PigLatin.sb2 and run it to test this procedure. The application asks for an input word and then says its pig latin translation. Modify it to translate a phrase, like “Would you like some juice?” into pig latin. (Hint: Call PigLatin for each word to assemble the output phrase.) As another challenge, write a procedure that takes a pig latin word as input and shows its original English word.

PigLatin.sb2

Fix My Spelling

In this section, we’ll develop a simple game that generates misspelled words and asks the player to enter the correct spelling. The game will create misspelled words by inserting a random letter at a random position in an English word. Of course, there could be more than one correct spelling of misspelled simple words. For example, if the original word is wall and the game produces mwall, either mall or wall would be correct. To keep our game simple, we’ll ignore that possibility and insist on a particular spelling for the correct answer.

FixMySpelling.sb2

First, let’s make a general procedure to insert characters at a specific position in a string. This procedure, called Insert, takes three parameters: the input word (strIn), the string (or character) to insert (strAdd), and the position where you want those new characters (charPos). The procedure generates a new string (strOut) with strAdd inserted into strIn at the correct position, as illustrated in the example of Figure 8-7.

Illustrating the Insert procedure

Figure 8-7. Illustrating the Insert procedure

We’ll add the characters from strIn, one by one, into strOut. When we reach charPos, we’ll just add the character(s) from strAdd to strOut before appending the letter at charPos from strIn. The complete procedure is shown in Figure 8-8.

The Insert procedure

Figure 8-8. The Insert procedure

First, the procedure initializes strOut to an empty string and sets pos to 1 to access the first letter of the input string ①. It then starts a repeat loop to append the letters of strIn, one by one, to strOut ②. Each iteration grabs the next letter of strIn and places it in the ch variable ③. If the position of the current character matches charPos, the procedure appends strAdd to strOut ④. In all cases, ch is appended to strOut ⑤, and pos is incremented to access the next letter of strIn ⑥.

Now that we have our Insert procedure, let’s look at the main script of the game, shown in Figure 8-9.

The main script for the Fix My Spelling game

Figure 8-9. The main script for the Fix My Spelling game

The alpha string contains all the letters of the alphabet. It will provide the random letter to insert into the word we want to misspell ①. The script randomly picks a word from a premade list and saves that word as inWord ②. You’ll learn more about lists in the next chapter; for now, just think of this list as a word bank. The script then selects a random letter (randChar) from alpha ③ and a random position (randPos) to place this letter into inWord ④. The script then calls our Insert procedure to create the misspelled word (strOut) ⑤. After that, the script starts a loop to get the player’s answer ⑥. Inside the loop, the script asks the player to enter the correct spelling ⑦, and it uses an if/else block to check the answer ⑧. If the player’s answer matches the original word (inWord), the game ends; otherwise, the player has to try again.

TRY IT OUT 8-3

Load FixMySpelling.sb2 and play it several times to understand how it works. Can you modify the game such that the corrupt word contains two additional letters instead of just one?

FixMySpelling.sb2

Unscramble

Our last example presents another word game that is a little more challenging to play. We’ll start with an English word, scramble its letters, and ask the player to guess the original word.

Unscramble.sb2

Let’s start by creating a procedure that rearranges the characters of a given string in random order. The caller sets the input string (strIn), and the procedure, named Randomize, modifies it so that its characters are shuffled around, as illustrated in Figure 8-10.

Illustrating the Randomize procedure

Figure 8-10. Illustrating the Randomize procedure

We’ll pick a random letter from strIn and append that letter to a temporary string, str1. (This temporary string, which starts off empty, is where we’ll store the scrambled word as we build it.) We’ll then remove that letter from strIn so we don’t reuse it and repeat the whole process untilstrIn is empty. The Randomize procedure implements these steps as shown in Figure 8-11.

The Randomize procedure

Figure 8-11. The Randomize procedure

First, Randomize sets len to the length of the input string, strIn, and empties the temporary string, str1 ①. The procedure then starts a repeat loop to assemble the scrambled word ②. The repeat count equals the length of the input string. For each loop iteration, we pick a random position in strIn ③ and append that letter to str1 ④. Note that we used length of in step ③ because strIn and its length will change inside the loop. After that, we call a procedure named Remove to delete the character we just used from strIn ⑤. When the loop finishes shuffling letters around, strIn is set to the scrambled word (str1) ⑥.

The Remove procedure, which lets us avoid adding the same letter to our scrambled word twice, is shown in Figure 8-12. It removes a character from strIn at the position you specify with the charPos parameter.

The Remove procedure

Figure 8-12. The Remove procedure

This procedure uses another temporary string, named str2, to build the new string we want to create. It starts by emptying str2 and setting a loop counter, n, to 1 to access the first character of strIn ①. The procedure then starts a repeat loop to assemble the output string ②. If we don’t want to delete the current character, we append it to str2 ③. The loop counter is then incremented to access the next letter of strIn ④. When the procedure finishes, strIn is set to the new word (str2) ⑤.

Now we are ready to explore the main script of the game, shown in Figure 8-13.

The main script of the Unscramble game

Figure 8-13. The main script of the Unscramble game

The script selects a word randomly from a list and saves that word in inWord ①. It then sets strIn equal to inWord ② and calls Randomize to shuffle the characters of strIn ③. After that, the script starts a loop to get the player’s answer ④. Inside the loop, the script asks the player to enter the unscrambled word ⑤ and uses an if/else block to check that answer ⑥. This part is identical to what we did in the Fix My Spelling game in the previous section.

The previous examples were just a small set of the different operations you can do on strings. Try using the same techniques to change strings in your own projects!

In the rest of this chapter, we’ll explore some programs that use strings to solve interesting problems.

Scratch Projects

The procedures you just saw demonstrated the basics of processing strings. In this section, we’ll apply what we’ve learned to write several practical applications. Along the way, you’ll learn some new programming tricks that you can use in your own creations.

Shoot

This game is intended to teach the concept of relative motion in a fun and engaging way. The object of the game is to estimate the turn angle and moving distance between two objects on the Stage. The user interface for the game is illustrated in Figure 8-14.

Shoot.sb2

The user interface of the Shoot game

Figure 8-14. The user interface of the Shoot game

When the game starts, it positions the Player and the Target sprites at random locations on the Stage. Next it prompts the player to estimate the turn angle and the distance the Player sprite would need to move to hit the Target. The Player sprite is then moved according to the numbers entered by the player. If the sprite stops within a certain radius of the Target, the player wins the game. Otherwise, the Player sprite returns to its initial position, and the player can try again. When the green flag icon is clicked to start the game, the Player sprite runs the script shown inFigure 8-15.

The Player sprite script that runs when the green flag icon is clicked

Figure 8-15. The Player sprite script that runs when the green flag icon is clicked

The script broadcasts NewGame to instruct the Helper sprite to assign new locations for the Player and the Target sprites ①. The Helper sprite runs a simple procedure (not shown) that updates the following five variables with random numbers that will keep Player and Target visible (and separated by a certain distance) on the Stage:

XPlayer and YPlayer

The x- and y-coordinates of the Player sprite

XTarget and YTarget

The x- and y-coordinates of the Target sprite

initAngle

The initial direction of the Player sprite

Once the script has new positions for Player and Target, it broadcasts StartGame to move the Target sprite to its new location ②. (The script for the Target sprite is not shown here.) Then the script enters an infinite loop to give the player multiple chances to hit the target ③. The loop will be terminated by a stop all command (in the CheckAnswers procedure) when the player hits the target.

Each loop iteration sets the initial position and direction of the Player sprite and clears all pen marks from the Stage ④ to delete the trace left behind from the previous guess. The script then broadcasts GetAnswers ⑤, and in response, the Helper sprite prompts the player to enter an answer, as shown in Figure 8-16. The Helper sprite then splits the answer into two parts (before and after the comma) and updates angle and distance accordingly. Follow along with the comments on Figure 8-16 to see how this script works.

The Player sprite is then moved, with its pen down, as directed by the player ⑥. This leaves a visual trace of the movement route that the player can use to refine his or her estimate for the next round.

The GetAnswers script

Figure 8-16. The GetAnswers script

Finally, the Player sprite executes the CheckAnswers procedure to see whether it is close enough to the target. The game ends only if the Player sprite comes within a very close distance of the target. Figure 8-17 shows how the Player sprite checks its distance from the target.

The Player sprite uses the distance to block to check how close it is to the Target sprite. If the distance is less than 20 steps, the game considers this a hit and says, “You won!” Otherwise, the shooting trial is considered a miss, the forever loop starts again, and the player gets another chance.

The CheckAnswers procedure of the Player sprite.

Figure 8-17. The CheckAnswers procedure of the Player sprite.

TRY IT OUT 8-4

Modify the Shoot game to keep track of the number of times it takes the player to hit the target and assign the player a score accordingly.

Binary to Decimal Converter

Binary (base-2) numbers have only two possible digits: 0 and 1. Most computers operate and communicate with binary numbers. Humans, however, prefer to work with numbers in the decimal (base-10) system. In this section, you’ll develop an application that converts binary numbers to their decimal equivalents. Later, you could use it as a game to test your ability to perform such conversions.

BinaryToDecimal.sb2

Let’s first discuss how to convert from binary to decimal. Figure 8-18 shows an example using the binary number 10011011.

Converting a binary number to a decimal number

Figure 8-18. Converting a binary number to a decimal number

All we have to do is multiply each binary digit by its corresponding positional value and add the resulting products. Positional values correspond to increasing powers of the base from right to left, with the first position having a power of 0. Since binary is base 2, the rightmost digit has a positional value of 20 = 1, so you’d multiply the digit by 1. You’d multiply the next digit by 21 = 2, the next by 22 = 4, and so on.

Figure 8-19 illustrates the user interface of the binary-to-decimal conversion application. The program asks the user to input an 8-bit binary number. It then shows the input number on the Stage with the Bit sprite, which uses two costumes to represent 0 and 1. The program also computes the equivalent decimal number, and the Driver sprite, which has a computer costume, displays that value to the user.

Binary-to-decimal conversion program

Figure 8-19. Binary-to-decimal conversion program

TRY IT OUT 8-5

To check your understanding, practice the following binary-to-decimal conversions: (a) 1010100, (b) 1101001, and (c) 1100001.

The program starts when the green flag icon is clicked. This event is trapped by the Driver sprite, which executes the script shown and described in Figure 8-20.

The script for the Driver sprite

Figure 8-20. The script for the Driver sprite

This script prepares the Stage and asks the user to input a binary number so the Bit sprite can begin a new round of conversion. When the Bit sprite completes its work, the Driver sprite shows the user the decimal value, which is computed and stored by the Bit sprite in a shared variable named decimal.

The script that the Bit sprite runs in response to the Initialize message is illustrated in Figure 8-21.

The Initialize script for the Bit sprite

Figure 8-21. The Initialize script for the Bit sprite

This script draws a bit pattern representing eight zeros on the Stage. As you’ll see in a moment, wherever a binary 1 appears in the user’s input string, the script should stamp a costume of digit 1 over the corresponding bit. When the user enters the binary number to be converted, the Bitsprite should receive the BinaryToDecimal message and execute the script shown in Figure 8-22.

The BinaryToDecimal script for the Bit sprite

Figure 8-22. The BinaryToDecimal script for the Bit sprite

First, the conversion procedure initializes all of the variables it will use ①:

§ length is the number of bits in the user’s binary number.

§ pos points to the rightmost digit of the input number.

§ weight starts at the positional value of the rightmost binary digit.

§ decimal is set to 0 but will hold the result of the conversion at the end.

§ xPos begins at the x-coordinate of the image of the rightmost binary digit.

Inside the repeat loop ②, the procedure checks each digit to see whether it is a 1 or a 0. If the loop finds a 1 ③, it adds the current value of weight to decimal and stamps the digit-1 costume on top of the digit-0 image.

At the end of the loop, the script updates several variables before moving to the next iteration:

§ pos is updated to point to the digit to the left of the one we just processed.

§ xPos is aligned with the center of the image of the next digit, just in case we need to stamp a new image.

§ weight is multiplied by 2, which means it will take on the values 1, 2, 4, 8, 16, and so on as the loop iterates.

TRY IT OUT 8-6

Make the Driver sprite validate the number entered by the user before broadcasting the BinaryToDecimal message to the Bit sprite. You should verify that (1) the number entered by the user is a binary number (that is, it only contains ones and zeros) and (2) the length of the input is at most eight digits.

Hangman

In this section, we’ll write a classic Hangman game. Figure 8-23 shows the game in action.

Hangman.sb2

The user interface for the Hangman game

Figure 8-23. The user interface for the Hangman game

The program randomly selects a secret six-letter word and shows one question mark for each letter. The player has eight chances to guess the letters in the word. If the player guesses a letter correctly, the program shows all occurrences of that letter in the secret word. Otherwise, the program shows a new part of a hanging figure (the head, body, left arm, and so on). After eight wrong guesses, the program finishes the figure, and the player loses the game. If the player guesses the secret word in eight attempts or fewer, the result is victory. This application has the following four sprites:

Driver This sprite hides itself when the game starts, prompts the player to enter guesses, and processes the player’s answers. When the game ends, the sprite shows one of the following two costumes:

image with no caption

Hangman This sprite displays the evolving image of the hangman. It has a total of nine costumes, each one showing an additional part of the hangman’s body, as depicted in Figure 8-24.

The nine costumes of the Hangman sprite

Figure 8-24. The nine costumes of the Hangman sprite

New This sprite displays the New button on the Stage.

Helper This invisible sprite displays the letters guessed by the player as well as the number of remaining attempts. It uses seven variables with monitors configured as large displays and positioned at the correct locations on the Stage. Using a different sprite to update the display separates the game logic from the user interface. You can, for example, change this sprite to show more fancy letters on the Stage without affecting the rest of the application.

When the player presses the New sprite (the New button), it broadcasts a NewGame message to alert the Driver sprite that a new game has started. When the Driver sprite receives this message, it executes the script shown in Figure 8-25.

The NewGame script of the Driver sprite

Figure 8-25. The NewGame script of the Driver sprite

The script resets the game’s user interface ① and starts a loop ② to read in letter guesses. Another procedure called by the Driver sprite will terminate this loop via a stop all block when the game’s end condition is detected.

In each iteration of the loop, the Driver sprite asks the player to guess a letter and waits for input ③. When the player enters a guess, the script calls ProcessAnswer, which will update a flag (named gotLetter) to indicate whether the letter was right or wrong.

When ProcessAnswer returns, the script checks the gotLetter flag ④ and acts based on whether the player’s guess was correct or not. I’ll explain the procedures called by NewGame next, starting with the scripts in Figure 8-26.

Scripts triggered from the Initialize procedure

Figure 8-26. Scripts triggered from the Initialize procedure

During initialization, the Driver sprite hides itself, initializes displayWord to a string with six question marks, and sets remAttempts (how many guesses the player has left) to 8. It then selects the secretWord from a predefined list of six-letter words. Next the procedure broadcastsUpdate so the Helper sprite will assign its variables (whose monitors are visible on the Stage) to the correct values. The last instruction broadcasts the Reset message to the Hangman sprite. When the Hangman sprite receives this message, it switches to its start costume, which shows an empty gallows.

Now let’s consider a simple example to help us understand what the ProcessAnswer procedure does (see Figure 8-27). Assume the secret word is across and that this is the first round of the game (which means that displayWord is “??????”). If the player’s first guess is r, ProcessAnswershould set gotLetter to 1 to indicate a correct guess, set displayWord to “??r???” to show the letter’s position, and set qmarkCount (the number of question marks in the updated display string) to 5. When qmarkCount reaches 0, the player has guessed all the letters in the secret word.ProcessAnswer belongs to the Driver sprite, and you can see the full script in Figure 8-27 (left).

ProcessAnswer starts by resetting both the gotLetter flag and qmarkCount to 0. It will increase qmarkCount by 1 for every unknown letter in the secret word. The temporary variable, temp, which is used to construct the display string after every guess, is initialized to an empty string. The pos variable is used as a loop counter.

The ProcessAnswer procedure

Figure 8-27. The ProcessAnswer procedure

The loop examines each letter of secretWord, using pos as an index. If the examined letter (saved in char) equals the guessed letter (saved in Scratch’s built-in answer variable), the gotLetter flag is set to 1. Otherwise, the char variable is set to the letter at the corresponding position in the displayWord variable. Either way, the script adds char to the end of temp, as illustrated in Figure 8-27 (right).

When the loop terminates, the displayWord variable will contain the six letters to be displayed on the Stage, taking the user’s most recent guess into account. The loop also tracks the number of question marks in the display string. If there are none, then the user has successfully guessed the secret word.

When ProcessAnswer returns, the NewGame message handler checks gotLetter to see whether the player guessed correctly. If not, it will call ProcessWrongGuess, shown in Figure 8-28.

This procedure broadcasts WrongGuess to notify the Hangman sprite to show its next costume, and then it decrements the number of remaining guesses by 1. If the user is out of guesses, the script reveals the secret word and ends the game. Otherwise, it broadcasts an Update message to show how many trials the player has left.

The ProcessWrongGuess procedure

Figure 8-28. The ProcessWrongGuess procedure

If the player’s letter was correct, the ProcessCorrectGuess shown in Figure 8-29 should be called instead of ProcessWrongGuess.

The ProcessCorrectGuess procedure

Figure 8-29. The ProcessCorrectGuess procedure

ProcessCorrectGuess broadcasts Update to show the letter the player guessed correctly. It then checks the value of qmarkCount. If qmarkCount is 0, the player has guessed all of the letters correctly, so the Driver sprite shows its win costume and ends the game.

TRY IT OUT 8-7

The Hangman program doesn’t validate the user input; you could enter a non-alphabetic character or even an entire word. Modify the program so that it rejects any invalid input by the user.

Fraction Tutor

For our last example, we’ll present an educational game for teaching fractions. The interface for this game is shown in Figure 8-30. The player can select an operation (+, –, ×, or ÷) and click the New button to create a new problem. When the player enters an answer and clicks the Checkbutton, the Teacher sprite (image of a woman) checks that answer and provides an appropriate feedback message.

FractionTutor.sb2

The user interface for the Fraction Tutor application

Figure 8-30. The user interface for the Fraction Tutor application

The application contains six sprites. Operation allows the player to choose a mathematical operation. Read shows the answer entry button, New shows the New button, and Check shows the Check button. The Teacher sprite checks the player’s answer, and an invisible sprite named Digitstamps the numbers that correspond to the current problem on the Stage.

When the player clicks the New sprite (the New button), it executes the script shown in Figure 8-31. The script assigns random values between 1 and 9 to the numerator and denominator of both operands, which are represented by the four variables num1, den1, num2, and den2. It then broadcasts a NewProblem message to tell the Digit sprite to stamp these numbers on the Stage.

The script for the New sprite

Figure 8-31. The script for the New sprite

The Digit sprite has 12 costumes (named d1 through d12), as shown in Figure 8-32 (right). When this sprite receives the NewProblem broadcast, it stamps costumes representing the numerators and denominators of the two operands. Figure 8-32 also shows the procedure that does the actual stamping.

The function of the Digit sprite

Figure 8-32. The function of the Digit sprite

The procedure uses nested if/else blocks to determine which costume corresponds to the digit to be stamped. Note how the costume name for digits 1 through 9 is formed using the join operator. After switching to the correct costume, the Digit sprite moves to the specified (x,y) position and stamps the image of the costume at that location.

When the new problem is shown, the user can click the Read button to enter an answer. The script associated with this button is illustrated in Figure 8-33. The part of the script that parses the player’s answer into two tokens (numerator and denominator) is similar to the one presented inFigure 8-16 for extracting the angle and distance from answer in the Shoot game and, therefore, is not shown here. Check the FractionTutor.sb2 file for the complete procedure.

The script of the Read sprite

Figure 8-33. The script of the Read sprite

First, the user is asked to enter an answer in fraction form (for example, 3/5 or –7/8). The script then extracts the numerator and the denominator of the answer string (which are separated by the division sign) and assigns them to the num3 and den3 variables, respectively. For example, if the user enters –23/15, num3 will be set to –23 and den3 will be set to 15. After that, the script broadcasts a GotAnswer message to tell the Digit sprite to show the user’s answer on the Stage. When the Digit sprite receives this message, it stamps the digits of num3 and den3 at the correct positions on the Stage in the same way it displayed the numerators and denominators of the two operands. You can check the file FractionTutor.sb2 for the details.

After entering an answer, the user can click the Check button to see if the answer is correct. The script for the Check sprite broadcasts a CheckAnswer message to inform the other sprites of the user’s request. This message is trapped and processed by the Teacher sprite, which will execute the script shown in Figure 8-34.

The CheckAnswer script

Figure 8-34. The CheckAnswer script

The current costume of the Operation sprite tells which operation procedure (Add, Subtract, Multiply, or Divide) to execute ①. The operations take num1, den1, num2, and den2 as inputs and set the values of ansNum and ansDen, which represent the numerator and denominator of the correct answer, respectively. The four procedures are shown in Figure 8-35.

After finding the answer, CheckAnswer needs to put it in its simplest form. For example, 2/4 should be simplified to 1/2. To perform this reduction, the script first finds the greatest common divisor (GCD), also known as the greatest common factor, of the numerator and denominator ②. (We’ll look at this procedure in a moment.)

The Add, Subtract, Multiply, and Divide procedures of the Teacher sprite

Figure 8-35. The Add, Subtract, Multiply, and Divide procedures of the Teacher sprite

After finding the GCD, the script divides ansNum and ansDen by that value ③ and calls GiveFeedback ④ to display whether or not the user’s answer was correct.

Now let’s look more closely at the details of these procedures, starting with the four operation procedures shown in Figure 8-35.

These procedures compute the result of performing an operation of the form

image with no caption

and store the result in two variables (ansNum and ansDen) corresponding to the answer’s numerator and denominator, respectively.

Let’s now move on to the FindGCD procedure, shown in Figure 8-36.

The FindGCD procedure of the Teacher sprite

Figure 8-36. The FindGCD procedure of the Teacher sprite

Let’s trace the operation of FindGCD when num1 = –10 and num2 = 6. We need to find the largest positive integer that divides num1 and num2 without a remainder. The procedure starts by setting gcd, the result, to the lesser absolute value of the two numbers, –6 in our example. A loop then tests the numbers 6, 5, 4, and so on, until both num1 and num2 divide evenly by the checked number. This is the result we are after. In this example, gcd will be set to 2 since both numbers (–10 and 6) divide by 2 without a remainder.

The last procedure to examine is the GiveFeedback procedure, which compares the user’s answer with the correct answer and displays an appropriate message, as shown in Figure 8-37. The figure also shows some examples that demonstrate the different cases of the if/else structure.

The GiveFeedback procedure of the Teacher sprite

Figure 8-37. The GiveFeedback procedure of the Teacher sprite

TRY IT OUT 8-8

Modify the fraction tutor program to keep track of the number of correct and incorrect answers. Devise a scheme for calculating a score and showing it to the user.

Summary

String processing is an important programming skill. In this chapter, you learned how to access individual characters of a string to combine them, compare them, remove them, and shuffle them around.

We started with a detailed look at the string data type and how strings are stored as sequences of characters. We then wrote several procedures that demonstrated basic string manipulation techniques. After that, we used these techniques to write several interesting and practical applications. The concepts developed in these projects can be applied in many other areas, and I certainly hope they’ll help you think of your own projects.

In the next chapter, you’ll learn about lists and how to use them to store and manipulate a bunch of values. Equipped with this new data structure, you’ll have all the tools you need to write professional programs in Scratch.

Problems

Q:

1. Write a program that asks the user to enter a word and then says that word N times, where N is the number of letters in the input word.

Q:

2. Write a program that asks the user to enter a word. The program then determines the number of occurrences of the letter a in the input word.

Q:

3. Write a program that reads a singular English noun from the user. The program then produces the plural form of that noun. (Hint: Check the last letter and the second from the last letter of the input word.) To keep the program simple, consider only the following rule: If the word ends in ch, x, or s, add es for the plural, otherwise just add an s.

Q:

4. Write a program that reads a single character (between a and z) from the user and outputs the position of that character in the alphabet (a = 1, b = 2, c = 3, and so on). Uppercase letters and lowercase letters should be treated the same. (Hint: Define a variable named alpha that holds the letters of the alphabet, as we did in Figure 8-9, and then use a loop to find the position of the input character within the variable alpha.)

Q:

5. Write a program that asks the user to enter a letter of the alphabet and then displays the letter that precedes the input letter. (Hint: Use the same technique used in the previous problem.)

Q:

6. Write a program that reads a positive integer from the user then finds and displays the sum of its digits. For example, if the user enters 3582, the program should display 18 (3 + 5 + 8 + 2).

Q:

7. Write a program that reads a word from the user and then displays the letters in reverse using the say block.

Q:

8. Write a program that gets a number from the user and then inserts a space between each pair of digits. For example, if the input number is 1234, the output string should be 1 2 3 4. (Hint: Construct the output variable by joining the individual letters from the input number with white spaces.)

Q:

9. In this problem, you’ll create a game that lets players compare fractions. The user interface is shown on the right. When the New button is clicked, the game randomly picks two fractions to compare. The user selects less than (<), greater than (>), or equal to (=) by clicking the operator button. When the user clicks the Check button, the game checks the answer and provides feedback. Open the file CompareFractions.sb2 and add the necessary scripts to complete the game.

Compare Fractions.sb2

image with no caption