Chapter 12. Quizzes and Word Puzzles

Quizzes and Word Puzzles

Let’s get away from arcade games for a while and look at a series of games that involves words, not actions. Two different types of word games are covered in this chapter. The first is a type of game that asks questions and then determines whether the player answered correctly. The second type of game makes the player figure out a word or phrase by guessing one letter at a time.

Flash Quiz

Flash QuizExample file: Flashquiz.fla

The first two games you will build in this chapter involve questions and answers. The first is a quiz game in which 10 questions are presented, each with 4 possible answers. After the player selects an answer for each, he can see how well he has done.

Figure 12.1 shows the main game frame. The question is near the top, and the four possible answers are below it. The user must click the buttons to the left of each answer.

The main game frame shows a question and four answers.

Figure 12.1. The main game frame shows a question and four answers.

Project Goal

The goal for this project is to make a game that can read a set of questions from an external text file. Then the game displays the questions one by one for the player to answer. Four possible answers are shown. A sound that plays when the player chooses her answer signifies whether she got it right or wrong.

When all 10 questions have been asked, the game is over. A final score is displayed. Go to the example movie Flashquiz.fla on the CD-ROM and play a few rounds to get the idea of how it works.

Approach

The first task is to get the questions and answers from a text file. You can use loadVars for this; it grabs a local text file and takes the questions and answers from there.

Unfortunately, loadVars can’t handle arrays or objects, which is what you need to store a set of questions and answers efficiently. However, you can read in a single piece of text and use split to break it into parts to store in an array. This is how you can get 10 questions, 4 answers for each question, and the number of the correct answer, all from one block of text.

After the questions are in an array, the rest is simple. The text from each question and the answers are placed in the appropriate text areas. The number of the correct answer is stored in a variable. Then the program waits for the player to click a button.

Each button calls a function, telling it which answer it represents. If the correct button is clicked, a good sound plays and the number of questions correctly answered is incremented. If the wrong button is clicked, the bad sound is played. Either way, the next question is asked.

When all 10 questions have been asked, the game advances to a “game over” frame where the final score is displayed.

The only extra feature of this game is a neat special effect that causes the text to fly in from the right when each question is first asked.

Preparing the Movie

A lot of things need to be set up before the coding can begin. The first frame, shown in Figure 12.2, shows the “loading” frame. Because the questions are loaded from an external text file, the movie has to wait to make sure that the questions are all there before it can proceed.

The “loading” frame stays on the screen until the questions have been loaded.

Figure 12.2. The “loading” frame stays on the screen until the questions have been loaded.

After the questions have been loaded, some ActionScript moves the game along to the second frame, labeled “start game.” This frame features some instructions and a button, as shown in Figure 12.3.

The “start game” frame waits until the user is ready for the first question.

Figure 12.3. The “start game” frame waits until the user is ready for the first question.

The game frame itself, shown earlier in Figure 12.1, is the most complex. It features a text area for the question, four text areas for the answers, and even a small text area with the question number. There are also four buttons, one to the left of each answer.

The five main text areas are not all they seem in Figure 12.1. Each is actually a text area named “text” inside a movie clip. These five movie clips are called “question” and “answer0” to “answer3.” This was done instead of using plain text areas so the clips can be moved on the Stage to create a certain effect to be discussed later.

Writing the Code

There isn’t much code in this game, but it is scattered in a few places. The first frame has code in the main timeline that loads the questions from an external text file.

The code starts by creating a LoadVars object. A LoadVars object is just like a small variable object, except that you can use it to perform some specific tasks with the LoadVars object’s properties. Specifically, you can request that the object’s properties be sent to the server, or that new properties be loaded from the server.

Because you want to request properties from the server, there is no need to set any properties of the LoadVars object ahead of time. You’ll learn how to send properties in Chapter 17, “Advanced Techniques.”

The load command, when used on a LoadVars object, calls the server and requests some text.

Note

Note

The load command of the LoadVars object attempts to grab a text file from a URL. It then reads in the text file as if the contents of the file were property assignments. For instance, a text file that contained “myVariable=Hello” would set the property “myVariable” in the object to “Hello.” Because things do not load instantly on the Web, this might happen several seconds after the load command has been issued.

The script starts by creating a LoadVars object named “loadQuestions.” It then calls the load command with the local URL “flashquiz.txt.”

The onLoad property of a LoadVars object defines a function that will be called when the loading is complete. In this case, the function “initQuestions” will be called.

After a LoadVars.load is done, then any properties that are sent by the text file will be available to you in ActionScript. For instance, if the property “myProperty” is set to “myValue,” then you can ask for “loadQuestions.myProperty” and get “myValue” in return.

<LINELENGTH>90</LINELENGTH>
stop();

// get the questions
loadQuestions = new LoadVars();
loadQuestions.load("flashquiz.txt");

// call initQuestions when loading is complete
loadQuestions.onLoad = initQuestions;

The “initQuestions” function takes a long string of text and converts it into an array with questions, answers, and the number of the correct answer for each question.

