AppInventor: MathBlaster

From OnnoWiki
Jump to navigation Jump to search

Sumber: http://www.appinventor.org/content/ai2apps/intermediateApps/mathBlaster


Math Blaster

The Khan Academy (khanacademy.org) revolutionized on-line education and taught Math to millions with its video and interactive lessons. One thing the site does is generate practice problems for students to test their Math skills. In this chapter, you'll learn how to build a mobile app that generates arithmetic problems and checks the students answers, just like it is done on khanacademy.org! You can use what you learn as a template for building educational apps of all types.

What You'll Learn

   Working with lists of dynamic (changing) data.
   Coding repeat blocks (Iteration)
   Generating random numbers
Appinventor-mathblaster1.png



Define and Display a List of Numbers

An important strategy in programming is to break down a problem into small parts, then tackle each part separately by building and testing blocks of code. Though the ultimate goal of this tutorial is to build an complete math blaster that generates random problems and checks them, you'll start with a more focused problem: defining a list and displaying that list in the user interface.

Set-up a Test User Interface

To begin, create a test user interface in the Designer. The final user interface will be different, but don't worry about that for now. Create a new project named "MathBlaster" and drag out the following components:

   A label for displaying the list. Name it "NumbersLabel".
   A label for displaying the sum. Name it "SumLabel".
   A button named "ComputeButton" with the text "Compute Sum".
Appinventor-mathblaster2.png


Define the List Variable

Now that you've set up the user interface for this initial sub-goal, open the Blocks Editor. For this app, you need a variable to hold the list of numbers to be added up. For now, define the list with the numbers 5, 11, and 7, and later on we'll make it so the numbers are randomly generated. In the Blocks Editor, drag out an initialize global block from the Variables folder, a make a list block from the List folder, and three number blocks from the Math folder. Name and connect the blocks in the following manner:

Appinventor-mathblaster3.png

Display the List

The numbers list variable, like all variables, is part of the app's hidden memory. If you want such data to appear in the user interface, it must be displayed explicitly, typically in a label. You want the list displayed when the app starts, so you'll add blocks to set the NumbersLabel in the Screen1.Initialize event handler:

Appinventor-mathblaster4.png

The list is displayed in the default manner that occurs when you place a list directly into a label. Specifically, the items of the list are separated with spaces and the entire list is displayed within parenthesis.

Challenge 1: Add up a List of Numbers

A second sub-goal for the app is to compute the total of the numbers in order to check the student's arithmetic. Keep in mind that you want blocks that will sum the list of numbers generically, i.e., even if the items were changed or items were added, the computation would still work.

In the final app you won't show the answer at all, you'll just compare the sum to whatever the user enters. But you're still working on an intermediate goal here, a test app. Your immediate goal is to sum the numbers and just display the result in the label named SumLabel.

How Does Your Brain Add Up Numbers?

Ask a friend to shout out some numbers to you while you sum them up. How do you do it? Our brains tends to work on auto-pilot, so this is not an easy question to answer. But to become a good programmer, you must learn to shut off the auto-pilot and examine your brain processes closely.

If you're like most people, your "algorithm" for summing numbers is something like the following: Take the first number and remember it, then when the second number comes, add it to the first and remember the total. When the third number comes, add it to the previous total, and so on. Your app needs to follow a similar algorithm, but of course translating the dImage:Appinventor-mathblaster5.pngescription to blocks is not so easy! First, you need a way to program, the "and so on" part of the description as you need a solution that will work no matter how many numbers are in the list (we want math problems of all sizes!). In programming, "and so on" is coded with iteration , that is, code that tells the app to repeat something some number of times.

App Inventor, and most languages, provide a foreach construct, which basically says, "do the blocks inside for each item in the list":

Appinventor-mathblaster5.png

If the list has three items, like our sample, the blocks inside the foreach will be repeated three times. If the list has four items, the blocks inside will be repeated four times, and so on. For the sample numbers list, the variable item will hold the value 5 on the first iteration, 11 on the second, and 7 on the third. So foreach is exactly what you want.

But what do you want to do for each of those iterations-- what blocks go within the foreach? You want to add the next number in the list to a running total. Anytime your app needs to remember something, like a running total, you define a variable. In this case, you can define a variable "total" and give it an initial value of 0:

Appinventor-mathblaster6.png

For each item in your list, you add the item to the variable total. When the foreach completes (three iterations in this case), you can display the calculated total in a label:

Appinventor-mathblaster7.png

Design the User Interface

Now your app can create and display a list of numbers, and even add them up. Now its time to create the user interface for the complete version of MathBlaster. You'll need to rename some of the components, but your ultimate goal is for the user interface to appear as on the right. You'll need:

  • A new label for the "add up the following numbers:".
  • Keep the "NumbersLabel" as is.
  • A text box for the user's answer. Name it "AnswerText" and set its hint property to "enter the sum here".
  • Two buttons, one named "AnswerButton" and one named "NextButton". The best way to do this is to just rename the ComputeButton "AnswerButton", then create a new button named "NextButton".
  • A label that will say whether the user's answer is correct or not. Name it "AnswerCheckLabel".
