Sie sind auf Seite 1von 15

part 1 Exercise Start_Quiz_App.

fla

File

In this tutorial, we are going to learn how to create a quiz in Flash using ActionScript 3. We're going to make use of arrays and for loops in order to complete this project. This tutorial comes with an exercise file (the download link can be found at the top of the article). Let's go ahead and open it and take a look at its contents. This Flash movie has 2 frames. The first frame contains the elements needed for the user to take the quiz. The second frame contains elements that will display the results (answers and scores). The Flash movie should start at frame 1, and stay there until the user finishes answering all the questions. Once the user is done, the Flash movie goes to frame 2 where the answers are checked and the score is given. Since the quiz and the results are separated into two different frames, then the code will be separated as well. Frame 1 will contain the code that is needed to run the quiz (displaying questions and storing the answers submitted by the user), while frame 2 will contain the code that is needed to check the answers, compute the results and display them. So first, let's go ahead and work on frame 1. Frame 1 contains 3 objects:

1. questions_txt - This is a Dynamic TextField that will be used to display the questions. In the Properties Inspector, this TextField has been set to be multilined. 2. answers_txt - This is an Input TextField where the user will type in the answer. In the Properties Inspector, this TextField has been set to have a border and to be a single line TextField. 3. submit_btn - This button will be used by the user to submit each answer.

The first thing we'll do is to stop the Flash movie on frame 1. If we don't, then the movie will just continue looping between frames 1 and 2. So select frame 1 of the actions layer, then go to the Actions Panel and put in a stop action.

stop();

Next,

let's

create

couple

of

objects:

stop();