Here is what the first part of the Flashquiz.txt file looks like. The first line assigns the text “The Planets” to the property “topic.” The code will take this property, addressed as “loadQuestions.topic,” and assign its value to the root level “topic” variable so that it appears in a dynamic text field.

<LINELENGTH>90</LINELENGTH>
topic=The Planets&questions=Which planet is closest to the Sun?: Jupiter;Saturn;Mercury;Mars:2:

In the text file, the property assignment ends with the “&” character. Then the program starts setting the variable “questions.” This text is several lines long. Each line is a single question. Each question is broken into three parts: the question text, the answers, and the number of the correct answer. A colon is used to divide these three elements. Furthermore, a semicolon is used to divide the four answers.

<LINELENGTH>90</LINELENGTH>
Which planet is tilted on its axis the most?:Earth;Venus;Mars;Uranus:3:
Which planet is the largest?:Jupiter;Earth;Neptune;Pluto:0:
Which planet has exactly two moons?:Venus;Mars;Saturn;Uranus:1:

Tip

Tip

An extra colon was used at the end of each line so that when the line is broken into parts by the code, any extra characters at the end of the line are placed in a fourth, unused, part. What extra elements would there be? Well, if you use some Windows text editors, an extra invisible character is placed at the end of every line of text. If you let this extra character be a part of the number of the correct answer, it prevents Flash from converting that number to something it can use. Thus, the extra colon places this extra character harmlessly in an unused fourth element of each line.

Warning

Warning

Be careful not to place an unwanted blank line at the end of the text file. It is easy to press Return or Enter at the end of the last question to create this line. If a blank line is added to the end of the text file, the code uses that as an eleventh question.

This text is broken into array elements by using the split command several times. First it is used to separate questions from each other. Then, it is used to separate the parts of the questions. Finally, it is used to separate the answers. The result is a nested array with all the information you need.

<LINELENGTH>90</LINELENGTH>
function initQuestions(questions) {
    // set the topic text
    topic = loadQuestions.topic;

    // break into questions using returns
    // NOTE: character 10 may work better in some cases than character 13
    qArray = loadQuestions.questions.split(String.fromCharCode(13));

    // break each question into question, answers, and correct answer
    for(i=0;i<qArray.length;i++) {
        qArray[i] = qArray[i].split(":");

        // break the answers apart
        qArray[i][1] = qArray[i][1].split(";");
    }

    // start the game
    _root.gotoAndPlay("start game");
}

Warning

Warning

I used String.fromCharCode(13) to get the carriage return character that is used to break up the lines of a text file. Why didn’t I use the ActionScript Constant newline? Because newline is different between the Mac and Windows version of Flash. On the Mac, it returns character number 13, but on Windows it returns character number 10. Furthermore, some text editors place a character 10 after a line rather than a 13. Some even place both! So if you can’t seem to get the game to recognize more than the first question, you may want to change the 13 to a 10 to see whether it fixes the problem.

Note

Note

The split function takes a string and breaks it into an array of strings. The one parameter it takes is the character used to divide the items. In the previous example, both a colon and a semicolon are used to split strings into arrays.

When the game goes to the “play” frame, the ActionScript in the main timeline immediately calls “initGame.” This sets the “questionNum” and “numRight” to 0. It calls “displayQuestion” to show the first question.

<LINELENGTH>90</LINELENGTH>
function initGame() {
    // set variables
    questionNum = 0;
    numRight = 0;

    // ask the first question
    displayQuestion();
}

The “displayQuestion” function determines whether the game is over, displays the final score if necessary, and jumps to the “game over” frame if the game is over. Otherwise, it takes the question and each answer and places them in the text areas inside the appropriate movie clips. It places the number of the correct answer in “correctAnswer.”

<LINELENGTH>90</LINELENGTH>
function displayQuestion() {
    // see whether all the questions have been asked
    if (questionNum >= qArray.length) {

        // show final score and end the game
        finalScore = numRight + " out of " + qArray.length;
        gotoAndPlay("game over");

    } else {

        // place the question and answers on the screen
        question.text = qArray[questionNum][0];
        answer0.text = qArray[questionNum][1][0];
        answer1.text = qArray[questionNum][1][1];
        answer2.text = qArray[questionNum][1][2];
        answer3.text = qArray[questionNum][1][3];

        // show the question number
        questionNumDisplay = questionNum+1;
        // remember which one is correct
        correctAnswer = int(qArray[questionNum][2]);

        // make the text slide in
        animateIn();
    }
}

Note

Note

When you have an array inside another array, you can refer to a specific item by using multiple bracket sets. For instance, “myArray[3][8]” refers to the eighth item in the third array in the “myArray” variable. “myArray” is made up of four or more arrays and the third one has at least nine items.

The “animateIn” function is just a special effect, and does not really affect game play. It sets the position of each text movie clip off the Stage to the right. It then sets a variable called “xstop” for each of these movie clips to the x position where the movie clip should be. Code assigned to each of these clips then acts to move the clips to the left until they line up with “xstop.”

