Tutorials

MoleMash with Hall of Fame

Goal:

In this lesson, you will:

  • Learn how to use timers in your apps
  • Learn how to pick a random number
  • Use image sprites
  • Use procedures
  • Learn about databases

Step 0: Learn about Databases

Variables are great for storing information while your user is using your app, but what if you wanted to store information between the times when your user opens and closes her app? You can do this with a database. Databases can store information for later use, even when the app is closed! You can think of databases as a place to store information you can recall later. Here are some examples of databases you may use every day:

  • Contact list – you store your friend’s phone numbers so you can use them later
  • Messaging app – most messaging apps automatically store old messages so you can reread them later
  • Notebook – you write things down and read them later

In App Inventor, the component TinyDB allows you to save data on your user’s phone that will be there each time she logs into your app. It is important to know that TinyDB only allows you to store data locally. This means that two users cannot share data with the same TinyDB. When a user stores data into TinyDB, it will only be available on her phone, and no one else’s.

To use TinyDB, drag it onto your screen in the designer side of App Inventor. You can find it under the storage menu. It will appear as a non visible component and will look like this:

TinyDB

You can talk to your TinyDB by making calls to it. When you make a call, you can store things and get things from it. The way you store data in TinyDB is by giving it a tag. The tag is a name that you will use to retrieve the data. It is a lot like a variable name. If you use the same tag name to store data twice, the database will overwrite, or erase, the old data with the new data. This can be useful if you need to update what’s in your database but you should be careful never to repeat tag names otherwise! Here’s a few examples of how to make calls to TinyDB:

TinyDB store global fruits

The first block shows how to store values in TinyDB. In this case we stored our fruits list from earlier with the tag “Food”. The second block shows how to retrieve the fruits list from the database. The tag needs to be typed exactly as it was when the data was stored, including all capital letters.

To better understand this, let’s walk through an example. Let’s say you needed to store three things in a database for later use. One is our Fruits lists from the last section, one of them is your age, and the other is a list of your favorite things to do. You make three to calls to the database like this:

TinyDB store global fruits
Tiny DB my age
TinyDB store favorites list

You now have three entries in you database, and this what they look like:

Tag Name: “Food”

Data:

  • “Apples” (index = 1)
  • “Bananas” (index =2)
  • “Oranges” (index = 3)

Tag Name: “My Age”

Data:

  • 16

Tag Name: “Favorite”

Data:

  • “Learn how to Code” (index = 1)
  • “Visit Family” (index = 2)
  • “Listen to Music” (index =3)

Now, when you want to retrieve your favorite things to do, so you make a call like this:

TinyDB favorites value not tagged

When you use this block you will get “Learn how to Code Visit Family Listen to Music”. Now let’s say you want to retrieve your age, so you make a call like this:

TinyDB my age value tag if not there

When you use this block you just get a blank string: “ ”. This is because the tag “myage” does not exist in your database! However, the tag “MyAge” does exists. Since your database did not recognize the tag, it defaulted to show you the block next to “valueIfTagNotThere”, which is a blank string. You can make this string say anything you want. You can even make it be an error message to your user.

If you create an app with multiple screens (like your slideshow app), components and variables will not be able to talk to each other between each screen. You will need to use a TinyDB in order to transfer information from one screen of your app to another. Visit this page for more information: MIT Screens.

Step 1: Basic Design

In this game, a mole pops up at random positions on a playing field, and the player scores points by hitting the mole before it jumps away.

You will need to download this picture of a mole and save it on your computer.

The first components

You will need a few components to start:

  • A Canvas named “MyCanvas”. This is the area where the mole moves.
  • A Label named “ScoreLabel” that shows the score, i.e., the number of times the player has hit the mole.
  • A Button named “ResetButton”.

Drag these components from the Palette onto the Viewer and assign their names. Put MyCanvas on top and set its dimensions to 300 pixels wide by 300 pixels high. Set the Text of ScoreLabel to “Score: —“. Set the Text of ResetButton to “Reset”. Also add a Sound component and name it “Noise”. You’ll use Noise to make the phone vibrate when the mole is hit.

Timers and the Clock component