var nQNumber:Number = 0; var aQuestions:Array = new Array(); var aCorrectAnswers:Array "war", "Titan"); = new Array("Jupiter", "Mars",

var aUserAnswers:Array = new Array();


What are these instances for? nQNumber We will be storing the quiz questions in an array. Each question will therefore be numbered starting at 0. ThisnQNumber variable will be used to move through each of those quiz questions. After the user answers one question, we will have this number increase by one and use that number to retrieve the next question. aQuestions This is the array that will be used to store the questions.

aCorrectAnswers This is the array that stores all the correct answers. Of course we will have to be the ones to provide what the correct answers are, which is why this array is already populated with values. When the array was created, the values were also declared in the array constructor, therefore populating the array. The first value will have an index of 0, the second value will have an index of 1, and so on... You will notice that the aQuestions array, which is supposed to store the questions, has not been given any values yet. Don't worry, we'll provide those values shortly using array access notation instead. aUserAnswers This array will be used to store the answers given by the user. Each time the user (the quiz taker) submits an answer, then that answer will go into this array. So we just create this array first, but we don't put any values in it initially. We'll have to wait for what the user will input in the answer field and use those to populate this array instead. Next, let's go ahead and create the questions. We've provided 4 answers when the aCorrectAnswers array was created, so we'll need to provide 4 questions as well. Make sure that the order of the questions corresponds to the order of the answers as well (question index 0 should match answer index 0, question index 1 should match answer index 1, and so on...). We will populate the aQuestions array using Array Access Notation:

var nQNumber:Number = 0; var aQuestions:Array = new Array(); var aCorrectAnswers:Array "Titan"); = new Array("Jupiter", "Mars", "war",

var aUserAnswers:Array = new Array();

aQuestions[0] system?";

"What

is

the

biggest

planet

in

our

solar

aQuestions[1] = "Which planet in our solar system is the 4th planet from the sun?"; aQuestions[2] = "Mars is named after the Roman god of ___.";

aQuestions[3] = "What is the name of Saturn's largest moon?";

So now that we've created all the needed objects and have added all the questions and answers for this first part of our project, let's now go ahead and create the actual quiz functionality. The first thing we'll do is display the first question in the questions_txt TextField. So what we can do is getaQuestions[0] (the 0 index corresponds to the first item in the array, and therefore the first question) and assign it to the text property of our TextField like so: questions_txt.text = aQuestions[0] . But the problem here is that we'd like to be able to update to the next question after the user finishes answering the first one. So instead of manually inputting the index number, we can make use of a variable instead. And then we can just update that variable whenever needed. This is where our nQNumber variable comes in. Initially, it has a value of 0, so typing in questions_txt.text = aQuestions[nQNumber] will be the the same as typing inquestions_txt.text = aQuestions[0] . And then later on, we'll add some code that will increment the value of nQNumber every time the user submits an answer, thereby updating to the next question. But first, update your code so that the first question will be displayed in the questions_txt TextField:

aQuestions[0] = "What is the biggest planet in our solar system?"; aQuestions[1] = "Which planet in our solar system is the 4th planet from the sun?"; aQuestions[2] = "Mars is named after the Roman god of ___."; aQuestions[3] = "What is the name of Saturn's largest moon?";

questions_txt.text = aQuestions[nQNumber];
So now, if you test the movie, you should see the first question displayed in the TextField. And now that we have that, the next thing we need to fix is how our Flash movie is going to respond whenever a quiz taker types an answer in the input field and clicks on the submit button. So let's break it down. When the user clicks on the submit button, our flash movie should: 1. get the user's answer (what he or she inputs in the answer field) and add it to the aUserAnswers array 2. update to the next question

Since we want all this to happen whenever the user clicks on the button, we'll have to create a CLICK event handler for submit_btn. And let's give the event listener function the name quiz.

questions_txt.text = aQuestions[nQNumber];

submit_btn.addEventListener(MouseEvent.CLICK, quiz);

function quiz(e:MouseEvent):void {
// This function will be responsible for: // 1. pushing the user's answers to the aCorrectAnswers array // 2. updating to the next question

}
Let's first work on how to get the user's answer and add it to the aUserAnswers array. To do that, we'll use thepush() method of the array class. We'll get the contents of the answers_txt TextField using the text property, and then we'll pass that to the push() method like so: aUserAnswers.push(answers_txt.text) . So whatever text is inside the answers_txt TextField at the time the submit button is clicked will be added to theaUserAnswers array (the first value that is pushed to the array gets an index of 0, the next one after that will get an index of 1, and so on...). Then after each answer is pushed to the array, make the input TextField blank again, clearing it for the next question. So here's how the updated event listener function will look like:

function quiz(e:MouseEvent):void {

aUserAnswers.push(answers_txt.text); answers_txt.text = ""; // This line puts an empty string,


making the TextField appear empty again }

So after the user submits the answer, the next question should then be displayed. To display the next question, we'll need to retrieve it from the aQuestions array and assign it to the questions_txt TextField. Recall that we used questions_txt.text = aQuestions[nQNumber] (where nQNumber is initially equal to 0) in order to display the first question. The next question that follows has an index of 1. So in order to retrieve that next question, we will need to increment the value of nQNumber by 1 so that it goes from 0 to 1. Once it is incremented, we'll then assign aQuestions[nQNumber] to the questions_txt TextField once again. And then the next time the user clicks on the submit button, then nQNumber gets incremented by one again, allowing us to retrieve the item with the next index, and so on... Here's the updated event listener function:

function quiz(e:MouseEvent):void { aUserAnswers.push(answers_txt.text); answers_txt.text = "";

nQNumber++; questions_txt.text = aQuestions[nQNumber];


}

But wait! We aren't done yet. There are still some fixes that we need to put in this function. Recall that we have a limited number of questions. In this example, we only have 4. A problem will arise when the user clicks on the submit button for the fourth time. Why will there be a problem? There are 4 questions, so naturally, the user will end up clicking the submit button for a total of 4 times. Yes that is true. But the 4th time the user clicks on the button, nQNumber will be increased to 4. And recall that our array index numbers start at 0, not at 1. So the last question is actually at aQuestions[3]. AndaQuestions[4] is actually for a fifth question. But there is no fifth question, and trying to retrieve one from the array will cause an error. So what do we do then? We'll need to put an if statement that will tell our Flash movie to no longer try to retrieve any more questions, once we get to the last one. So let's do that now. We need to get the line questions_txt.text = aQuestions[nQNumber]; and place it in an if statement. The if statement needs to check if nQNumber is less than 4. If nQNumber is still less than 4, then go ahead and retrieve the next question. If it is no longer less than 4, then we don't want our code to retrieve any more questions. So we can type in if(nQNumber < 4) as our condition. But... that's actually not what we'll do. Instead of typing in 4, we'll use aQuestions.length instead. The length property of the array class tells us how many items there are in the array. So if an array has 5 items, then the array length will be 5. If it has 6 items, then the length will be 6. In this particular example, our array has 4 items, and therefore has an array length of 4. Why can't I just type in 4? Is there a benefit to using the length property instead? Well, no one is stopping you from hard-coding in a value of 4, but the great thing about making use of the lengthproperty instead is that if you decide to add more questions (or maybe remove some questions), then you won't have to go back to the if statement and hard-code in a new value. The length property will automatically update itself once you add or reduce items in the array. This will be especially useful if you had numerous items in your code that need to reference how long your array is. Imagine if you hard-coded the data numerous times in different parts of your code. Then every time you decide to add or subtract items to the array, then you'll have to go back to all those hard-coded parts of your code, and manually change the value. That would not be very efficient. So our updated event listener function will now look like this:

function quiz(e:MouseEvent):void { aUserAnswers.push(answers_txt.text); answers_txt.text = ""; nQNumber++;

if(nQNumber < aQuestions.length) {


questions_txt.text = aQuestions[nQNumber];

}
}

Great! So once the user gets through all the questions, what do we do next? We then tell the Flash movie to go to the next frame where the user will get the quiz results. To do that, we just add an else clause to our if statement that will instruct our Flash movie to go the the next frame. We will use the nextFrame() method of the MovieClip class to move the playhead to the next frame. So basically, what we're telling our Flash movie is that if nQNumber is no longer less than aQuestions.length, then it means that we don't have anymore questions and the quiz is done, and it can now move to frame 2 where the results will be displayed. So finally, our updated event listener function will look like this:

function quiz(e:MouseEvent):void { aUserAnswers.push(answers_txt.text); answers_txt.text = ""; nQNumber++; if(nQNumber < aQuestions.length) { questions_txt.text = aQuestions[nQNumber]; }

else {

nextFrame(); }
}

In the next part of this tutorial, we will work on the code that will display the answers that the user submitted alongside the correct answers. We will also work on the code that will check the answers and calculate and display the user's score. Here's the frame 1 code in full:

stop();

var nQNumber:Number = 0; var aQuestions:Array = new Array(); var aCorrectAnswers:Array "Titan"); = new Array("Jupiter", "Mars", "war",

var aUserAnswers:Array = new Array();

aQuestions[0] = "What is the biggest planet in our solar system?"; aQuestions[1] = "Which planet in our solar system is the 4th planet from the sun?"; aQuestions[2] = "Mars is named after the Roman god of ___."; aQuestions[3] = "What is the name of Saturn's largest moon?";

questions_txt.text = aQuestions[nQNumber];

submit_btn.addEventListener(MouseEvent.CLICK, quiz);

function quiz(e:MouseEvent):void {

aUserAnswers.push(answers_txt.text); answers_txt.text = ""; nQNumber++; if(nQNumber < aQuestions.length) { questions_txt.text = aQuestions[nQNumber]; } else { nextFrame(); } }

part 2
In the first part of this lesson, we added the functionality that will allow the user to take the quiz we added the questions and the correct answers, and we enabled the user to submit his or her own answers by using the input field and clicking on the submit button. All of that happens in frame 1 of our simple Flash quiz. In this part of the How to Create a Quiz in Flash using ActionScript 3 tutorial, we will be working on the following: 1. 2. Displaying the user's answers alongside the correct answers Checking the user's answers and computing the score

3. Displaying the user's score All of these will happen in frame 2 of our Flash movie. So let's go ahead and take a look at the elements that we have on this frame. Select frame 2 of the main timeline and take a look at the stage. You will see that there are 9 dynamic text fields. Out of these 9, there are 8 dynamic text fields that are distributed into 2 columns. Each column has 4 dynamic text fields. The ones on the left column will be used to display the answers that the user gave. The ones on the right column will display the correct answers. So what we want to do here is to just show the user some feedback so that he or she can compare his or her answers with the correct ones. And then there's one more dynamic text field right below the 2 columns. This one will be used to display the user's score. The instance names of of the dynamic text fields are as follows: TextFields for the USER's answers userAnswer0_txt, userAnswer1_txt, userAnswer2_txt,userAnswer3_txt TextFields for the CORRECT answers correctAnswer0_txt, correctAnswer1_txt,correctAnswer2_txt, correctAnswer3_ txt

TextField

for

the

SCORE

- score_txt

The TextField names for the answers have numbers in them so that they will match the index values of the answers in the arrays (aUserAnswers and aCorrectAnswers). userAnswer0_txt will be foraUserAnswers[0], userAnswer1_text will be for aUserAnswers[1], and so on... So now let's go ahead and add the code. Make sure you select frame 2 of Actions layer and then go to the Actions Panel. Let's first create a number variable:

var nScore:Number = 0; This variable is going to be used to store the user's score. I'm initializing it to 0 just in case the user does not get any answer correctly. If that happens then the score will just stay at 0. Ok, so we'll go back to that variable later. For now, let's work on the code that will display the answers in their respective text fields. We will get the data from the arrays using array access notation, and assign each piece of data to it's corresponding text field using the text property of the TextField class. We can do it this way:

userAnswer0_txt.text = aUserAnswers[0]; userAnswer1_txt.text = aUserAnswers[1]; userAnswer2_txt.text = aUserAnswers[2]; userAnswer3_txt.text = aUserAnswers[3];

correctAnswer0_txt.text = aCorrectAnswers[0]; correctAnswer1_txt.text = aCorrectAnswers[1]; correctAnswer2_txt.text = aCorrectAnswers[2]; correctAnswer3_txt.text = aCorrectAnswers[3]; If you add in this code and then test the movie, you should see all the answers displayed in the text fields after you answer all the questions. So at this point, we can actually move on to the next part of the code that will check whether the answers the user gave are correct. But before we do that, I'd like to show you another way of displaying the answers in the TextFields. Instead of manually assigning each item to its corresponding text field one by one, we'll use a for loop instead. So go ahead and remove or comment out the code above, and we'll try this other method of displaying the answers. Ok, so in the first textField.text ex. correctAnswer0_txt.text method, we = = displayed the answers this way: array[index]; aCorrectAnswers[0];

For this other method that we're doing, we need to learn another way of targeting our TextField. For example, instead of typing in correctAnswer0_txt.text, we can replace correctAnswer0_txt withthis["correctAnswer0_txt"] instead. So this is what we'll have: this["correctAnswer0_txt"].text = aCorrectAnswers[0]; This is but another way of targeting our display objects (like Buttons, MovieClips and TextFields). Let's take a look at the example again: this["correctAnswer0_txt"] Here, since our code is placed in the main timeline, then the this keyword in this instance would refer to themain timeline. And then inside the square brackets, we place the name of the child object that we want to target (the name must be specified as a string, so it should be in quotation marks). So what we're doing here is we are telling Flash to target the correctAnswer0_txt TextField which can be found inside this (which in this example would be the main timeline). So what is the benefit of writing it this way instead? In this other method of targeting display objects, we are specifying the name of the instances as strings. Because we're doing it this way, we can replace the numbers in the names with variables instead. That way, we can just have that variable be incremented inside a for loop so that we don't have to hard code in the numbers for each text field (here you see why it's important that we numbered our text fields within their respective names). If this sounds a bit confusing, let's take a look at how the new text assignment statement will look inside of the for loop: this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i]; Here, the numbers are replaced with the variable i. For the text field's name, the join operator (+) is used to combine the variable with the rest of the name. Then as the for loop updates, so does i, therefore allowing us to iterate through the text fields and the items in the arrays. Note that i is a number, and it is being combined with strings. In this example, there is no need to convert i into a string. Because the number data is being combined with strings, Flash will automatically convert that number data into a string. So now let's go ahead and write ourfor loop. We'll start with the variable i being equal to 0, and then as long as i is less then aQuestions.length, we'll keep the for loop running (you can also use aCorrectAnswers.length or aUserAnswers.length since they all have the same lengths anyway). So our for loop will look like this:

for(var i:Number = 0; i < aQuestions.length; i++) { this["userAnswer" + i + "_txt"].text = aUserAnswers[i]; this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i]; }