Appinventor-mathblaster8.png

Challenge 2: Compare the Computed Answer to the User's Answer

Now that your app knows how to add, you can set up it so the user can answer and have her answer checked. When the user clicks the AnswerButton, the app should still add up the numbers in the list. Instead of displaying that answer, the app should compare it-- the computed total-- to the answer submitted by the user in AnswerTextBox. Depending on the result, the app should display "correct" or "incorrect" in the AnswerCheckLabel:


Appinventor-mathblaster9.png


Challenge: Debugging the App

If you code the app with the blocks above, the app will not behave correctly. Before moving on, try to identify and fix the bug. When you are ready, click on "View Answer"


Jawaban

The given solution works the first time the AnswerButton is clicked, but not the second. The problem is that the variable total is not reinitialized to zero on each click. So after the first time the button is clicked, total is set to 23. When the second click occurs, and AnswerButton.Click is triggered again, the list items will be added to the current value of total (23) and the result will be 46.

The solution is simple: set total to zero at the top of the event handler:

Appinventor-mathblaster10.png


Challenge 3: Generating a List of Random Numbers

The app thus far isn't much fun because the same problem is asked over and over. The next step is to add a "Next Problem" button and make it so that the app generates random problems each time it is clicked.

For now, assume that you always want to generate exactly three random numbers. Later, you can modify the code so that problems of different sizes are generated. Also, assume that the numbers should be randomly chosen within the range 1-20.

Here are the blocks for the NextButton.Click event handler:

Appinventor-mathblaster11.png


The blocks first empty out the numbers list by setting it to an empty make a list block. Then add items to list is called to add the three random numbers. Finally, the NumbersLabel is updated to display the list and the AnswerTextBox is modified to erase the previous answer.

Challenge 4: Generating a Random Number of Random Numbers

So you now have a "Math Blaster" app but all the problems are exactly three numbers long. The next step is to eliminate this restriction so questions of different lengths will be generated and asked.

Your task is to change the app so that the list of numbers has between two and five items on each question. For such a task, foreach isn't useful as you are not trying to iterate over the items of an existing list (you are creating a new one!). Instead, you need a while or for range as in the following solution:

Appinventor-mathblaster12.png

With a for range, the blocks within the "do" are performed some number of times as defined by a range. Think of the range i as a counter or index. In this case, it starts out as 1, on the first iteration. Each time the inner block (add items to list) is performed, the step (1) is added to i, until it reaches the end, which in this case is a random number between 2 and 5. So if the random integer generated is 4, the range will be 1-4 and the inner block will be performed four times.

Note that the blocks within the NextButton.Click event handler should be copied to the Screen.Initialize event handler, as the first question should also be generated with a random number of items as opposed to the "fixed" three items in the numbers list definition. Furthermore, the numbers definition should have an empty make a list block within it instead of the three items that we used for the initial version of the app. An empty make a list block is a common pattern for defining a "dynamic" list: you are defining a list to hold items, but the items are generated as the app runs. Here are the blocks for these updates:

Appinventor-mathblaster13.png

Challenge 5: Showing the + Signs in the Arithmetic

As is, the app displays the list of numbers within parenthesis and with spaces, not + signs, separating the numbers. Your next task is to change this so that a proper addition equation is displayed. For example, for the default list, your app should display "5+11+7", not "(5 11 7)"

App Inventor doesn't provide a simple way to format list items nicely, so you'll have to use iteration-- a foreach-- to walk through the list of numbers and build a text string with "+" between the numbers. You will build the text in NumbersLabel step-by-step, adding a number and a plus on each iteration:

Iteration 	NumbersLabel
1 	        5
2 	        5+11
3 	        5+11+7

Here are the updated blocks:

Appinventor-mathblaster14.png

Instead of just dumping the list into NumbersLabel, the label is built a number at a time, with the join block taking care of adding the "+" between each number.

Challenge: Debugging the App

The blocks above are close but not quite right. Before moving on, test the app and try to identify the issues and fix them. When you are ready, click on "View Solution"

Jawaban

The given solution leaves an additional "+" at the end of the equation, e.g., 5+11+7+. There are a number of ways to fix this, including using a different iteration block such as while-do or for range. If the foreach block is retained, you need to add some blocks to "post-process" the label and remove the last "+":

Appinventor-mathblaster15.png

The segment block takes a part (segment) of some text, in this case starting from the first character and taking all but the last character (the unwanted "+").

Note that you'll need to update the Screen.Initialize event handler with these blocks as well so the first question will appear correctly

Refactoring

Effective software engineers know that having redundant code (blocks) in an app is bad practice: if something changes, you have to find all copies of the code and make the change. Copying and pasting blocks, as done above, is a sub-optimal solution. A better solution involves refactoring the blocks and defining a procedure.









Referensi