You need to arrange for the mole to jump periodically, and you’ll do this with the aid of a Clock component. The Clock component provides various operations dealing with time, like telling you what the date is. Here, you’ll use the component as a timer that fires at regular internals. The firing interval is determined by the Clock ‘s TimerInterval property. Drag out a Clock component; it will go into the non-visible components area. Name it “MoleTimer”. Set its TimeInterval to 500 milliseconds to make the mole move every half second. Make sure that TimerEnabled is checked.

Adding an Image Sprite

To add the moving mole we’ll use a sprite.

Sprites are images that can move on the screen within a Canvas. Each sprite has a Speed and a Heading, and also an Interval that determines how often the sprite moves at its designated speed. Sprites can also detect when they are touched. In MoleMash, the mole has a speed zero, so it won’t move by itself. Instead, you’ll be setting the mole’s position each time the timer fires. Drag an ImageSprite component onto the Viewer. You’ll find this component in the Drawing and Animation category of the Palette. Place it within MyCanvas area. Set these properties for the Mole sprite:

  • Picture: Use mole.png, which you downloaded to your computer at the beginning of this tutorial.
  • Enabled: checked
  • Interval: 500 (The interval doesn’t matter here, because the mole’s speed is zero: it’s not moving by itself.)
  • Heading: 0 The heading doesn’t matter here either, because the speed is 0.
  • Speed: 0.0
  • Visible: checked
  • Width: Automatic
  • Height: Automatic

You should see the x and y properties already filled in. They were determined by where you placed the mole when you dragged it onto MyCanvas. Go ahead and drag the mole some more. You should see x and y change. You should also see the mole on your connected phone, and the mole moving around on the phone as you drag it around in the Designer. You’ve now specified all the components. The Designer should look like this. Notice how Mole is indented under MyCanvas in the component structure list, indicating that the sprite is a sub-component of the canvas.

molemashdesigner

Excellent!  We are now ready to move onto the Blocks.

Step 2: Basic Building Blocks

Component Behavior and Event Handlers

Now you’ll specify the component behavior. This introduces some new App Inventor ideas. The first is the idea of a procedure. For an overview and explanation of procedures, check out the Procedures page.

A procedure is a sequence of statements that you can refer to all at once as single command. If you have a sequence that you need to use more than once in a program, you can define that as a procedure, and then you don’t have to repeat the sequence each time you use it. Procedures in App Inventor can take arguments and return values. This tutorial covers only the simplest case: procedures that take no arguments and return no values.

Define Procedures

Define two procedures:

  • MoveMole moves the Mole sprite to a new random position on the canvas.
  • UpdateScore shows the score, by changing the text of the ScoreLabel

Start with MoveMole:

  • In the Blocks Editor, under Built-In, open the Procedures drawer. Drag out a to procedure block and change the label “procedure” to “MoveMole”.
    Note: There are two similar blocks: procedure then do and procedure then resu;t. Here you should use procedure then do.

    The to MoveMole block has a slot labeled “do”. That’s where you put the statements for the procedure. In this case there will be two statements: one to set the mole’s x position and one to set its y position. In each case, you’ll set the position to be a random fraction, between 0 and 1, of the difference between the size of the canvas and the size of the mole. You create that value using blocks for random fraction and multiplication and subtraction. You can find these in the Math drawer.

  • Build the MoveMole procedure. The completed definition should look like this:
    movemole

MoveMole does not take any arguments so you don’t have to use the mutator function of the procedure block. Observe how the blocks connect together: the first statement uses the Mole.X set block to set mole’s horizontal position. The value plugged into the block’s socket is the result of multiplying:

  1. The result of the call random fraction block, which a value between 0 and 1
  2. The result of subtracting the mole’s width from the canvas width

The vertical position is handled similarly.

With MoveMole done, the next step is to define a variable called score to hold the score (number of hits) and give it initial value 0. Also define a procedure UpdateScore that shows the score in ScoreLabel. The actual contents to be shown in ScoreLabel will be the text “Score: ” joined to the value of score.

  • To create the “Score: ” part of the label, drag out a text block from the Text drawer. Change the block to read “Score: ” rather than ” “.
  • Use a join block to attach this to a block that gives the value of the score variable. You can find the join block in the Text drawer.

Here’s how score and UpdateScore should look:
updatescore

Add a Timer

The next step is to make the mole keep moving. Here’s where you’ll use MoleTimer. Clock components have an event handler called when … Timer that triggers repeatedly at a rate determined by the TimerInterval.