So the first time the for loop runs, i will be equal to 0, therefore aUserAnswers[0] and aCorrectAnswers[0]will be assigned to the userAnswer0_txt and correctAnswer0_txt TextFields respectively. Then as iupdates, the rest of the items in the arrays will be assigned to their respective text fields as well. Go ahead and test your movie and you should see that this will yield the same results as with the

previous method that we used. This second method would be more efficient to use since we won't have to type in the text assignment statements one by one. Imagine if our quiz had 100 questions! Ok, so now we can move on to the part that checks whether the user's answers are correct. So how do we write the code that will determine whether each answer is correct or not? If the answer that the user submitted is the same as the corresponding item in the aCorrectAnswers array, then it means that the user got the correct answer. We know that the user's answers are stored in the aUserAnswers array so we could just compare if the items in aUserAnswers match their partners (the ones with the same index value) in theaCorrectAnswers array. We'll use an if statement for that. For each match that is detected, we will give the user a point by incrementing nScore by 1 (nScore is that variable that we created earlier, which was initialized to0). We will place that if statement in the for loop as well, since we want to go through each item in both of the arrays. So our updated for loop is now:

for(var i:Number = 0; i < aQuestions.length; i++) { this["userAnswer" + i + "_txt"].text = aUserAnswers[i]; this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i];