<LINELENGTH>90</LINELENGTH>
function animateIn() {
    // set the location of each piece of text
    // and set where each movie clip should stop
    question.xstop = 300;
    question._x = 800;

    answer0.xstop = 400;
    answer0._x = 1000;

    answer1.xstop = 400;
    answer1._x = 1200;

    answer2.xstop = 400;
    answer2._x = 1400;

    answer3.xstop = 400;
    answer3._x = 1600;
}

When the user clicks one of the four buttons, the button calls “selectAnswer” with the number of the answer, from 0 to 3. If this matches “correctAnswer,” a good sound is played, and “numRight” is increased. If not, a bad sound is played. Either way, the “questionNum” is incremented and the next question is displayed.

<LINELENGTH>90</LINELENGTH>
function selectAnswer(n) {
    // add to count if correct
    if (n == correctAnswer) {
        triggerSound("right");
        numRight++;
    } else {
        triggerSound("wrong");
    }

    // ask next question
    questionNum++;
    displayQuestion();
}

A simple function that comes in handy in a number of game situations is “triggerSound.” It simply plays a sound with the proper link name.

<LINELENGTH>90</LINELENGTH>
function triggerSound(soundName) {
         // simply play a sound
         soundfx.stop();
         soundfx = new Sound();
         soundfx.attachSound(soundName);
         soundfx.start();
}

That’s it for the main timeline script. However, two important small scripts are assigned to other elements on the Stage. The first is the script assigned to each text movie clip. It checks to see whether the clip’s position is to the right of “xstop” and moves it more to the left if it is. The result is that the movie clip keeps moving left until it hits “xstop.” Therefore, when the position of the clip is set offscreen to the right by the “animateIn” function, the question slides in from the right.

<LINELENGTH>90</LINELENGTH>
onClipEvent(enterFrame) {
    if (_x != xstop) _x -= 20;
}

Each button also has a short script attached to it. It calls the “selectAnswer” function with a number from 0 to 3. So the first button has this script:

<LINELENGTH>90</LINELENGTH>
on (release) {
    selectAnswer(0);
}

Other buttons use a 1, 2, or a 3 in place of the 0.

Loose Ends

You’ll need two sounds, one linked with the name “correct” and one with the name “wrong”. You’ll also need a “continue” button of some sort, such as the one shown in Figure 12.3 earlier. Check out the Flashquiz.fla movie on the CD-ROM if you have any questions about how this all fits together.

Other Possibilities

Although the goal of this program is to present 10 questions to the player, nothing in the code restricts the game to 10 questions. You can ask more or fewer than 10 questions by changing the Flashquiz.txt file.

Also, in addition to showing the player that he got “8 out of 10” correct, you can give the player a ranking. So “8 out of 10” might earn a “You know your planets!” message, although only 2 out of 10 might produce the message “Go back to school.”

Flash Trivia

Flash TriviaExample file: Flashtrivia.fla

Now that you have a working quiz game, you can build on that to create a trivia game. There are really only a few differences between the quiz game and the trivia game. You’ll add more advanced scoring, giving players a chance to score more points if they are quick, and also allowing them to guess more than once while losing points for each wrong guess.

Another feature is randomness. The answers are scrambled so they don’t always appear in the same order for everyone. This makes it easier to build the question list, because the first answer in the data file can always be the correct one, but it will not usually be presented as the first answer that the player sees.

Figure 12.4 shows the main play frame of the example movie, Flashtrivia.fla.

The trivia game looks a lot like the quiz game, but scoring takes time into account.

Figure 12.4. The trivia game looks a lot like the quiz game, but scoring takes time into account.

Project Goal

Your goal for this movie is to create a basic trivia game that builds on the previous game. Instead of the answers always appearing in the same order, they appear in a random order each time.

When a question first appears, it is worth 1,000 potential points. As the player tries to determine the correct answer, the number of potential points rapidly decreases. If the player makes an incorrect guess, she loses even more potential points. When the player finally gets the correct answer, the number of potential points remaining is added to her score.

Approach

Like the previous movie, the questions and answers are loaded from an external text file. However, this text file is a little different. In the previous game, the answers were presented in a set order, and an additional item pointed out which answer was the correct one. This time, the correct answer is always first, and is followed by three incorrect answers. You can do this because the answers are shuffled anyway. Here are a few lines from the “flashtrivia.txt” file:

<LINELENGTH>90</LINELENGTH>
questions=The world's first computer bug was actually a real bug stuck in an
early computer. What type of bug was it?:Moth;Beetle;Fly;Worm:
Which is the world's largest Island?:Greenland;Iceland;Australia;New Zealand:
Besides humans, what other animal also has individual fingerprints?:Koala
Bears;Apes;Snakes;Frogs:

Warning

Warning

Just as with the previous project, be careful not to place an unwanted blank line at the end of the text file. It is easy to press Return or Enter at the end of the last question to create this line. If a blank line is added to the end of the text file, the code uses that as an eleventh question.

Before each question is asked, the four answers are randomly shuffled into a new array. The correct answer can appear in any of the four spots. Its value is stored in a variable to use later to determine whether the user picked the correct answer.

You can use the same animation as in the previous game, but it should be sped up a little. The question appears right away, with no animation, but the answers fly in quickly from the right. The number of potential points only starts to decrease after all four answers are in place.

