Hangman Tutorial Lesson 2 – Creating and loading the levels

When making an App, there are a lot of different places to start. I usually choose a place to start where I can get quick results and feedback, and iterate from there. In some of the steps, I’ll even implement quick and dirty throwaway code, just to make sure the code I’ve been working on actually works, and then delete that code later.

For Hangman, I chose to start out with creating the levels for hangman. To show that this step is working, our goal for this lesson is to load all the levels, choose one at random, and show the phrase on the app. Even though we don’t want to reveal the word in the end, it’s useful to make sure it is working as expected.

In hangman, we let the player guess a word or multiple words (which we’ll call a phrase in the game). We need a place to store our phrases. We have a few options. We could store the phrases straight in the code, and build up the list when we start the app. I don’t like this option because it’s not very flexible and makes it awkward to add new phrases later. Another option is to store the phrases in a text file, which the code then loads when the app starts. I prefer this solution because it’s simple and makes a clean separation of the code from the phrases. One last option that I can think of is storing the data in a database. While Android makes database development easy, it is still overkill for a simple problem. I usually end up using a database when I need to store complex data structures, or when I have so much data that I can’t load it all at once and need a optimized method of accessing this data.

So let’s use a file to store our phrases. If you look in your package explorer and expand the Hangman folder, you should see a “res” folder. This contains all resources that you are going to want to use in your app, whether they be sound files, image files, xml files, or text files. If you expand the res folder, you should see some default folders already created for you. There are a bunch of drawable folders (which contain images and shapes), a layout folder (which contains the user interface layouts for your app), a menu folder (which has XML files to define your menus that you use in your app), and then values folder (which contains XML files that represent simple values, such as strings and integers). One folder that is missing that we want to create is the “raw” folder (which contains any files you want to store in the raw form). This is where we are going to store our text file. We need to create the folder, so right click on the “res” folder and click “New”, and then “Folder,” and name it “raw”.

Image

Next we need to create our new file. Right-click on the “raw” folder, click on “New” and select “File”.

Image

Specify the filename of “phrases.txt” and hit “Finish”.

Image

To start, let’s just put a phrase per line (we’ll make the file format a little more complicated later). You can make up your own phrases or just enter the text below:

George Washington
Great Wall of China
New Hampshire
Chocolate Chip Cookies
Chicken Pot Pie
Computer Science
Partly Cloudy
Peanut Butter and Jelly Sandwich

Now we need to create code to load the phrases. In the package explorer, right click on “com.famlinkup.hangman” package, select “New” and then “Class”:

Image

In the Name field, enter “PhraseGenerator” and click “Finish”.

Image

This class will be in charge of both loading the phrases from the text file, and providing a random phrase from these loaded phrases. Let me show the whole class and then explain it:

package com.famlinkup.hangman;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.content.Context;
import android.widget.Toast;

public class PhraseGenerator
{
  private List<String> lines;
  private Random random;

  public PhraseGenerator(Context context)
  {
    this.lines = loadPhrases(context);
    this.random = new Random();
  }

  private List<String> loadPhrases(Context context)
  {
    List<String> phrases = new ArrayList<String>();
    BufferedReader br = null;
    InputStream fileStream = context.getResources().openRawResource(R.raw.phrases);
    String line;
    try
    {
      br = new BufferedReader(new InputStreamReader(fileStream));
      while ((line = br.readLine()) != null)
        phrases.add(line);
    }
    catch (IOException e)
    {
      Toast.makeText(context, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
    }
    return phrases;
  }

  public String nextPhrase()
  {
    return lines.get(random.nextInt(lines.size()));
  }
}

In our constructor, we pass something called a Context. In Android, the context represents the current state of the application. For our use case, we need the context to get access to the file we created. The constructor calls loadPhrases, which is in charge of loading all the phrases from the text file and storing them in the lines variable. Also, the constructor create a Random object that we will later use any time we want the next phrase.

In loadPhrases, we open and read from the file by calling context.getResources(), which gives you access to the resources in your “res” folder, and then calling openRawResource, which takes an id. Android stores all of it’s predefined resources in a static class “R”, which is autogenerated everytime you add a resource, so that it keeps in sync with the resources you have. Because the file is in the “raw” folder, we access it through R.raw, and because the name of the file is “phrases”, you access the file through the id defined at R.raw.phrases.

Once you have the inputStream, you can then read it one line at a time by using a BufferedReader, like you would do in any other Java application. We then add each line to our List of lines.

Now that we have our list of lines, getting a random phrase is easy. We just get a random number from 0 to the length of the list, and use that number to index into our list.

Now that the PhraseGenerator is created, we would want to test to make sure it works. Let’s open the MainActivity class and add some code to test it. In MainActivity (which is sort of like your main method in a Java application), you want to create a PhraseGenerator object and call nextPhrase in the onCreate() method already defined:

PhraseGenerator phraseGenerator;

@Override
protected void onCreate(Bundle savedInstanceState)
{
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  phraseGenerator = new PhraseGenerator(this);
  Toast.makeText(this, phraseGenerator.nextPhrase(), Toast.LENGTH_LONG).show();
}

The one thing I need to explain is what Toast is. In Android, Toast is a simple way to show a message to the user, and have it disappear after a certain amount of time. I find it to be very useful to debug simple things while I’m still developing my app. You can think of it sort if like an alert in web development. Toast takes the context (which is just “this” when you are in an activity), the message to show, and the duration.  Don’t forget to call show() afterwards too.

Now we can test it. Deploy that application to either your phone or emulator. You should see something like this:

device-2014-03-24-215625

You should see one of your phrases from the text file in a little bubble somewhere on the screen. Congratulations, your app actually does something now!  In the next lesson, we’ll be talking about about the layout and how to define it.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s