Set up MoleTimer to call MoveMole each time the timer fires, by building the event handler like this:
molemashtimereventhandler

Add a Mole Touch Handler

The program should increment the score each time the mole is touched. Sprites, like canvases, respond to touch events. So create a touch event handler for Mole that:

  1. Increments the score.
  2. Calls UpdateScore to show the new score.
  3. Makes the phone vibrate for 1/10 second (100 milliseconds).
  4. Calls MoveMole so that the mole moves right away, rather than waiting for the timer.

Here’s what this looks like in blocks. Go ahead and assemble the when Mole.Touched blocks as shown.

molemashtoucheventhandler

Here’s a tip: You can use typeblocking: typing to quickly create blocks.

  • To create a value block containing 100, just type 100 and press return.
  • To create a MoveMole block, just type MoveMole and select the block you want from the list

Reset the Score

One final detail is resetting the score. That’s simply a matter of making the ResetButton change the score to 0 and calling UpdateScore.

Step 3: High Score

At this point, you have a functioning game — way to go!  Next, we’ll modify our game to include a High Score for players to beat.

To do this, we’ll use a TinyDB component.  Remember that a TinyDB component is a database that lets us store data between each use of the app — so if the user closes the app and comes back later, the information we put in the database will still be there.

Components

On the Design tab, drag a TinyDB component into your app.  It will show up below the screen as a “Non-visible component.”

You will also need another label.  Draw another Label component in and name it “HighScoreLabel”.  Put “High score: 0” in the Text property of this label.

Your design should look something like this:
screen-shot-2017-02-01-at-10-09-06-am

Now we’re ready for blocks.

Build

The basic logic we want to follow goes like this:

  • When the player is done playing (ie, they click the “Reset” button),
  • If their score is greater than the high score,
  • Update the high score in the database and update the high score on the screen
  • Then reset the score (just like we’ve been doing)

We’ll need to build a few things to make this happen.

To do this, we need some more things to happen when the Reset button is clicked.  Find your “when Reset.clicked” block and add an “if” block from the control section:
screen-shot-2017-02-01-at-10-12-02-am

We are checking if our score is greater than the high score, so we need to compare the two values:
Screen Shot 2017-02-01 at 10.15.47 AM.png

If our score is greater than the high score, then what?  Then we need to update the high score in the database and update the high score on the screen.
screen-shot-2017-02-01-at-10-19-33-am

This looks great!  We’ve built the logic we planned out.

There’s one more trick to make this work — we need to make sure our app is prepared for a tricky situation.  Right now, when a player opens our app and hasn’t pressed the Reset button, they’ll see a high score of zero, no matter what!  To fix this, we need to add some behavior that controls what happens when the screen is very first initialized:
screen-shot-2017-02-01-at-10-21-15-am

That’s it!  Test it out — does it work?  If so, time to whack some moles!  If not, put on your best problem solving hat and get to tinkering!

Congrats!

You have a fabulous new game app that you made yourself — that’s awesome!

What’s next?

Credits

This tutorial is a melding of the following resources:

Advertisements

Dual-Mode Magic 8-Ball

Goal:

In this lesson, you will:

  • Learn how to include images and sounds in AppInventor
  • Learn about data and different data types
  • Learn how to use variables
  • Learn to organize data into lists
  • Make a magic 8 ball app that can answer two types of questions

Step 0: Learn about Data Types

Data

At some point in your life, you’ve probably heard the word data. Data can mean a lot of things, but in computer science, data is the information that your app needs in order to work. To better understand this, let’s think about some apps and some of the information that they need in order to work.

WhatsApp logo

WhatsApp

This social app can message and call contacts. The data it needs is:

  • Your username
  • Your friends’ usernames
  • Messages you want to send
  • The time
  • Your location

Angry Birds logo

Angry Birds

In this game app you shoot birds at pigs to defeat them. The data it needs is:

  • Your score
  • How many points each object is worth
  • What levels you’ve completed
  • How many birds you get in each level

The programmer needs to set up ways for the app to get all the information it needs. Remember, computers can’t do anything on their own without instructions. Here are a few ways that apps in App Inventor can get data to use:

  1. The programmer put the information in:
    • In your slideshow app, you (the programmer) entered in your favorite images.
    • In Angry Birds, the programmer entered in how many birds the player gets on each level.
  2. The user enters the information:
    • In WhatsApp, the user needs to tell the app what she wants to send and who she wants to send it to.
  3. The app connects to another place to get information:
    • WhatsApp connects to your phone to get the time so it knows what time you sent a message.

