iOS For High School Students: Text Adventure Game

This is the next tutorial in the beginning programming for iOS series – for high school students, by high school students! This tutorial will walk you through creating an app from the very beginning. The tutorials are cumulative, so principles will build upon the first iOS For High School Students tutorial. As in the first […] By .

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 5 of this article. Click here to view the first page.

The First Method

You’ll begin the game by providing the user instructions on how to operate the game. To do this, you’re going to create a method called instructions. The instructions method needs to be a part of the Game class, and you have to declare it and implement it.

In order to make the method a part of the Game class, you include its definition under your Game class! First it will be declared in Game.h (the header file), and then it will be implemented in Game.m (the implementation file).

At the moment, your header file for the Game class is empty. :[ In Game.h, modify the code to provide the method declaration for instructions so that your code matches the code shown below:

#import <Foundation/Foundation.h>

@interface Game : NSObject
{
 //instance variables
}

- (void) instructions;
@end

First of all, notice that I included some curly brackets after the @interface line. This is where you define the variables specific to your class. Then, when you create an instance of the class, it will be an object that possesses the variables defined within the curly brackets – these variables are known as instance variables.

However, the objective at this point is to declare a method specific to the game class. That’s what we’ve done with the -(void)instructions; line – it declares a method called instructions.

  • The “-” denotes that the method affects the instance and not the original class. For the time being, you will only be working with instance methods.
  • The “(void)” indicates that the method returns void, or nothing. In other words, the method might do something, but it does not return a value as a result of the method. In contrast, a “(BOOL)” in place of the “(void)” would indicate that the method returns a boolean, or a true or false value.
  • Lastly, “instructions” is simply the name of the method. Standard naming conventions for methods dictates that the first word should be lowercase while each additional following word begins with an uppercase letter. For example, if you wanted to change the name of the method to suggest instructions that occur only at the beginning, beginningInstructions or instructionsThatStartGame would be appropriate. This is not mandatory but contributes to the readability of your code and that is something that you should strive for.

Next, you have to implement the instructions method. Select the Game.m file. All you have to do is type in your method declaration again, but this time, include curly brackets to include the commands you want the method to execute every time it’s called. The final Game.m should look like this:

#import "Game.h"

@implementation Game

-(void) instructions
{
    //stuff you want the method to do
}


@end

Because it’s important to be able to test and run your code after every major change, you need to get your application working before you do anything more. Switch back to main.m to actually initialize your game. Replace the “NSLog(@”Hello, World!”);” line and the comment above it in main.m with the following:

        // 1 - Initialize game
        Game* myGame = [[Game alloc] init];
        // 2 - Show instructions
        [myGame instructions];

This is what the above code does:

  1. This line can be summarized as: “Create a pointer to an instance of the Game class named myGame and set its value to be a pointer to an instance of Game that has been created (allocated memory for and initiated).”
  2. This line has myGame run the instance method named “instructions”. Recall that a pointer is not the actual object with its specific methods, it is just a reference to its memory location.

Build and run the program. With any luck, you should see output similar to the following, which confirms the program ran (and ended) appropriately.

It’s also possible that, depending on your Xcode set up and version, that you won’t see anything at all output. As long as you don’t see an error message, this should be fine as well.

Note: In case you’re wondering why you might not see any output, one possible reason is that the above output is from the GDB debugger, which was used in older versions of Xcode. The latest Xcode versions set the debugger to LLDB by default and the LLDB debugger does not output anything if the program itself had no output. Since you still haven’t written any code to output anything, the above will result in there being no output.

Now go back to Game.m – it’s time to decide what you want the instructions method to actually do. For this tutorial, you want it to do the following:

  • Introduce the game scenario and ask for the player’s name;
  • Allocate storage space for the player name;
  • Take input from the keyboard to and store it in the previously allocated storage space.

So the first step is to print a message to the console for the user to read. EASAAAY, right? Within the curly brackets for instructions in Game.m, insert the following:

    // 1 - Show introduction
    NSLog(@"\n\nYour plane crashed on an island. Help is coming in three days. Try and survive.\nType your first name and press enter to continue.");

Just as a reminder, “\n” creates a newline. I chose to double up on them in the beginning to make the text easier to read in the console, because it can get cluttered with time stamps. Feel free to build and run the code whenever you make changes so you can detect any errors early on.

Now you need to create a variable to store the username so that you can use it throughout the game.

The example above uses NSLog() to print out text. More specifically, NSLog() prints out a bunch of characters. The double quotations take all the characters and the spaces between them and creates a string (a consortium of chars). It then proceeds to log (print) the string in the console.

You need to store the user’s input as a string. So add the following to instructions below the NSLog line:

    // 2 - Define storage for name
    char firstname[20];

The above code creates an array, of characters – the word “char” denotes what type of variable you’re creating to store the input and “firstname” is the name of the string of characters. A string is an array of characters. However, it is not true to say that all arrays are strings, because an array could be anything (an array of children, integers, zombies, etc.). A string is just a specific type of an array.

Note: An array is simply a collection of data where you can easily access each element by referring to an index. For instance, 10 people standing in a row would be equivalent to an array since you can refer to each individual in the line as #1, #2 etc. An array is pretty similar to that in computer terms.

Back to the code snippet above: the “[20]” indicates that the string can hold 19 chars or 19 different items (1st, 2nd, 3rd…20th).

The reason the array can hold 19 different characters instead of 20 is due to the fact that character arrays usually have a marker which indicates the end of the string. This marker is the null character and so if you had filled in every position in the above character array, the null character would go in the final (20th) position and so you can only fit in 19 characters in the array.

Now you need to use scanf() to receive input from the user. Add the following below your last line of code:

    // 3 - Receive input via keyboard
    scanf("%s", &firstname);

The scanf() function is known for not handling whitespace (spaces, tabs, the newline character etc.). This line will only take the first chunk of characters before a space, which is perfect for the first name, if users follow the instructions and don’t try to type their full name. >:I

The “%s” denotes that firstname is a string, just like “%i” denotes an integer. Lastly, the & character used before firstname means “address of.” It directs scanf() where to store the value of the input. You will notice that the program doesn’t crash if you omit the &. However, it’s good coding practice to include it.

You now need to log a message to console. But you have a problem. NSLog cannot output our string! Specifically, it can’t log a C-string. The firstname string and scanf are code from the C language. And you thought you were learning Objective-C (the joke’s on you). [trollmeme]

All you have to do is convert the C-string to an NSString and then NSLog will log it appropriately. Note that an NSString is actually an object – you are using an object-oriented programming language after all! Here’s how you accomplish the task – add the following code after your last code:

    // 4 - Convert input to an NSString
    NSString* name;
    name = [NSString stringWithCString:firstname encoding:NSASCIIStringEncoding];

You create “name” as a pointer to an NSString object. You can then assign it the value of our C string converted to an NSString by the methods stringWithCString and encoding (standard methods in the NSString class).

When I was trying to solve this problem on my own, I used Apple’s Developer Library Reference. I was hesitant to use the Developer Library Reference in the past, because it isn’t exactly “uber” user friendly for beginners. However, I really encourage you to take a peek.

If programming ever becomes overwhelming: just relax. You will always be running into new problems to solve. Just realize that everything you read/learn is more stuff that you know and less that you have to be confused about. :P Give this reference a whirl!

Now you’re going to make a slight alteration to increase your ability to re-use the variable “name.” Because its declaration (NSString* name) is located in the instructions method, it can only be used within that method. This is where instance variables come into play.

If you declare “name” as a variable of your Game class, then you can use it anywhere within the confines of the Game class. So, remove the declaration from the instructions method and add it to Game.h – simply cut the first line in section #4 and paste it into Game.h within the curly braces as follows:

    //instance variables
    NSString* name; //Easy enough right?

Compile and run your code just to make sure you haven’t made any errors up to this point. :] If everything works, you should see something similar to the following:

You’re almost done with the instructions method. You just need to give the user some feedback to make sure they entered their name right. All you want to do is log the value of “name” with a cute little message.

The important thing to remember is that “name” is neither an integer nor a char, so (%i and %c) won’t work. The correct symbol is %@, which refers to objects. So add the following to the end of instructions in Game.m:

    // 5 - Display name
    NSLog(@"Your name is: %@. Press enter to continue.", name);

Note the absence of the & character. “Name” is already a pointer to an NSString object and a pointer is a reference to a memory address. So, you can see the redundancy of using &name or the (address of) name.

As a little joke, I created a version of this program for a friend. I told her to type in my name. However, I had created the program to return with the message “No, your name is…calculating…calculating…searching Google…: Sarah.” To which she responded:

Oh the humble joys of programming!

Anyway, cheers on getting your first method working! Compile and run and if you enter your name at the prompt, you should see something like this:

Next you’ll proceed to develop more of the framework before getting into the plot.