if(aUserAnswers[i] == aCorrectAnswers[i]) { nScore++; trace(nScore); }


}

So what the if statement in the for loop will do is it will compare the items with the same index value from both arrays. Each time they match, then nScore gets incremented by 1. I've added in a trace statement so we could verify if the correct computation is being made. But there's still one more modification that we need to make with regard to the comparison of the answers. You see, when strings are being compared, the process is case-sensitive. So a lower case a will not be considered equal to an uppercase A. So what happens here is that the user may have submitted the correct word, but if the casing of even just one letter is different from the item in theaCorrectAnswers array, then it will not be considered equal and the user will not be given the corresponding point. In order to fix this, we need to make sure that when the items are compared, the strings from both arrays have identical casings. It doesn't matter if they are in uppercase or lowercase, the important thing is that they are the same. So what we can do is, we can convert the casing to either uppercase or lowercase when the items are being compared in the if statement. We can convert the items by using either the toUpperCase() ortoLowerCase() methods of the String class. I'm going to use the toUpperCase() method. So let's go ahead and update the code:

for(var i:Number = 0; i < aQuestions.length; i++) { this["userAnswer" + i + "_txt"].text = aUserAnswers[i]; this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i]; if(aUserAnswers[i].toUpperCase() aCorrectAnswers[i].toUpperCase()) { nScore++; trace(nScore); } } ==