When a player picks a wrong answer, not only are points deducted from the number of potential points, but the answer he selected also disappears.

Preparing the Movie

This movie has four frames. The first loads the questions and answers and places them in an array. The second frame explains the game to the player.

The action takes place in the third frame. This frame shows the question, four answers, and a button next to each answer. It also shows the number of potential points and the score, which are both dynamic text areas, the first linked to the variable “potentialPoints” and the second linked to the variable “score.”

Remember that the four answers are actually movie clips with text areas inside them. The text areas are all set to represent a variable called “text.” The four movie clips, however, are named “answer0” to “answer3.”

The last frame of the game is the “game over” frame. This shows the final score and allows the player to click a button to play again.

Writing the Code

The first piece of code is attached to the “loading” movie clip on frame 1. It is basically the same code used in the previous game to load the questions from the text file. When the questions arrive, it calls “initQuestions,” which is in the main timeline.

<LINELENGTH>90</LINELENGTH>
stop();

// get the questions
loadQuestions = new LoadVars();
loadQuestions.load("flashtrivia.txt");

loadQuestions.onLoad = initQuestions;

The “initQuestions” function breaks the string into questions with two parts. The first part is the question, and the second part is the answers. Then it breaks the answers into individual answers. This is all stored in the “qArray” array.

<LINELENGTH>90</LINELENGTH>
function initQuestions() {
    // break into questions using returns
    // NOTE: character 10 may work better in some cases than character 13
    qArray = loadQuestions.questions.split(String.fromCharCode(13));

    // break each question into question and answers
    for(i=0;i<qArray.length;i++) {
        qArray[i] = qArray[i].split(":");

        // break the answers apart
        qArray[i][1] = qArray[i][1].split(";");
    }
    // start the game
    _root.gotoAndPlay("start game");
}

Most of the code is in the “play” frame. This is where the questions get asked and the player has to react. When the frame begins, the “initGame” function sets the score to 0 and displays the first question.

<LINELENGTH>90</LINELENGTH>
function initGame() {
    // set variables
    questionNum = 0;
    score = 0;

    // ask the first question
    displayQuestion();
}

The “displayQuestion” function takes the next question and places the question and answer text in the proper text areas. It also sets the number of potential points for this question to 1,000.

<LINELENGTH>90</LINELENGTH>
function displayQuestion() {
    // see whether all the questions have been asked
    if (questionNum >= qArray.length) {

        // show final score and end the game
        gotoAndPlay("game over");

    } else {
        // rearrange
        answers = shuffleArray(qArray[questionNum][1].slice(0));

        // place the question and answers on the screen
        question.text = qArray[questionNum][0];
        answer0.text = answers[0];
        answer1.text = answers[1];
        answer2.text = answers[2];
        answer3.text = answers[3];

        // show the question number
        questionNumDisplay = questionNum+1;

        // remember which one is correct
        correctAnswer = qArray[questionNum][1][0];
        // make the text slide in
        animateIn();

        // start potential points at 1000
        potentialPoints = 1000;
    }
}

The “scoreCount” function is called once per frame by the “actions” movie clip. It subtracts one point from the number of potential points, making sure that it never drops below 0.

<LINELENGTH>90</LINELENGTH>
// every frame that goes by subtracts one point
function scoreCount() {

    // make sure that last answer has arrived
    if (answer3._x == 400) {

        // subtract point
        potentialPoints -= 1;
        if (potentialPoints < 0) potentialPoints = 0;
    }
}

The “shuffleArray” function is used by “displayQuestion” to re-order the answers randomly. It works by creating a new array and then adding one element at a time from the old array to the new array.

<LINELENGTH>90</LINELENGTH>
// take array1 and shuffle into array 2
function shuffleArray(array1) {
    // create new, empty array
    array2 = new Array();

    // loop through array
    do {
        // select a random item
        r = int(Math.random()*array1.length);
        // add item to new array
        array2.push(array1[r]);
        // remove item from old array
        array1.splice(r,1);
    } while (array1.length > 0);

    // send back the new array
    return(array2);
}

The “animateIn” function sets the location of the four answers off the Stage to the right. It also notes that each of these movie clips should stop moving left when it gets to the horizontal location 400. A script attached to each movie clip moves the clip quickly to the left until that happens.

<LINELENGTH>90</LINELENGTH>
function animateIn() {
    // set the location of each answer
    // and set where each should stop
    answer0.xstop = 400;
    answer0._x = 800;

    answer1.xstop = 400;
    answer1._x = 1000;

    answer2.xstop = 400;
    answer2._x = 1200;

    answer3.xstop = 400;
    answer3._x = 1400;
}

When the player clicks a button, the answer she selected is compared to the “correctAnswer” variable, which was assigned in “displayQuestion.” If she got it correct, she gets the potential points, and the next question is displayed. If not, then 200 points are deducted from the number of potential points, and the answer is removed from the screen.

