OS X games from the ground up: variables

You can see an index of all the posts in this series: go to index.

If you are starting from this point, or need a fresh set of files, here are the starter files from the end of the previous post: your first programme

In the previous post you began constructing your first c programme by using printf to display information to the user. So far we’ve just been showing static information. In this programme though, we also need to create and store information dynamically. For example, we will need somewhere to store the words that we choose from each list.

We can do this in C using variables. A variable is a little chunk of memory that’s been set aside to store a value. Unlike the static information we’ve been looking at so far, the value stored in a variable can, as the name suggests, vary. So how do we know which bit of memory to put our variables in? Well fortunately we don’t have to worry about that level of detail – we just give each variable a unique name to identify it and C takes care of the rest.

Think of C’s role in variable management as being somewhat like a cloakroom or coat check attendant. When you hand over your coat, you neither know nor care which rail or hanger your coat is stored on – that’s the attendant’s job. All you want to be sure of is that, when you hand over the ticket, you get back your coat and not some random coat left by another person.

In C, the spare memory (which is known as the stack) is like the cloakroom, the information you store there is like your coat and the name you give to the variable so it can be identified is like the ticket. So let’s say you want to store the number 73, you might say to C: “Please hang this number up somewhere safe and give it the name ‘score’. ” Later on when you want to add some points to your score, you’ll say: “I’d like the number I left you with the name ‘score’ please”. C then hands it back to you so you can add some points to it, then you hand it back over until you need it again.

Now, in many cloakrooms you can leave different types of items, such as coats, umbrellas, hats and bags. The attendant needs to know which item you want to leave because there is a different charge for each item type. Well the same is true when storing variables with C. We need to tell C what type of information we are storing – for example is it a whole number, a number with a fractional part, some text etc.? And just like the cloakroom attendant needs to know the type so he knows what to charge, C needs to know the type because each type requires a different amount of memory.

So how does this work in practice? Well let’s take our score example. We know we only want to store whole numbers, so we would create this variable with the following statement:

This is called a variable declaration. The int bit tells C that we want to store a whole number. Int is short for integer, which is the mathematical term for a number without a fractional part, e.g. 73. We’d use a different type here if we wanted to store a different sort of number, for example float for a floating point number (a number with a fractional part). The second part, score, is the name we want to use to identify the variable. Notice that we haven’t given C a value to put in this variable yet. So what’s in there? What would we get if we asked for it? Well, let’s try it. Open Xcode and your Buzzword project and then open main.c. Now amend your program so it looks like the following (lines 17 and 18 are new):

You can see we are using printf in a slightly different way here.  Previously you’ve just used printf to display static information, but it has a few more tricks up its sleeve. The f in printf stands for “formatted”, because it also accepts things called conversion specifiers. These work in a similar way to the escape sequences you saw in the previous post. What a conversion specifier does is tells C, “I’d like to insert this type of information at this point please.” Conversion specifiers always start with %, which is followed by a single conversion character code representing the type of information we want to show. In this case we’ve use i (for integer – but note that you will also see %d used for an integer – either is fine, but be consistent). We also have to tell C what information to show at this point, so for each conversion specifier we include, we must also add a comma after the closing quote mark and a variable or some information of the correct type. In this example we want to show the score, so we’ve added our score variable.

If you run this you’ll see the instructions you added in the last post, and then something like this (don’t forget to use the Log Navigator if you want to see all of the output more clearly, but you can also scroll the Debug area at the bottom of the main pane):

xcode uninitialised c variable output

It will most likely be 0 but it could be a different number. The main thing to remember is that when you declare variables in this way, they contain garbage. You shouldn’t rely on them having any particular value until you set one. This is known as initialisation, and, once we’ve declared a variable, we can do it like this:

You can also declare a variable and initialise it in a single step, like this:

Let’s try this now. Change the current variable declaration in your programme so it looks like the line above and then try building and running again. You should see the instructions you added in the last post followed by:

Xcode c combined variable declarion and initialisation

So that’s great – we can store a number in a variable, and get it back again when we need it. But if this was a real score in a real game, we’d probably expect it to go up every now and then as the player accumulated points. C allows us to manipulate variables using operators. Operators perform common arithmetic operations such as adding, subtracting, multiplying and dividing. So, if our player had just won 10 points, we could add these to his score with a statement like this:

We can also use other variables in the equation. So if we had another variable called penalty, that contained the number of points to be subtracted if the player incurs a penalty, we remove those points with:

If we wanted to multiply the points by a bonus factor stored in the variable called bonus, we’d use:

Note that we use an asterisk, not an x for multiplication.

If we wanted to divide the points by the time taken, which we’d stored in a variable called time, we’d use:

Again, notice that we use a forward slash and not ÷ for division.

You can also combine operators in a single expression, e.g.:

If score was 1000 and bonus was 2 and time was 20, this expression would first calculate score * bonus, which equals 2000,  and then divide that by time, giving 100. However, consider this expression:

If score was 1000, penalty was 50 and bonus was 2, you might expect this expression would first calculate score – penalty, which equals 950, and then multiply that by bonus, giving 1900. But the number that would actually be put into score would be 900! Why is this?

Operators in C have what is known as an order of precedence. The order in which operators are applied within an expression depends on their order of precedence. You can find a table showing this order here: Operators in C and C++. You need to be looking at the table half way down the page in the Operator Precedence section, not the one at the top. Don’t worry that this is a big table with lots of operators you haven’t encountered yet – you’ll learn more about these in future posts. Where operators have the same precedence, e.g. * and /, they are applied in order of associativity, which you can see in the final column of the table. In the case of * and /, this is from left to right.

As you can see from the table, multiplication and division have a higher precedence than addition and subtraction, so what is actually happening in our expression above is that C is first calculating penalty * bonus, which is equal to 100 and then subtracting that from score, giving 900. To get the expression evaluated in the order you want, you can use parentheses, like this:

Parentheses will take precedence over multiplication and division operations. So, in this case, the part of the expression in parentheses will be evaluated first, giving us the correct result of 1900.

OK, that’s all good, but in our Buzzword programme we are much more concerned with letters than numbers. Well fortunately there’s a variable type that stores letters too. In your programme change the variable declaration/initialisation, and the printf line that follows it to:

Here we’ve changed to the type of our variable to char, which is short for character. Note that when we initialise char type variables, the initial value is placed with single quote marks. We’ve also changed the conversion character to c (for char).

When you build and run this, the end of the output should look like this:

xcode c char declaration and initialisation

OK great, but it’s going to be a bit long-winded if we have to do this for every letter of every word in our programme. Fortunately c has a way of dealing with collections of variables. Instead of declaring and initialising lots of individual variables, each with their own name, we can create a group of variables and give them a single name. This structure is known as an array.

For example, let’s say rather than recording just a single score, we wanted to keep track of the last five scores that a player had achieved. We could declare an array like this:

This looks similar to the way you declared a single int variable, but now you’ve added square brackets with a number at the end of the declaration. This tells C, “I don’t want a single variable, I want a group of five of them, and I want the group to be called scores”.

So, now that you have your array, how do you access the individual scores within it? The answer is that you use the square brackets again, like this:

This tells C, “please store the number 73 in the first variable of the group called scores”. Each variable within an array is called an element. Note that the first element of an array is numbered 0. That means the last element is always one less than the size of the array. In this case, to initialise the last element of scores you would use:

If you try to do this:

you will get an error, because that element doesn’t exist.

Here’s an example of how we could declare our array and initialise all the elements:

You’ll recall though, that there was a way we could declare and initialise single variables with a single statement. The same is also true of arrays. We do it like this:

This does exactly the same as the six statements in the previous example. Note that when we declare an array like this, we don’t have to include the number of elements between the square brackets because C can work this out based on the number of elements we’ve included in the initialisation list.

When we want to create a group of chars rather than ints we could do this:

We could now get the value of an individual element in this array, like this:

The number in square brackets that we use to reference a particular element is called a subscript. Remember that array elements are numbered from 0, so to get the nth element of the array, you would use the subscript n-1.

This is all well and good, but in C the reason we often want to group a set of characters together, is because we want to treat them as a single word or phrase. C provides us with a handy shortcut for doing this:

Note that this also results in an array of chars, but it is not quite the same as the char array we created earlier. This type of character array is called a string, because it is a string of characters. When you declare a char array like this, c adds an additional hidden element at the end. This is a special value called NULL, which you can also enter manually using the escape sequence \0. When c encounters this value it knows that it has reached the end of the string.

You’ve already been using strings, when you create a printf statement like:

The phrase between the quotes is known as a string literal because it is a string that is embedded within the programme code. We’ve used other literals when we’ve embedded other types of data directly in our programme. For example, the 73 in this statement is an integer literal:

Let’s see strings at work. Replace the current variable declaration/initialisation and the following printf statement with these statements:

Build and run and you should see the following at the end of the output:

c string example

This has introduced you to another conversion specifier, %s (for string). You can see from this example, that once you have declared and initialised a string, you can work with the whole string or with individual characters (elements of the array).

In the next part of this series you’ll see how you can use arrays to generate  the lists of words we need for Buzzword. In the meantime, here’s a challenge for you. Remove the two lines of code you just added and replace them with code that does the following:

1. Display the phrase: “10 green bottles hanging on the wall”. To make this a little bit more challenging, you must create the phrase so that the number at the beginning and the word ‘green’ are stored in variables.

2. When you have managed to get the phrase to display successfully, change it to “9 blue bottles hanging on the wall” by changing the values you use to initialise the two variables.

A solution will be shown in the next post.

 

This entry was posted in Games, Programming Tutorials and tagged , , , , , . Bookmark the permalink.

Leave a reply