So now, when each pair is compared, they will be converted into the same casing. Note that this will not affect how the words are displayed in the text fields. The conversion to upper case (or lower case, if that's what you chose), will only be for the if statement condition in this example. So now, if you test the movie and try out the quiz again, you should see nScore update in the output window (provided that you get at least one answer right, if you don't get any answers right, then nScore never gets updated and won't get traced). Lastly, we'd like to display the final score in the score_txt text field. We'll display the score once the for loop has finished checking all the answers. To check whether the for loop is finished, we can check whether i is equal to aQuestions.length - 1. If i is equal to the array length minus one, then it means that the for loop is already at the last item (we subtract the length by 1 because the index values start at 0, where as the length count starts at 1). So we'll use another if statement inside the for loop to check for that. If i is equal toaQuestions.length - 1, then we assign nScore to score_txt using the text property of the TextField class (be sure to convert nScore to a string using the toString() method). So let's go ahead and update the code:

for(var i:Number = 0; i < aQuestions.length; i++) { this["userAnswer" + i + "_txt"].text = aUserAnswers[i]; this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i]; if(aUserAnswers[i].toUpperCase() aCorrectAnswers[i].toUpperCase()) { ==

nScore++; }

if(i == aQuestions.length - 1) { score_txt.text = nScore.toString(); }


}

So Here

there

you is

have

it. the

Our

quiz code

app

is in

now

complete. full: 1

FRAME

stop();

var nQNumber:Number = 0; var aQuestions:Array = new Array(); var aCorrectAnswers:Array "Titan"); = new Array("Jupiter", "Mars", "war",

var aUserAnswers:Array = new Array();

aQuestions[0] = "What is the biggest planet in our solar system?"; aQuestions[1] = "Which planet in our solar system is the 4th planet from the sun?"; aQuestions[2] = "Mars is named after the Roman god of ___."; aQuestions[3] = "What is the name of Saturn's largest moon?";

questions_txt.text = aQuestions[nQNumber];

submit_btn.addEventListener(MouseEvent.CLICK, quiz);

function quiz(e:MouseEvent):void { aUserAnswers.push(answers_txt.text); answers_txt.text = ""; nQNumber++; if(nQNumber < aQuestions.length) { questions_txt.text = aQuestions[nQNumber]; } else { nextFrame(); } }

FRAME

var nScore:Number = 0;

for(var i:Number = 0; i < aQuestions.length; i++) { this["userAnswer" + i + "_txt"].text = aUserAnswers[i]; this["correctAnswer" + i + "_txt"].text = aCorrectAnswers[i]; if(aUserAnswers[i].toUpperCase() aCorrectAnswers[i].toUpperCase()) { ==

nScore++; } if(i == aQuestions.length - 1) { score_txt.text = nScore.toString(); } }

PREV: How to Create a Quiz in Flash - ActionScript 3 Tutorial - PART 1

Das könnte Ihnen auch gefallen