<LINELENGTH>90</LINELENGTH>
function selectAnswer(n) {
    // correct
    if (answers[n] == correctAnswer) {
        triggerSound("right");

        // add score
        score += potentialPoints;

        // ask next question
        questionNum++;
        displayQuestion();

    } else {
        // wrong
        triggerSound("wrong");

        // subtract from potential points
        potentialPoints -= 200;
        if (potentialPoints < 0) potentialPoints = 0;
        // remove the answer
        _root["answer"+n].text = "";
    }
}

The “triggerSound” utility function is the same one used earlier in this chapter. It simplifies adding quick sounds to the rest of the code.

<LINELENGTH>90</LINELENGTH>
function triggerSound(soundName) {
         // simply play a sound
         soundfx.stop();
         soundfx = new Sound();
         soundfx.attachSound(soundName);
         soundfx.start();
}

The other pieces of code on the “play” frame include the bit of code on the “actions” movie clip that calls “scoreCount.”

<LINELENGTH>90</LINELENGTH>
onClipEvent(enterFrame) {
    _root.scoreCount();
}

The code found on each of the four answer movie clips is also used (here is the code for one of the clips). Notice that it moves the movie clip twice as fast as in the quiz game.

<LINELENGTH>90</LINELENGTH>
onClipEvent(enterFrame) {
    if (_x != xstop) _x -= 40;
}

Each of the four buttons includes a script that triggers “selectAnswer.” Not only do these buttons react to mouse clicks, but each button is assigned a keyboard key as well. For instance, the first button, which you can see is labeled “A” in Figure 12.4 (shown previously), also reacts to the key “A.”

<LINELENGTH>90</LINELENGTH>
on (release, keyPress "A") {
    selectAnswer(0);
}

Loose Ends

Browse through each element in the example movie Flashtrivia.fla on the CD-ROM. There are many named text areas, including the question, the four answers, the potential points, and the score. Each button is the same movie clip, but a static letter has been placed on top of it. These letters don’t do anything except remind the user that he can press a key on the keyboard rather than click the button itself.

Other Possibilities

Like the quiz game, you can place as many questions in the text file as you want. If you know server-side CGI programming, you could even write a server program to generate the Flashtrivia.txt information from a database of questions.

You can easily change the number of potential points with which a question starts, and change the number of points deducted for a wrong answer.

Hangman

HangmanExample file: Hangman.fla

This next game should be familiar to all. The classic pencil-and-paper game, hangman, asks the player to guess which letters are used in a phrase. If the letter she guesses is in the phrase, that letter is revealed in every position where it is located. If the letter is not in the phrase at all, a piece of a drawing of a man getting hanged is added. If the drawing is complete before the phrase has been guessed, the player loses.

Project Goal

The goal here is to re-create the classic hangman game in Flash. The player can use the keyboard to make guesses. Flash takes care of showing the letters and drawing the hanging man, or in this case, the fox.

Figure 12.5 shows the main game frame with the fox fully drawn and some letters showing. In this case, the game has just been lost.

This hangman game has been lost.

Figure 12.5. This hangman game has been lost.

Approach

This game requires a lot of string manipulation. The phrase to be guessed is a string. From that, you build a string that uses underscore characters in place of letters. This is what the player sees.

When the player makes a guess, that letter is compared to every letter in the original phrase. If the letter matches one in the phrase, that letter is shown in that position on the screen.

If the player guesses wrong, the fox movie clip is advanced to the next frame, which adds a part of the fox. If this is the last frame of the fox movie clip, the game is over.

Preparing the Movie

The main element is the text area on the screen. The text area starts with all underscores and spaces, which are replaced gradually with letters as letters are correctly guessed.

The text area has to be set up as Dynamic Text and linked to the variable “display.” You also need to set the field to Multiline. This can all be done in the Properties panel when the field is selected.

The display text uses the “Monaco” font, which is a monospaced font found on every Mac. If you are building your movie in Windows, you might have to use another monospaced font such as “Courier New” instead.

Tip

Tip

Monospaced font is necessary for this game so that the words wrap around from line to line exactly the same as game play continues. If the letters were different widths, the addition of new letters that were smaller or larger than the underscore would force Flash to rewrap the text.

This game also needs an “actions” movie clip that accepts keyboard input and passes it on to the main timeline script.

Writing the Code

The main parts of the code lie in the main timeline. There are only three functions. The first sets up the phrase at the start of the game.

The first function loops through all the letters in the phrase and creates a “display” string that contains underscores in place of letters. This is what the player sees at the start of the game.

<LINELENGTH>90</LINELENGTH>
function initGame() {
    //  get phrase
    phrase = "Imagination is more important than knowledge";

    // build display
    display = "";
    for(i=0;i<phrase.length;i++) {
        // place spaces in the correct spots
        if (phrase.charAt(i) == " ") {
            display = display + " ";

        } else {
            // place underscores in place of letters
            display = display + "_";
        }
    }
}

Note

Note

The charAt function returns the character at a position in a string. As with most functions in ActionScript, the first character is at position 0.

Each time the player presses a key, the “actions” movie clip sends the character code for that letter to the “makeGuess” function. The first thing this function does is convert the code to a letter.

Note

Note

The fromCharCode function takes a number, such as 65, and converts it to a character, such as “A.” All characters have a corresponding code. Numbers 65 to 90 refer to all the capital letters. Numbers 97 to 122 refer to all the lowercase letters. Character 32 is a space. You can find a complete list of characters and codes in the Flash MX documentation.