Sometimes an app will save information the user put in. For example, WhatsApp saves message history which allows you to see the last message you sent to a friend. To do this in, the programmer uses a database, which you will learn about in another lesson. You will also learn more about how to connect to other places to get information later.

Thought Exercise

If you were using an app that helps you find the nearest grocery store, what data do you think the app needs to have?

Data Types

As you saw in the section above, data can be a lot of things! To make it easier for computers to understand what to do with the data they are given, data is put into categories. This is known as a data type. Programming languages revolve around three major data types: numbers, strings, and booleans. App Inventor also lets you use more complex data types such as colors and images. You don’t need to do anything with data types you’ll learn about in this section but it will be good to keep them in mind as you code more.

Numbers

A number data type is just what you think it is! In App Inventor, you can use numbers by  going to Math in blocks.

You will use Math blocks whenever you need to use numbers. Here are some examples of when you might use a number data type in an app:

  • Calculating a player’s score in a game
  • Counting how many times a user has tried to log in
  • Counting how many times you want your app to do something
  • Checking to see if your user is a certain age

Optional: To learn more about all the things you can do with math blocks check out MIT’s website: Math blocks

Strings

A string data type is text. In App Inventor, you can create a string by going to Text in Blocks. Here are some of the text blocks you can use.

You should use a string anytime you want to add a text field to your code. Here are some examples of when you might use a string data type in an app:

  • Allowing the the user to enter a password or username
  • Having the app speak words to the user
  • Showing a message or an alert to the user
  • Programming the app to open a new screen by giving it the screen name

Optional: Before moving on check out MIT’s website to see all the things you can do with text: Text blocks

Booleans

A boolean can be one of two values: true or false. True basically means “yes” and false basically means “no”. To get a boolean, go to Logic in blocks and grab one of these blocks:

For now, there is not much to do with booleans other than keep them in mind. Booleans and logic will be covered in more detail in another lesson.

Variables

variable. A variable is a name for a piece of data that can change in value. An easy way to remember this is that a variable can vary, or change in value. There’s lots of information that is important to you every day that changes value. Here are some examples:

  • Your age
  • Your height
  • Your location
  • Today’s date

To better understand variables and how to use them in App Inventor, let’s walk through an example. Imagine you are creating a game where the user can earn and lose points. You want to have a score for the player to see in a text box. At the start of the game, the player has zero points so you added a block like this to the game.

The player sees zero in the textbox that contains her score. However, the player’s score will change as she plays the game. Each time she gains or loses points you have to update the text box. When she gets more points, you add a block like this.

That works, but now what about the next time the player earns 10 points? You’ll have to update the text again to say 20. Then what if the player loses points? You will have to change her score to 15. What if she gains points again? This can get confusing really fast.

In scenarios like this, you can create a variable to keep track of the player’s score. You can create a variable called score that always has the value of the player’s current score. As she plays the game, you can add and subtract points from score and you won’t need to worry about keeping track of what the her current score actually is. Here’s how it would work in App Inventor. First you would grab this block from the variables section.

This block tells the app that there will be a variable and asks you to give the variable a name and a value. Here’s what the block would look like for a game where the player’s score started at zero.

With this block, you are telling the app that there will be a piece of data called score and that it will change value as the game is played. Every time the app starts up, it is going to create a variable called score and set it zero. Now you can do what’s called “set” and “get” your score variable. “Get” will allow you to see what the value of the score is. Here’s how you would tell your app to display the score in a textbox.

“Set” allows you assign a new value for your user’s score. Every time the player earns points you can tell the app to do this.

This tells your app to change the value of the score to whatever it is now and add ten to it. If the current score is zero, the new score would be 10. If the current score is 25, the new score would be 35. Now you don’t have to worry about reassigning the score every time your player gains or loses points. The app will just take the current score and add 10 to it.

It is okay if you are still confused about variables! They are really hard to understand and the best way to understand them is by using them. You will use them today and again and again as you become a great coder!.

Step 1:

The final Magic 8-Ball App will deliver a prediction from a list that you have designed – and it will be able to answer both Number questions and Yes/No questions. To get started, first we’ll make our main screen, and program our app to play a sound when the user shakes the phone.