The “letter” variable is tested by the utility function “isAlpha” to see whether it is a letter. This means that other keys, such as the spacebar or a number, are ignored. You’ll learn more about the “isAlpha” function later.

Then, the function loops through each letter of the phrase looking for matches. While it is doing this, the function is rebuilding the “display” variable. Every match found is placed in “display,” as well as each letter that was guessed previously.

The variable “gotOne” is set to false before all this happens. If any match is found, “gotOne” is set to true. If it remains false at the end of the loop, the player guessed wrong, and the fox movie clip is advanced to the next frame.

Note

Note

The toUpperCase() function takes any string and converts all lowercase letters in it to capitals. This function is useful in situations like this in which you want the letters to match even if one is uppercase and the other is lowercase.

<LINELENGTH>90</LINELENGTH>
function makeGuess(code) {
    // get the character that corresponds to the key pressed
    letter = String.fromCharCode(code);

    // check to see whether it is a letter
    if (isAlpha(letter)) {

        // assume that the letter will not be found
        gotOne = false;

        // start building new display
        newDisplay = "";
        for(i=0;i<phrase.length;i++) {

            // see whether letters match
            if (phrase.charAt(i).toUpperCase() == letter.toUpperCase()) {

                // place letter in display text
                newDisplay = newDisplay + letter.toUpperCase();

                // note that at least one match has been found
                gotOne = true;

            } else {

                // not found, so display same character
                newDisplay = newDisplay + display.charAt(i) ;
            }
        }

        // show new display
        display = newDisplay;

        // if no match found, then add more to fox
        if (!gotOne) {
            fox.nextFrame();

            // see whether the fox is done
            if (fox._currentFrame == 8) {
                gotoAndPlay("lose");
            }

        } else if (display == phrase.toUpperCase()) {
            // the display matches the original, game over
            gotoAndPlay("win");
        }
    }
}

The “isAlpha” function is a good utility function that takes any character string and tests to see whether the first character is a letter. It uses charCodeAt to get the code of the first letter. Because the code numbers for lowercase letters are 32 higher than uppercase, you can subtract 32 from any code greater than 90 to look for uppercase and lowercase letters with one test.

Note

Note

The charCodeAt function returns the code of any character in a string. The one argument it takes is the position of the character. So you can use it to look at the first character with charCodeAt(0).

<LINELENGTH>90</LINELENGTH>
// utility to test whether a character is in A-Z
function isAlpha(letter) {
    // get character  code
    n = letter.charCodeAt(0);

    // convert lowercase to uppercase
    if (n > 90) n -= 32;

    // see whether it is in A-Z
    return ((n >= 65) and (n <= 90));
}

The other piece of code needed here is attached to the “actions” movie clip. It takes any keypress and sends it along to the “makeGuess” function.

Note

Note

The Key.getAscii() function returns the character code of the key pressed. It can be used inside an onClipEvent(keyUp) function attached to a movie clip.

<LINELENGTH>90</LINELENGTH>
onClipEvent (keyUp) {
    _root.makeGuess(Key.getAscii());
}

Loose Ends

The final movie needs a “win” and “lose” frame to jump to when the game is over. The example movie, Hangman.fla, keeps these frames simple, but you can insert animation for each of these. For instance, the “win” animation can show the fox being set free, whereas the “lose” animation can show something more gruesome.

Other Possibilities

The phrase in this example is hard-coded into the “initGame” function. However, you can use what you learned about loading external text from the two other games in this chapter to make it easier to change the phrase. You could even include a list of phrases to be shown one after the other.

If you want to include punctuation in the game, you can modify the code to look for other things, in addition to spaces, that will be automatically revealed at the start of the game. In fact, you could use isAlpha to test whether it is a letter, and display it at the start of the game if not.

Cryptogram

CryptogramExample movie: Cryptogram.fla

Cryptograms are a fairly common type of word puzzle that offer more of a challenge than the hangman-like games. If you have never seen one, check your local newspaper’s puzzle page. Chances are good that you’ll find one near the daily crossword.

In a cryptogram, a sentence or phrase is encrypted with the simplest technique: Each letter of the alphabet is replaced with another letter. For instance, “Hello” might be “JQXXE “, where J stands for H, Q for E, X for L, and E for O. Because X replaces L, it must do so for all instances of L in the phrase.

Note

Note

The odd thing about cryptograms is that they get easier to solve as they get longer. A common way to start solving them is to look for single-letter words, which must be either “a” or “I,” and then two-letter words, which are usually “is,” “it,” “in,” “of,” or “on.” If a three-letter word starts the phrase, it is usually “The.”

Project Goal

Cryptograms are usually done with paper and pencil (or pen for those who want a challenge). A computer version can actually make the puzzle solving easier. In the paper version of the game, if the player identifies that Z is E, he or she must then look for other instances of Z and change them to E. If the player changes his or her mind, then all the Es must be erased.

This game takes care of this automatically. When the player indicates that a Z is an E, all Zs in the puzzle are immediately mapped to E. If the player then wants to change that decision he or she can easily make all of the Zs represent As.

Approach

This game uses two letter maps. The first letter map maps each letter of the alphabet to its encoded counterpart. For instance, look at this letter map:

<LINELENGTH>90</LINELENGTH>
SLGKWPZRMCYINEQFHXAVBOUDJT

In this letter map, the first letter of the alphabet, A, is encoded as S. The second letter, B, is encoded as L, and so on. Using this letter map, the word “Hello” is encoded as “RWIIQ.”

The second letter map is the one the user is using to decode the puzzle. It starts off as this:

<LINELENGTH>90</LINELENGTH>
ABCDEFGHIJKLMNOPQRSTUVWXYZ

As the user maps encoded letters to what he or she thinks they decode to, the user’s letter map changes. For instance, if the user decides that R maps to H, then the user’s map changes to this:

<LINELENGTH>90</LINELENGTH>
ABCDEFGHIJKLMNOPQHSTUVWXYZ

By taking a phrase and using the first letter map, you get an encoded phrase that can be used in the cryptogram. Then, when the encoded phrase is passed through the user’s letter map, the phrase is decoded back into its original state, provided that the user has created the correct letter map.

In this game, the player can move forward and backward through the letters of the puzzle with the arrow keys. When a user presses a letter key, the letter map changes to map the currently selected letter to the key pressed.

Figure 12.6 shows the game in progress. The upper letters are the ones that the player has already mapped. Letters that are not mapped are shown with an asterisk. The lower letters are the encrypted phrase. Only the upper letters change as the player solves the puzzle.

In the cryptogram puzzle, the lower letters are the encoded message, whereas the upper letters change according to the player’s choices. The last letter in the first line is bold because it is the currently selected letter.

Figure 12.6. In the cryptogram puzzle, the lower letters are the encoded message, whereas the upper letters change according to the player’s choices. The last letter in the first line is bold because it is the currently selected letter.

Preparing the Movie

The only active elements on the screen are two nearly-identical dynamic text fields. The first, named “decryptedText” and linked to the variable “decrypted,” is slightly higher than the second, named “encyrptedText” and linked to the variable “encrypted.” The font color of the second field is a bit lighter as well.

Both text fields use Courier New as a font, so that the letters are monospaced as they are in the hangman game.

Writing the Code

An unusual thing about this movie is that all the code is in the one frame script. All of it. There’s not even a single button or movie clip. The Library for this movie is, in fact, empty.

The frame script starts off by calling “initGame.” This sets the phrase and initializes the letter maps. The user map is actually set to all asterisks. This maps every letter to an asterisk. The result is that all letters display as asterisks in the decrypted text field.

The encryption map, called “letterMap,” is set by a call to “createLetterMap,” which is covered next. You can also see the yet-to-be-written functions “showPhase” and “showCursor.” The first updates the text fields on the screen using the latest version of the letter maps. The second makes the currently-selected letter in the phrase bold. The “charpos” variable represents which letter is selected.

The “initGame” function ends by creating a keyboard listener, which makes sure that the function “getLetter” is triggered each time the user presses a key on the keyboard.

Note

Note

Listeners are a great new addition to Flash MX. A listener tells Flash to recognize when an event occurs and to trigger a set of commands or a function when it does. The code can create a listener by first defining a standard object. The event to be listened for, in this case “onKeyUp,” is set to link to a function. Then the addListener command attaches this object to a Flash object, in this case the Key object. Only certain Flash objects can have listeners attached and they can only be used for specific events relative to the object. For instance, Key listeners can hear only onKeyUp and onKeyDown events.

<LINELENGTH>90</LINELENGTH>
initGame();
stop();

function initGame() {
    // phrase to use
    phrase="Imagination is more important than knowledge. -- Albert Einstein";
    // init all variables
    createLetterMap();
    userMap = "**************************";
    charpos = 0;

    // show phrase and cursor
    showPhrase();
    showCursor();

    // listen for key presses
    keyListener = new Object();
    keyListener.onKeyUp = getLetter;
    Key.addListener(keyListener);
}

To create a random letter map, it seems that all you need to do is loop through all the letters and assign a new, random letter to each letter of the alphabet. However, it is not that simple. You need to be sure that not just any letter is picked, but only a letter not yet used. For instance, you don’t want to assign R to both A and B.

The second layer of complexity appears when you realize that you don’t want to assign a letter to itself. So, for instance, if G is assigned to G, then you want to throw out the letter map and make a new one.

The “createLetterMap” function loops until it finds a valid letter map. This usually happens on the first or second try.

<LINELENGTH>90</LINELENGTH>
// create random string of letters
function createLetterMap() {
    do { // loop until valid map created
        letterMap = "";
        for (var i=0;i<26;i++) {
            do { // loop until unqiue letter chosen
                r = Math.floor(Math.random()*26); // random number
                c = String.fromCharCode(r+65); // convert to letter
            } while (letterMap.indexOf(c) > -1);
            letterMap += c;
        }

        // check to make sure map is good
        bad = false;
        for(var i=0;i<26;i++) {
            if (letterMap.charCodeAt(i) == i+65) {
                bad = true; // letter at solved location
                break;
            }
        }
    } while (bad);
}

The “showPhrase” function loops through the letters of the phrase. It runs each letter though the “letterMap” to get the encrypted value. It then runs each encrypted letter through the “userMap” to get the current value according to the user. If a character is not a letter, but is a space or punctuation mark, then the character is shown without encryption.

<LINELENGTH>90</LINELENGTH>
function showPhrase() {
    encrypted = "";
    decrypted = "";
    for (var i = 0; i<phrase.length; i++) {

        // get real letter at this location
        c = phrase.toUpperCase().charAt(i);

        if ((" .-,'").indexOf(c)>-1) {
            // so white space as is
            encrypted += c;
            decrypted += c;
        } else {

            // use map to find encrypted character
            encryptedChar = letterMap.charAt(c.charCodeAt(0)-65);
            encrypted += encryptedChar;

            // use second map to find decrypted character
            decryptedCharacter = userMap.charAt(encryptedChar.charCodeAt(0)-65);
            decrypted += decryptedCharacter;
        }
    }
}

When the user presses a key, the Key object listener calls the function “getLetter.” The key pressed is placed into two variables: “ascii” for the ASCII key code, and “code” for the keyboard code. The “ascii” value is used to identify letters, and the “code” value is used to identify the arrow keys.

If the arrow keys are being pressed, then the “charpos” is updated. At the end of this function, the “showCursor” function is called so that the correct letter in the phrase is made bold.

If a letter is pressed, then the “userMap” is updated to reflect the fact that the user wants to map the current encrypted letter to the key pressed. The text fields are updated with “showPhrase.” Then the decrypted phrase is compared to the original phrase to see whether they match.

<LINELENGTH>90</LINELENGTH>
function getLetter() {
    // get ascii code and keyboard code
    var ascii = Key.getAscii();
    var code = Key.getCode();

    // move cursor with arrow keys
    if (code == Key.LEFT) {
        charpos--;
        if (charpos < 0) charpos = 0;
    } else if (code == Key.RIGHT) {
        charpos++;
        if (charpos > phrase.length-1) charpos = phrase.length-1;

    } else {
        // get upper case letter pressed
        var keyChar = String.fromCharCode(ascii);
        keyChar = keyChar.toUpperCase();

        // make sure it is a letter
        if ((keyChar >= "A") and (keyChar <= "Z")) {

            // get letter in phrase
            phraseChar = phrase.toUpperCase().charCodeAt(charpos)-65;

            // if the character is a letter
            if ((phraseChar >= 0) and (phraseChar < 26))  {

                // get character code in map
                letterNum = letterMap.charCodeAt(phraseChar)-65;

                // replace the character in the  second map
                userMap = replaceChar(userMap,letterNum,keyChar);

                // update phrase
                showPhrase();

                // check for game over
                if (phrase.toUpperCase() == decrypted) {
                    gotoAndStop("game over");
                }
            }
        }
    }
    // update cursor
    showCursor();
}

Unfortunately, there is no ActionScript command to allow you to easily change a single character in a string to another character. So you need to make your own function to do that. This function takes the characters before the change and appends them to the characters after the change, with the new character in the middle.

<LINELENGTH>90</LINELENGTH>
// replace a character in a string
function replaceChar(mainString, num, newchar) {
    newString = mainString.substring(0,num)+newchar+ mainString.substring(num+1,mainString.length);
    return(newString);
}

To show the user to which letter the “charpos” variable is pointing, that letter is bolded in both the encrypted and decrypted fields. Using the new Flash MX TextFormat object is the way to do that. TextFormat objects have a ton of properties. When you apply a text format to a field, only those properties that have been specifically set in the object are changed in the field.

The “plainFormat” TextFormat object only specifies that bold be false. So when it is applied to the text fields “decryptedText” and “encryptedText,” any bold characters are changed to plain. The “cursorFormat” object is the opposite. All characters to which it is applied are bolded. The code sets the text format of only the one character in the fields that match “charpos.”

<LINELENGTH>90</LINELENGTH>
function showCursor() {
    // set both fields to plain
    plainFormat = new TextFormat();
    plainFormat.bold = false;
    decryptedText.setTextFormat(plainFormat);
    encryptedText.setTextFormat(plainFormat);

    // set one character in both fields to bold
    cursorFormat = new TextFormat();
    cursorFormat.bold = true;
    decryptedText.setTextFormat(charpos,cursorFormat);
    encryptedText.setTextFormat(charpos,cursorFormat);
}

Loose Ends

The example movie contains a “game over” frame. This is where the movie jumps when the puzzle is solved. You can also use the removeListener if you want to force the movie to stop responding to key presses.

Other Possibilities

As the user moves through the phrase with the arrow keys, the cursor is sometimes over spaces and other inactive characters. You can add more code to test cursor movement segments to recognize when the cursor is over white space and continue to move it forward or backward until it hits a letter.

Although the example movie has a phrase that is embedded into the code, you can also read the phrase in with a LoadVariables or LoadVars command. This enables you to change the phrase without having to recompile the .swf.

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

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