Design:

  1. Open a new tab or window and go to ai2.appinventor.mit.edu.
  2. If you have already made an app, you will automatically be directed to the Designer with the last project you worked on showing. Click “Project” in the upper left corner of the screen and then “My Projects”, which will take you to your list of projects. Click “New Project” and name your project something like “Magic8Ball” (note: spaces are not allowed).
    newproject
  3. Download one image and one sound file from below to be used in your app. Right click (control-click) on the link of the image or sound, then choose “Download” or “Save As”. Save the media files to a convenient location that you will remember.
  4. On the left column of the Designer, the User Interface palette should be open.  If it is not, click to open it.  Drag an Image component over to the Viewer.
  5. Set the image to an 8-ball image:
    Click on your newly added image to see its properties in the Properties pane on the right.  Under “Picture” click on the word “None…” and a small selection window will pop up.  Click the “Upload File” button and browser to where you saved the 8-Ball image.  Select the file, then click “OK” to close the selection window.  Click “OK” again on the properties pane to close the small popup window.
    screen-shot-2017-01-16-at-3-51-28-pm
  6. From the Media palette, drag over a Sound component onto the Viewer pane.  The Sound component plays sound files.  Notice that since the sound component will not be a visible part of the app, it appears at the bottom of the Viewer pane, as a “Non-visible component.”
    screen-shot-2017-01-16-at-3-56-48-pm
  7. Set the Sound component’s source file:
    Click on your newly added Sound component to see its properties in the Properties pane on the right.  Under “Source” click in the small box on the word “None…” and a small selection window will pop up.  Click the “Upload File” button and browse to where you saved the sound file.  Select the sound file, then click “OK” to close the selection window.  Click “OK” again on the properties pane to close the small popup window.
  8. We need one more piece to make our app work: a sensor that can tell when the phone is moving, so our user can shake the phone to get their predictions.  From the Sensors palette, drag an AccelerometerSensor component onto the Viewer.  Notice that it will show up below the screen, like the sound, because it’s another non-visible component.
    screen-shot-2017-01-16-at-3-57-33-pm

Build:

  1. In the upper right corner of the Designer, click on the Blocks button.
    Now you are going to tell your app how to behave when the user shakes the phone.  This is actually very simple in App Inventor, because the “code” for the program only consists of two blocks!
    Once the Blocks Editor is open, there are several options running along the left side of the screen.  We refer to these as “Palettes” with “Drawers.”
  2. From the blocks palette located under Screen1, click on the AccelerometerSensor1 drawer.  Drag the “when AccelerometerSensor1.shaking” block into the work area.
  3. From the blocks palette, click on the Sound1 drawer, drag the “Sound1.Play” block into the work area and insert it into the “when AccelerometerSensor1.Shaking” block.  They will click together like magnetic puzzle pieces.
    Your blocks should now look like this:
    screen-shot-2017-01-15-at-10-34-43-am
    That’s it!  You’ve written the program for Part One of Magic 8-Ball.  Now it’s time to test that it’s working right.
    Go ahead and test your app!  If something’s amiss, now’s your chance to break out your problem solving skills and figure out what’s going wrong.

Step 2: Get a Prediction

Design:

Go back to the Designer window in your browser and add some new things to your app.

  1. From the Screen Arrangement palette, drag over the Vertical Arrangement component (#1). At first it will just look like an empty box, but when you put things in it, App Inventor will know that you want to line them up vertically (one on top of the other).
  2. From the Basic palette, drag over a Label component (#2) and drop it inside of the vertical arrangement component. In the Properties pane, change the “Text” property of Label1 to “Ask the Magic 8-Ball a question”.(#3)
  3. From the Basic palette, drag over another Label component (Label2) into the Vertical Arrangement box so that it sits right below Label1. Change the “Text” property of the Label2 to “Touch the Magic 8-Ball to receive your answer.” Now drag the 8-Ball image so that it is also inside the Vertical Arrangement component on top of the two labels. This will cause them to line up with each other in a vertical line. (Note: this can be tricky mouse work, but get them in there just right and the vertical arrangement will resize itself to fit everything.)

Now it’s time to go back into the Blocks Editor to program the components you just added to your project.

Build

Now for the fun part! You’re going to make a list of predictions and program the app to pick one item from the list and display it inside Label2 when the user shakes the phone. The app will also still play the sound that you programmed in Part One. Here’s how to do it…

  1. From the blocks palette, click on Label2 drawer to see all of its associated blocks. Drag over the green set “Label2.BackgroundColor” and insert it just above the “Sound1.Play” block. Notice that the “when AccelerometerSensor1.Shaking” block automatically gets bigger to accommodate the new block.
  2. Clicking on the word “BackgroundColor” will allow you to change the property that is being set. We want to change the Text so our block will look like set Label2.Text.
  3. From the Built-In palette, click on the Lists drawer. Drag over the pick random item block and connect it to the open socket of the set Label2.Text block.
  4. From the Built-In palette, click on Lists again, then drag out the make a list block and plug it into the “list” socket on the right side of the pick random item block.
  5. From the Built-In palette, click on the Text drawer, drag out a ” “ block and connect it to the item socket of the make a list block. Click directly on the space in the block. You can then type in text there. Think about the sayings you want in your list of predictions for the Magic 8-Ball. Type the first prediction into this new text block.
  6. Notice after you plug in two text blocks, there are no more sockets to add more responses. To create more sockets, you need to click the dark blue button on the block. Make a list is called a mutator block, which means it can be expanded or shrunk by clicking the blue button in the upper left corner.
  7. Plug each text block into the pick random item block. (Ideas for answers: http://en.wikipedia.org/wiki/Magic_8-Ball)

Blocks should look something like this:

You’ve got a Magic 8-Ball App! Now your app is fully functional and will predict the future with absolute certainty. Test out that this works, and then come back for some challenge tasks to make the app even more fun.

Step 3: Add a Number mode

Your app already works like a classic magic 8 ball, giving predictions for Yes/No questions.  But since it’s a high tech magic 8 ball, it should have some high tech functionality!  Let’s change our app so that the user can choose if they want to ask a Yes/No question or a number question, like “What’s my lucky number?” and get an answer!

Design:

  1. Go back to the Designer tab to add some more pieces to your app.
  2. From the User Interface palette, drag a Spinner component to the top of the Viewer screen.  A Spinner is a component that lets the user choose from a list of options.
  3. In the Spinner’s properties (on the right), write “Choose a mode” in the “Prompt” property.  In the ElementsFromString property, write “Yes/No, Number”.  This sets the prompt the user will see when selecting options and the options available for the user to choose from.
    screen-shot-2017-01-15-at-10-59-10-am

Build:

Flip back to the Blocks tab.

  1. Create new global variable named “predictions” by pulling in the “initialize global name to” block from the Variables drawer.  Rename the “name” to “predictions.”   Drag your list of predictions over to your new variable.  Your new code should look like this:
    screen-shot-2017-01-16-at-3-28-09-pm
  2. From the Spinner1 drawer, get the “when Spinner1.AfterSelecting” block.  Inside the AfterSelecting block, add two if/then blocks from the Control drawer.
    screen-shot-2017-01-16-at-3-30-45-pm
  3. In the first if block, we want to set up a check to see if the user has chosen the Yes/No mode, and then set our predictions to be the Yes/No answers if they have.  To do this, add the blocks below until your code matches:
    screen-shot-2017-01-16-at-3-32-38-pm
  4. In the second if block, we want to set up a check to see if the user has chosen the Number mode, and then set our predictions to be the Number answers if they have.  To do this, add the blocks below until your code matches:
    screen-shot-2017-01-16-at-3-34-13-pm
  5. So far, the code we’ve built sets our predictions variable to have the right predictions stored in it when the user switches mode.  Now, we need to change our code that prints the prediction label to use our predictions variable!
    Change your “when AccelerometerSensor1.Shaking” block to set the Label2 text based on the predictions variable:
    screen-shot-2017-01-16-at-3-36-43-pm
  6. That’s it!  Test your app to see if it works!  If it doesn’t, go back and see if you can hunt down the problem.  When it does, time to peer deep into your future!

Congrats!

Congratulations for meeting the challenges this app presented and persevering  through them!

This app is yours — so feel free to make it whatever you want it to be!  Here are a few ideas for expanding the app to get you started:

  • Are there other types of questions/answers you want to provide?
  • What if you played different types of sounds based on good/bad answers?
  • Could you build a similar future-predicting game as an app?

Credits

This tutorial is a melding of the following resources: