Speaking Java – Your First Game

John Horton

February 2016

In this article, we will start writing our very own Java code at the same time as we begin understanding Java syntax. We will learn how to store, retrieve, and manipulate different types of values stored in the memory. We will also look at making decisions and branching the flow of our code based on the values of this data.

In this order, we will:

  • Learn some Java syntax and see how it is turned into a running app by the compiler
  • Store data and use it with variables
  • Express yourself in Java with expressions
  • Continue with the math game by asking a question
  • Learn about decisions in Java
  • Continue with the math game by getting and checking the answer

(For more resources related to this topic, see here.)

Acquiring the preceding Java skills will enable us to build the next two phases of our math game. This game will be able to ask the player a question on multiplication, check the answer and give feedback based on the answer given, as shown in the following screenshot:

Java syntax

Throughout this book, we will use plain English to discuss some fairly technical things. You will never be asked to read a technical explanation of a Java or Android concept that has not been previously explained in a non-technical way.

Occasionally, I might ask or imply that you accept a simplified explanation in order to offer a fuller explanation at a more appropriate time, like the Java class as a black box; however, never will you need to scurry to Google in order to get your head around a big word or a jargon-filled sentence.

Having said that, the Java and Android communities are full of people who speak in technical terms and to join in and learn from these communities, you need to understand the terms they use. So the approach this book takes is to learn a concept or appreciate an idea using an entirely plain speaking language, but at the same time, it introduces the jargon as part of the learning.

Then, much of the jargon will begin to reveal its usefulness, usually as a way of clarification or keeping the explanation/discussion from becoming longer than it needs to be.

The very term, "Java syntax," could be considered technical or jargon. So what is it? The Java syntax is the way we put together the language elements of Java in order to produce code that works in the Java/Dalvik virtual machine. Syntax should also be as clear as possible to a human reader, not least ourselves when we revisit our programs in the future. The Java syntax is a combination of the words we use and the formation of those words into sentence like structures.

These Java elements or words are many in number, but when taken in small chunks are almost certainly easier to learn than any human-spoken language. The reason for this is that the Java language and its syntax were specifically designed to be as straightforward as possible. We also have Android Studio on our side which will often let us know if we make a mistake and will even sometimes think ahead and prompt us.

I am confident that if you can read, you can learn Java; because learning Java is much easy. What then separates someone who has finished an elementary Java course from an expert programmer? The same things that separate a student of language from a master poet. Mastery of the language comes through practice and further study.

The compiler

The compiler is what turns our human-readable Java code into another piece of code that can be run in a virtual machine. This is called compiling. The Dalvik virtual machine will run this compiled code when our players tap on our app icon. Besides compiling Java code, the compiler will also check for mistakes. Although we might still have mistakes in our released app, many are stopped discovered at the when our code is compiled.

Making code clear with comments

As you become more advanced in writing Java programs, the solutions you use to create your programs will become longer and more complicated. Java was designed to manage complexity by having us divide our code into separate chunks, very often across multiple files.

Comments are a part of the Java program that do not have any function in the program itself. The compiler ignores them. They serve to help the programmer to document, explain, and clarify their code to make it more understandable to themselves at a later date or to other programmers who might need to use or modify the code.

So, a good piece of code will be liberally sprinkled with lines like this:

//this is a comment explaining what is going on

The preceding comment begins with the two forward slash characters, //. The comment ends at the end of the line. It is known as a single-line comment. So anything on that line is for humans only, whereas anything on the next line (unless it's another comment) needs to be syntactically correct Java code:

//I can write anything I like here

but this line will cause an error

We can use multiple single-line comments:

//Below is an important note

//I am an important note

//We can have as many single line comments like this as we like

Single-line comments are also useful if we want to temporarily disable a line of code. We can put // in front of the code and it will not be included in the program. Recall this code, which tells Android to load our menu UI:

//setContentView(R.layout.activity_main);

In the preceding situation, the menu will not be loaded and the app will have a blank screen when run, as the entire line of code is ignored by the compiler. There is another type of comment in Java—the multiline comment. This is useful for longer comments and also to add things such as copyright information at the top of a code file. Also like the single-line comment, it can be used to temporarily disable code, in this case usually multiple lines.

Everything in between the leading /* signs and the ending */ signs is ignored by the compiler. Here are some examples:

/*

This program was written by a Java expert

You can tell I am good at this because my

code has so many helpful comments in it.

*/

There is no limit to the number of lines in a multiline comment. Which type of comment is best to use will depend upon the situation. In this book, I will always explain every line of code explicitly but you will often find liberally sprinkled comments within the code itself that add further explanation, insight or clarification. So it's always a good idea to read all of the code:

/*

The winning lottery numbers for next Saturday are

9,7,12,34,29,22

But you still want to learn Java? Right?

*/

All the best Java programmers liberally sprinkle their code with comments.

Storing data and using it with variables

We can think of a variable as a labeled storage box. They are also like a programmer's window to the memory of the Android device, or whatever device we are programming. Variables can store data in memory (the storage box), ready to be recalled or altered when necessary by using the appropriate label.

Computer memory has a highly complex system of addressing that we, fortunately, do not need to interact with in Java. Java variables allow us to make up convenient names for all the data that we want our program to work with; the JVM will handle all the technicalities that interact with the operating system, which in turn, probably through several layers of buck passing, will interact with the hardware.

So we can think of our Android device's memory as a huge warehouse. When we assign names to our variables, they are stored in the warehouse, ready when we need them. When we use our variable's name, the device knows exactly what we are referring to. We can then tell it to do things such as "get box A and add it to box C, delete box B," and so on.

In a game, we will likely have a variable named as something along the lines of score. It would be this score variable using which we manage anything related to the user's score, such as adding to it, subtracting or perhaps just showing it to the player.

Some of the following situations that might arise:

  • The player gets a question right, so add 10 to their existing score
  • The player views their stats screen, so print score on the screen
  • The player gets the best score ever, so make hiScore the same as their current score

These are fairly arbitrary examples of names for variables and as long as you don't use any of the characters keywords that Java restricts, you can actually call your variables whatever you like. However, in practice, it is best to adopt a naming convention so that your variable names will be consistent. In this book, we will use a loose convention of variable names starting with a lowercase letter. When there is more than one word in the variable's name, the second word will begin with an uppercase letter. This is called "camel casing."

Here are some examples of camel casing:

  • score
  • hiScore
  • playersPersonalBest

Before we look at some real Java code with some variables, we need to first look at the types of variables we can create and use.

Types of variables

It is not hard to imagine that even a simple game will probably have quite a few variables. What if the game has a high score table that remembers the names of the top 10 players? Then we might need variables for each player.

And what about the case when a game needs to know if a playable character is dead or alive, or perhaps has any lives/retries left? We might need code that tests for life and then ends the game with a nice blood spurt animation if the playable character is dead.

Another common requirement in a computer program, including games, is the right or wrong calculation: true or false.

To cover almost these and many other types of information you might want to keep track of, every possibility Java has types. There are many types of variables and, we can also invent our own types or use other people's types. But for now, we will look at the built-in Java types. To be fair, they cover just about every situation we are likely to run into for a while. Some examples are the best way to explain this type of stuff.

We have already discussed the hypothetical but highly likely score variable. The sWell score is likely to be a number, so we have to convey this (that the score is a number) to the Java compiler by giving the score an appropriate type. The hypothetical but equally likely playerName will of course, hold the characters that make up the player's name. Jumping ahead a couple of paragraphs, the type that holds a regular number is called an int, and the type that holds name-like data is called a string. And if we try and store a player name, perhaps "Ada Lovelace" in score, which is meant for numbers, we will certainly run into trouble.

The compiler says no! Actually, the error would say this:

As we can see, Java was designed to make it impossible for such errors to make it to a running program. Did you also spot in the previous screenshot that I had forgotten the semicolon at the end of the line? With this compiler identifying our errors, what could possibly go wrong?

Here are the main types in Java. Later, we will see how to start using them:

  • int: This type is used to store integers. It uses 32 pieces (bits) of memory and can therefore store values with a magnitude a little in excess of 2 billion, including negative values.
  • long: As the name hints at, this data types can be used when even larger numbers are required. A long data type uses 64 bits of memory and 2 to the power of 63 is what we can store in this type. If you want to see what that looks like, try this: 9,223,372,036,854,775,807. Perhaps surprisingly, there are uses for long variables but if a smaller variable will do, we should use it so that our program uses less memory.

You might be wondering when you might use numbers of this magnitude. The obvious examples would be math or science applications that do complex calculations but another use might be for timing. When you time how long something takes, the Java Date class uses the number of milliseconds since January 1, 1970. The long data type could be useful to subtract a start time from an end time to determine an elapsed time. float: This is for floating-point numbers, that is, numbers where there is precision beyond the decimal point. As the fractional part of a number takes memory space just as the whole number portion, the range of numbers possible in a float is therefore decreased compared to non-floating-point numbers. So, unless our variable will definitely use the extra precision, float would not be our data type of choice.

  • double: When the precision in float is not enough we have double.
  • short: When even an int data type is overkill, the super-skinny short fits into the tiniest of storage boxes, but we can only store around 64,000 values, from -32,768 to 32,767.
  • byte: This is an even smaller storage box than a short type. There is plenty of room for these in memory but a byte can only store values from -128 to 127.
  • boolean: We will be using plenty of Booleans throughout the book. A Boolean variable can be either true or false—nothing else. Perhaps Boolean answer questions such as:
  • Is the player alive?
  • Has a new high score been reached?
  • Are two examples for a Boolean variable enough?
  • char: This stores a single alphanumeric character. It's not going to change anything on its own but it could be useful if we put lots of them together.

I have kept this discussion of data types to a practical level that is useful in the context of this book. If you are interested in how a data type's value is stored and why the limits are what they are, visit the Oracle Java tutorials site at http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. Note that you do not need any more information than we have already discussed to continue with this book.

As we just learned, each type of data that we might want to store will require a specific amount of memory. So we must let the Java compiler know the type of the variable before we begin to use it.

The preceding variables are known as the primitive types. They use predefined amounts of memory and so, using our storage analogy, fit into predefined sizes of the storage box.

As the "primitive" label suggests, they are not as sophisticated as the reference types.

Reference types

You might have noticed that we didn't cover the string variable type that we previously used to introduce the concept of variables.

Strings are a special type of variable known as a reference type. They quite simply refer to a place in memory where the storage of the variable begins, but the reference type itself does not define a specific amount of memory. The reason for this is fairly straightforward: we don't always know how much data will need to be stored until the program is actually run.

We can think of strings and other reference types as continually expanding and contracting storage boxes. So won't one of these string reference types bump into another variable eventually? If you think about the devices memory as a huge warehouse full of racks of labeled storage boxes, then you can think of the Dalvik virtual machine as a super-efficient forklift truck driver that puts the different types of storage boxes in the most appropriate place.

And if it becomes necessary, the virtual machine will quickly move stuff around in a fraction of a second to avoid collisions. It will even incinerate unwanted storage boxes when appropriate. This happens at the same time as constantly unloading new storage boxes of all types and placing them in the best place, for that type of variable. Dalvik tends to keep reference variables in a part of the warehouse that is different from the part for the primitive variables.

So strings can be used to store any keyboard character, like a char data type but of almost any length. Anything from a player's name to an entire book can be stored in a single string.

There are a couple more reference types we will explore. Arrays are a way to store lots of variables of the same type, ready for quick and efficient access.

Think of an array as an aisle in our warehouse with all the variables of a certain type lined up in a precise order. Arrays are reference types, so Dalvik keeps these in the same part of the warehouse as strings.

So we know that each type of data that we might want to store will require an amount of memory. Hence, we must let the Java compiler know the type of the variable before we begin to use it.

Declaration

That's enough of theory. Let's see how we would actually use our variables and types. Remember that each primitive type requires a specific amount of real device memory. This is one of the reasons that the compiler needs to know what type a variable will be of. So we must first declare a variable and its type before we attempt to do anything with it.

To declare a variable of type int with the name score, we would type:

int score;

That's it! Simply state the type, in this case int, then leave a space, and type the name you want to use for this variable. Also note the semicolon on the end of the line as usual to show the compiler that we are done with this line and what follows, if anything, is not part of the declaration.

For almost all the other variable types, declaration would occur in the same way. Here are some examples. The variable names are arbitrary. This is like reserving a labeled storage box in the warehouse:

long millisecondsElapsed;

float gravity;

double accurrateGravity;

boolean isAlive;

char playerInitial;

String playerName;

Initialization

Here, for each type, we initialize a value to the variable. Think about placing a value inside the storage box, as shown in the following code:

score = 0;

millisecondsElapsed = 1406879842000;//1st Aug 2014 08:57:22

gravity = 1.256;

double accurrateGravity =1.256098;

isAlive = true;

playerInitial = 'C';

playerName = "Charles Babbage";

Notice that the char variable uses single quotes (') around the initialized value while the string uses double quotes (").

We can also combine the declaration and initialization steps. In the following snippet of code, we declare and initialize the same variables as we did previously, but in one step each:

int score = 0;

long millisecondsElapsed = 1406879842000;//1st Aug 2014 08:57:22

float gravity = 1.256;

double accurrateGravity =1.256098;

boolean isAlive = true;

char playerInitial = 'C';

String playerName = "Charles Babbage";

Whether we declare and initialize separately or together is probably dependent upon the specific situation. The important thing is that we must do both:

int a;

//The line below attempts to output a to the console

Log.i("info", "int a = " + a);

The preceding code would cause the following result:

Compiler Error: Variable a might not have been initialized

There is a significant exception to this rule. Under certain circumstances variables can have default values.

Changing variables with operators

Of course, in almost any program, we are going to need to do something with these values. Here is a list of perhaps the most common Java operators that allow us to manipulate variables. You do not need to memorize them as we will look at every line of code when we use them for the first time:

  • The assignment operator (=): This makesthe variable to the left of the operator the same as the value to the right. For example, hiScore = score; or score = 100;.
  • The addition operator (+): This adds the values on either side of the operator. It is usually used in conjunction with the assignment operator, such as score = aliensShot + wavesCleared; or score = score + 100;. Notice that it is perfectly acceptable to use the same variable simultaneously on both sides of an operator.
  • The subtraction operator (-): This subtracts the value on the right side of the operator from the value on the left. It is usually used in conjunction with the assignment operator, such as lives = lives - 1; or balance = income - outgoings;.
  • The division operator (/): This divides the number on the left by the number on the right. Again, it is usually used in conjunction with the assignment operator, as shown in fairShare = numSweets / numChildren; or recycledValueOfBlock = originalValue / .9;.
  • The multiplication operator (*): This multiplies variables and numbers, such as answer = 10 * 10; or biggerAnswer = 10 * 10 * 10;.
  • The increment operator (++): This is a really neat way to add 1 to the value of a variable. The myVariable = myVariable + 1; statement is the same as myVariable++;.
  • The decrement operator (--): You guessed it: a really neat way to subtract 1 from something. The myVariable = myVariable -1; statement is the same as myVariable--;.

The formal names for these operators are slightly different from the names used here for explanation. For example, the division operator is actually one of the multiplicative operators. But the preceding names are far more useful for the purpose of learning Java and if you used the term "division operator", while conversing with someone from the Java community, they would know exactly what you mean.

There are actually many more operators than these in Java.

If you are curious about operators there is a complete list of them on the Java website at http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html. All the operators required to complete the projects in this book will be fully explained in this book. The link is provided for the curious among us.

Expressing yourself in Java

Let's try using some declarations, assignments and operators. When we bundle these elements together into some meaningful syntax, we call it an expression. So let's write a quick app to try some out.

Here we will make a little side project so we can play with everything we have learned so far.

Instead, we will simply write some Java code and examine its effects by outputting the values of variables to the Android console, called LogCat. We will see exactly how this works by building the simple project and examining the code and the console output:

The following is a quick reminder of how to create a new project.

  1. Close any currently open projects by navigating to File | Close Project.
  2. Click on Start a new Android Studio project.
  3. The Create New Project configuration window will appear. Fill in the Application name field and Company Domain with packtpub.com or you could use your own company website name here instead.
  4. Now click on the Next button. On the next screen, make sure the Phone and Tablet checkbox has a tick in it. Now we have to choose the earliest version of Android we want to build our app for. Go ahead and play with a few options in the drop-down selector. You will see that the earlier the version we select, the greater is the percentage of devices our app can support. However, the trade-off here is that the earlier the version we select, the less are cutting-edge Android features available in our apps. A good balance is to select API 8: Android 2.2 (Froyo). Go ahead and do that now as shown in the next screenshot.
  5. Click on Next. Now select Blank Activity as shown in the next screenshot and click on Next again.
  6. On the next screen, simply change Activity Name to MainActivity and click on Finish.
  7. To keep our code clear and simple, you can delete the two unneeded methods (onCreateOptionsMenu and onOptionsItemSelected) and their associated @override and @import statements. However, this is not necessary for the example to work.

As with all the examples and projects in this book, you can copy or review the code from the download bundle. Just create the project as described previously and paste the code from MainActivity.java file from the download bundle to the MainActivity.java file that was generated when you created the project in Android Studio. Just ensure that the package name is the same as the one you chose when the project was created. However, I strongly recommend going along with the tutorial so that we can learn how to do everything for ourselves.

As this app uses the LogCat console to show its output, you should run this app on the emulator only and not on a real Android device. The app will not harm a real device, but you just won't be able to see anything happening.

  1. Create a new blank project called Expressions In Java.
  2. Now, in the onCreate method just after the line where we use the setContentView method, add this code to declare and initialize some variables:
    //first we declare and initialize a few variables
    
    int a = 10;
    
    String b = "Alan Turing";
    
    boolean c = true;
  3. Now add the following code. This code simply outputs the value of our variables in a form where we can closely examine them in a minute:
    //Let's look at how Android 'sees' these variables
    
    //by outputting them, one at a time to the console
    
    Log.i("info", "a = " + a);
    
    Log.i("info", "b = " + b);
    
    Log.i("info", "c = " + c);
  4. Now let's change our variables using the addition operator and another new operator. See if you can work out the output values for variables a, b, and c before looking at the output and the code explanation:
    //Now let's make some changes
    
    a++;
    
    a = a + 10;
    
    b = b + " was smarter than the average bear Booboo";
    
    b = b + a;
    
    c = (1 + 1 == 3);//1 + 1 is definitely 2! So false.
  5. Let's output the values once more in the same way we did in step 3, but this time, the output should be different:
    //Now to output them all again
    
    Log.i("info", "a = " + a);
    
    Log.i("info", "b = " + b);
    
    Log.i("info", "c = " + c);
  6. Run the program on an emulator in the usual way. You can see the output by clicking on the Android tab from our "useful tabs" area below the Project Explorer.

Here is the output, with some of the unnecessary formatting stripped off:

info? a = 10

info? b = Alan Turing

info? c = true

info? a = 21

info? b = Alan Turing was smarter than the average bear Booboo21

info? c = false

Now let's discuss what happened. In step 2, we declared and initialized three variables:

  • a: This is an int that holds the value 10
  • b: This is a string that holds the name of an eminent computer scientist.
  • c: This is a Boolean that holds the value false

So when we output the values in step 3, it should be no surprise that we get the following:

info? a = 10

info? b = Alan Turing

info? c = true

In step 4, all the fun stuff happens. We add 1 to the value of our int a using the increment operator like this: a++;. Remember that a++ is the same as a = a + 1.

We then add 10 to a. Note we are adding 10 to a after having already added 1. So we get this output for a 10 + 1 + 10 operation:

info? a = 21

Now let's examine our string, b. We appear to be using the addition operator on our eminent scientist. What is happening is what you could probably guess. We are adding together two strings "Alan Turing" and "was smarter than the average bear Booboo." When you add two strings together it is called concatenating and the + symbol doubles as the concatenation operator.

Finally, for our string, we appear to be adding int a to it. This is allowed and the value of a is concatenated to the end of b.

info? b = Alan Turing was smarter than the average bear Booboo21

This does not work the other way round; you cannot add a string to an int. This makes sense as there is no logical answer.

a = a + b

Finally, let's look at the code that changes our Boolean, c, from true to false: c = (1+1=3);. Here, we are assigning to c the value of the expression contained within the brackets. This would be straightforward, but why the double equals (==)? We have jumped ahead of ourselves a little. The double equals sign is another operator called the comparison operator.

So we are really asking, does 1+1 equal 3? Clearly the answer is false. You might ask, "why use == instead of =?" Simply to make it clear to the compiler when we mean to assign and when we mean to compare.

Inadvertently using = instead of == is a very common error.

The assignment operator (=) assigns the value on the right to the value on the left, while the comparison operator (==) compares the values on either side.

The compiler will warn us with an error when we do this but at first glance you might swear the compiler is wrong.

Now let's use everything we know and a bit more to make our Math game project.

Math game – asking a question

Now that we have all that knowledge under our belts, we can use it to improve our math game. First, we will create a new Android activity to be the actual game screen as opposed to the start menu screen. We will then use the UI designer to lay out a simple game screen so that we can use our Java skills with variables, types, declaration, initialization, operators, and expressions to make our math game generate a question for the player. We can then link the start menu and game screens together with a push button.

If you want to save typing and just review the finished project, you can use the code downloaded from the Packt website. If you have any trouble getting any of the code to work, you can review, compare, or copy and paste the code from the already completed code provided in the download bundle.

The completed code is in the following files that correspond to the filenames we will be using in this tutorial:

  • Chapter 3/MathGameChapter3a/java/MainActivity.java
  • Chapter 3/MathGameChapter3a/java/GameActivity.java
  • Chapter 3/MathGameChapter3a/layout/activity_main.xml
  • Chapter 3/MathGameChapter3a/layout/activity_game.xml

As usual, I recommend following this tutorial to see how we can create all of the code for ourselves.

Creating the new game activity

We will first need to create a new Java file for the game activity code and a related layout file to hold the game Activity UI.

  1. Run Android Studio and select your Math Game Chapter 2 project. It might have been opened by default. Now we will create the new Android Activity that will contain the actual game screen, which will run when the player taps the Play button on our main menu screen.
  2. To create a new activity, we know need another layout file and another Java file. Fortunately Android Studio will help us do this. To get started with creating all the files we need for a new activity, right-click on the src folder in the Project Explorer and then go to New | Activity. Now click on Blank Activity and then on Next.
  3. We now need to tell Android Studio a little bit about our new activity by entering information in the above dialog box. Change the Activity Name field to GameActivity. Notice how the Layout Name field is automatically changed for us to activity_game and the Title field is automatically changed to GameActivity.
  4. Click on Finish. Android Studio has created two files for us and has also registered our new activity in a manifest file, so we don't need to concern ourselves with it.
  5. If you look at the tabs at the top of the editor window, you will see that GameActivity.java has been opened up ready for us to edit, as shown in the following screenshot:

  6. Ensure that GameActivity.java is active in the editor window by clicking on the GameActivity.java tab shown previously.
  7. Android overrides some methods for us by default, and that most of them were not necessary. Here again, we can see the code that is unnecessary. If we remove it, then it will make our working environment simpler and cleaner. To avoid this here, we will simply use the code from MainActivity.java as a template for GameActivity.java. We can then make some minor changes.
  8. Click on the MainActivity.java tab in the editor window. Highlight all of the code in the editor window using Ctrl + A on the keyboard.
  9. Now copy all of the code in the editor window using the Ctrl + C on the keyboard.
  10. Now click on the GameActivity.java tab.
  11. Highlight all of the code in the editor window using Ctrl + A on the keyboard.
  12. Now paste the copied code and overwrite the currently highlighted code using Ctrl + V on the keyboard.
  13. Notice that there is an error in our code denoted by the red underlining as shown in the following screenshot. This is because we pasted the code referring to MainActivity in our file which is called GameActivity.

    Simply change the text MainActivity to GameActivity and the error will disappear. Take a moment to see if you can work out what the other minor change is necessary, before I tell you.

  14. Remember that setContentView loads our UI design. Well what we need to do is change setContentView to load the new design (that we will build next) instead of the home screen design. Change setContentView(R.layout.activity_main); to setContentView(R.layout.activity_game);.
  15. Save your work and we are ready to move on.

Note the Project Explorer where Android Studio puts the two new files it created for us. I have highlighted two folders in the next screenshot. In future, I will simply refer to them as our java code folder or layout files folder.

You might wonder why we didn't simply copy and paste the MainActivity.java file to begin with and saved going through the process of creating a new activity? The reason is that Android Studio does things behind the scenes. Firstly, it makes the layout template for us. It also registers the new Activity for use through a file we will see later, called AndroidManifest.xml. This is necessary for the new activity to be able to work in the first place. All things considered, the way we did it is probably the quickest.

The code at this stage is exactly the same as the code for the home menu screen. We state the package name and import some useful classes provided by Android:

package com.packtpub.mathgamechapter3a.mathgamechapter3a;

import android.app.Activity;

import android.os.Bundle;

We create a new activity, this time called GameActivity:

public class GameActivity extends Activity {

Then we override the onCreate method and use the setContentView method to set our UI design as the contents of the player's screen. Currently, however, this UI is empty:

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

We can now think about the layout of our actual game screen.

Laying out the game screen UI

As we know, our math game will ask questions and offer the player some multiple choices to choose answers from. There are lots of extra features we could add, such as difficulty levels, high scores, and much more. But for now, let's just stick to asking a simple, predefined question and offering a choice of three predefined possible answers.

Keeping the UI design to the bare minimum suggests a layout. Our target UI will look somewhat like this:

The layout is hopefully self-explanatory, but let's ensure that we are really clear; when we come to building this layout in Android Studio, the section in the mock-up that displays 2 x 2 is the question and will be made up of three text views (both numbers, and the = sign is also a separate view). Finally, the three options for the answer are made up of Button layout elements. We used all of these UI elements, but this time, as we are going to be controlling them using our Java code, there are a few extra things we need to do to them. So let's go through it step by step:

  1. Open the file that will hold our game UI in the editor window. Do this by double-clicking on activity_game.xml. This is located in our UI layout folder which can be found in the project explorer.
  2. Delete the Hello World TextView, as it is not required.
  3. Find the Large Text element on the palette. It can be found under the Widgets section. Drag three elements onto the UI design area and arrange them near the top of the design as shown in the next screenshot. It does not have to be exact; just ensure that they are in a row and not overlapping, as shown in the following screenshot:

  4. Notice in the Component Tree window that each of the three TextViews has been assigned a name automatically by Android Studio. They are textView , textView2 and textView3:

  5. Android Studio refers to these element names as an id. This is an important concept that we will be making use of. So to confirm this, select any one of the textViews by clicking on its name (id), either in the component tree as shown in the preceding screenshot or directly on it in the UI designer shown previously. Now look at the Properties window and find the id property. You might need to scroll a little to do this:

    Notice that the value for the id property is textView. It is this id that we will use to interact with our UI from our Java code. So we want to change all the IDs of our TextViews to something useful and easy to remember.

  6. If you look back at our design, you will see that the UI element with the textView id is going to hold the number for the first part of our math question. So change the id to textPartA. Notice the lowercase t in text, the uppercase P in Part, and the uppercase A. You can use any combination of cases and you can actually name the IDs anything you like. But just as with naming conventions with Java variables, sticking to conventions here will make things less error-prone as our program gets more complicated.
  7. Now select textView2 and change id to textOperator.
  8. Select the element currently with id textView3 and change it to textPartB. This TextView will hold the later part of our question.
  9. Now add another Large Text from the palette. Place it after the row of the three TextViews that we have just been editing.

    This Large Text will simply hold our equals to sign and there is no plan to ever change it. So we don't need to interact with it in our Java code. We don't even need to concern ourselves with changing the ID or knowing what it is. If this situation changed, we could always come back at a later time and edit its ID.

  10. However, this new TextView currently displays Large Text and we want it to display an equals to sign. So in the Properties window, find the text property and enter the value =. We have changed the text property, and you might also like to change the text property for textPartA, textPartB, and textOperator. This is not absolutely essential because we will soon see how we can change it via our Java code; however, if we change the text property to something more appropriate, then our UI designer will look more like it will when the game runs on a real device.
  11. So change the text property of textPartA to 2, textPartB to 2, and textOperator to x. Your UI design and Component tree should now look like this:

  12. For the buttons to contain our multiple choice answers, drag three buttons in a row, below the = sign. Line them up neatly like our target design.
  13. Now, just as we did for the TextViews, find the id properties of each button, and from left to right, change the id properties to buttonChoice1, buttonChoice2, and buttonChoice3.
  14. Why not enter some arbitrary numbers for the text property of each button so that the designer more accurately reflects what our game will look like, just as we did for our other TextViews? Again, this is not absolutely essential as our Java code will control the button appearance.
  15. We are now actually ready to move on. But you probably agree that the UI elements look a little lost. It would look better if the buttons and text were bigger. All we need to do is adjust the textSize property for each TextView and for each Button. Then, we just need to find the textSize property for each element and enter a number with the sp syntax. If you want your design to look just like our target design from earlier, enter 70sp for each of the TextView textSize properties and 40sp for each of the Buttons textSize properties. When you run the game on your real device, you might want to come back and adjust the sizes up or down a bit. But we have a bit more to do before we can actually try out our game.
  16. Save the project and then we can move on.

As before, we have built our UI. This time, however, we have given all the important parts of our UI a unique, useful, and easy to identify ID. As we will see we are now able to communicate with our UI through our Java code.

Coding a question in Java

With our current knowledge of Java, we are not yet able to complete our math game but we can make a significant start. We will look at how we can ask the player a question and offer them some multiple choice answers (one correct and two incorrect).

At this stage, we know enough of Java to declare and initialize some variables that will hold the parts of our question. For example, if we want to ask the times tables question 2 x 2, we could have the following variable initializations to hold the values for each part of the question:

int partA = 2;

int partB = 2;

The preceding code declares and initializes two variables of the int type, each to the value of 2. We use int because we will not be dealing with any decimal fractions. Remember that the variable names are arbitrary and were just chosen because they seemed appropriate. Clearly, any math game worth downloading is going to need to ask more varied and advanced questions than 2 x 2, but it is a start.

Now we know that our math game will offer multiple choices as answers. So, we need a variable for the correct answer and two variables for two incorrect answers. Take a look at these combined declarations and initializations:

int correctAnswer = partA * partB;

int wrongAnswer1 = correctAnswer - 1;

int wrongAnswer2 = correctAnswer + 1;

Note that the initialization of the variables for the wrong answers depends on the value of the correct answer, and the variables for the wrong answers are initialized after initializing the correctAnswer variable.

Now we need to put these values, held in our variables, into the appropriate elements on our UI. The question variables (partA and partB) need to be displayed in our UI elements, textPartA and textPartB, and the answer variables (correctAnswer, wrongAnswer1, and wrongAnswer2) need to be displayed in our UI elements with the following IDs: buttonChoice1, buttonChoice2, and buttonChoice3. We will see how we do this in the next step-by-step tutorial. We will also implement the variable declaration and initialization code that we discussed a moment ago:

  1. First, open GameActivity.java in the editor window. Remember that you can do this by double-clicking on GameActivity in our java folder or clicking on its tab above the editor window if GameActivity.java is already open.
  2. All of our code will go into the onCreate method. It will go after the setContentView(R.layout.activity_game); line but before the closing curly brace } of the onCreate method. Perhaps, it's a good idea to leave a blank line for clarity and a nice explanatory comment as shown in the following code. We can see the entire onCreate method as it stands after the latest amendments. The parts in bold are what you need to add. Feel free to add helpful comments like mine if you wish:
    @Override
    
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            //The next line loads our UI design to the screen
    
            setContentView(R.layout.activity_game);
    
     
    
            //Here we initialize all our variables
    
            int partA = 9;
    
            int partB = 9;
    
            int correctAnswer = partA * partB;
    
            int wrongAnswer1 = correctAnswer - 1;
    
            int wrongAnswer2 = correctAnswer + 1;
    
     
    
        }//onCreate ends here
  3. Now we need to add the values contained within the variables to the TextView and Button of our UI. But first, we need to get access to the UI elements we created. We do that by creating a variable of the appropriate class and linking it via the ID property of the appropriate UI element. We already know the class of our UI elements: TextView and Button. Here is the code that creates our special class variables for each of the necessary UI elements. Take a close look at the code, but don't worry if you don't understand all of it now. We will dissect the code in detail once everything is working. Enter the code immediately after the code entered in the previous step. You can leave a blank line for clarity if you wish. Just before you proceed, note that at two points while typing in this code, you will be prompted to import another class. Go ahead and do so on both occasions:
    /*Here we get a working object based on either the button
    
    or TextView class and base as well as link our new   objects directly to the appropriate UI elements that we created previously*/
    
     
    
    TextView textObjectPartA = 
      (TextView)findViewById(R.id.textPartA);
    
     
    
    TextView textObjectPartB = 
      (TextView)findViewById(R.id.textPartB);
    
     
    
    Button buttonObjectChoice1 = 
      (Button)findViewById(R.id.buttonChoice1);
    
     
    
    Button buttonObjectChoice2 = 
      (Button)findViewById(R.id.buttonChoice2);
    
     
    
    Button buttonObjectChoice3 = 
      (Button)findViewById(R.id.buttonChoice3);

    In the preceding code, if you read the multiline comment, you will see that I used the term object. When we create a variable type based on a class, we call it an object. Once we have an object of a class, we can do anything that that class was designed to do.

  4. Now we have five new objects linked to the elements of our UI that we need to manipulate. What precisely are we going to do with them? We need to display the values of our variables in the text of the UI elements. We can use the objects we just created combined with a method provided by the class, and use our variables as values for that text. As usual, we will dissect this code further at the end of this tutorial. Here is the code to enter directly after the code in the previous step. Try and work out what is going on before we look at it together:
    //Now we use the setText method of the class on our objects
    
    //to show our variable values on the UI elements.
    
    //Just like when we output to the console in the exercise -
    
    //Expressions in Java, only now we use setText method
    
    //to put the values in our variables onto the actual UI.
    
    textObjectPartA.setText("" + partA);
    
    textObjectPartB.setText("" + partB);
    
     
    
    //which button receives which answer, at this stage is arbitrary.
    
     
    
    buttonObjectChoice1.setText("" + correctAnswer);
    
    buttonObjectChoice2.setText("" + wrongAnswer1);
    
    buttonObjectChoice3.setText("" + wrongAnswer2);
  5. Save your work.

If you play with the assignment values for partA and partB, you can make them whatever you like and the game adjusts the answers accordingly. Obviously, we shouldn't need to reprogram our game each time we want a new question and we will solve that problem soon. All we need to do now is link the game section we have just made to the start screen menu. We will do that in the next tutorial.

Now lets explore the trickier and newer parts of our code in more detail.

In step 2, we declared and initialized the variables required so far:

//Here we initialize all our variables

int partA = 2;

int partB = 2;

int correctAnswer = partA * partB;

int wrongAnswer1 = correctAnswer - 1;

int wrongAnswer2 = correctAnswer + 1;

Then in step 3, we got a reference to our UI design through our Java code. For the TextViews, it was done like this:

TextView textObjectPartA = (TextView)findViewById(R.id.textPartA);

For each of the buttons, a reference to our UI design was obtained like this:

Button buttonObjectChoice1 = 
  Button)findViewById(R.id.buttonChoice1);

In step 4, we did something new. We used a the setText method to show the values of our variables on our UI elements (TextView and Button) to the player. Let's break down one line completely to see how it works. Here is the code that shows the correctAnswer variable being displayed on buttonObjectChoice1.

buttonObjectChoice1.setText("" + correctAnswer);

By typing buttonObjectChoice1 and adding a period, as shown in the following line of code, we have access to all the preprogrammed methods of that object's class type that are provided by Android:

The power of Button and the Android API

There are actually lots of methods that we can perform on an object of the Button type. If you are feeling brave, try this to get a feeling of just how much functionality there is in Android.

Type the following code:

buttonObjectChoice1

Be sure to type the period on the end. Android Studio will pop up a list of possible methods to use on this object. Scroll through the list and get a feel of the number and variety of options:

If a mere button can do all of this, think of the possibilities for our games once we have mastered all the classes contained in Android. A collection of classes designed to be used by others is collectively known as an Application Programmers Interface (API). Welcome to the Android API!

In this case, we just want to set the button's text. So, we use setText and concatenate the value stored in our correctAnswer variable to the end of an empty string, like this:

setText("" + correctAnswer);

We do this for each of the UI elements we require to show our variables.

Playing with autocomplete

If you tried the previous tip, The power of Button and the Android API, and explored the methods available for objects of the Button type, you will already have some insight into autocomplete. Note that as you type, Android Studio is constantly making suggestions for what you might like to type next. If you pay attention to this, you can save a lot of time. Simply select the correct code completion statement that is suggested and press Enter. You can even see how much time you saved by selecting Help | Productivity Guide from the menu bar. Here you will see statistics for every aspect of code completion and more. Here are a few entries from mine:

As you can see, if you get used to using shortcuts early on, you can save a lot of time in the long run.

Linking our game from the main menu

At the moment, if we run the app, we have no way for the player to actually arrive at our new game activity. We want the game activity to run when the player clicks on the Play button on the main MainActivity UI. Here is what we need to do to make that happen:

  1. Open the file activity_main.xml, either by double-clicking on it in the project explorer or by clicking its tab in the editor window.
  2. Now, just like we did when building the game UI, assign an ID to the Play button. As a reminder, click on the Play button either on the UI design or in the component tree. Find the id property in the Properties window. Assign the buttonPlay value to it. We can now make this button do stuff by referring to it in our Java code.
  3. Open the file MainActivity.java, either by double-clicking on it in the project explorer or clicking on its tab in the editor window.
  4. In our onCreate method, just after the line where we setContentView, add the following highlighted line of code:
    setContentView(R.layout.activity_main);
    
    Button buttonPlay = (Button)findViewById(R.id.buttonPlay);
  5. We will dissect this code in detail once we have got this working. Basically we are making a connection to the Play button by creating a reference variable to a Button object. Notice that both words are highlighted in red indicating an error. Just as before, we need to import the Button class to make this code work. Use the Alt + Enter keyboard combination. Now click on Import class from the popped-up list of options. This will automatically add the required import directive at the top of our MainActivity.java file.
  6. Now for something new. We will give the button the ability to listen to the user clicking on it. Type this immediately after the last line of code we entered:
    buttonPlay.setOnClickListener(this);

    Notice how the this keyword is highlighted in red indicating an error. Setting that aside, we need to make a modification to our code now in order to allow the use of an interface that is a special code element that allows us to add a functionality, such as listening for button clicks. Edit the line as follows. When prompted to import another class, click on OK:

  7. public class MainActivity extends Activity {
    
    to
    
    public class MainActivity extends Activity implements View.OnClickListener{

    Now we have the entire line underlined in red. This indicates an error but it's where we should be at this point. We mentioned that by adding implements View.OnClickListener, we have implemented an interface. We can think of this like a class that we can use but with extra rules. The rules of the OnClickListener interface state that we must implement/use one of its methods. Notice that until now, we have optionally overridden/used methods as and when they have suited us. If we wish to use the functionality this interface provides, namely listening for button presses, then we have to add/implement the onClick method.

  8. This is how we do it. Notice the opening curly brace, {, and the closing curly brace, }. These denote the start and end of the method. Notice that the method is empty and it doesn't do anything, but an empty method is enough to comply with the rules of the OnClickListener interface, and the red line indicating an that our code has an error has gone. Make sure that you type the following code, outside the closing curly brace (}) of the onCreate method but inside the closing curly brace of our MainActivity class:
    @Override
    
        public void onClick(View view) {
    
     
    
           
    
        }
  9. Notice that we have an empty line between { and } of the onClick method. We can now add code in here to make the button actually do something. Type the following highlighted code between { and } of onClick:
    @Override
    
        public void onClick(View view) {
    
            Intent i;
    
            i = new Intent(this, GameActivity.class);
    
            startActivity(i);
    
        }
    

    OK, so that code is a bit of a mouthful to comprehend all at once. See if you can guess what is happening. The clue is in the method named startActivity and the hopefully familiar term, GameActivity. Notice that we are assigning something to i. We will quickly get our app working and then diagnose the code in full.

  10. Notice that we have an error: all instances of the word Intent are red. We can solve this by importing the classes required to make Intent work. As before press Alt + Enter.
  11. Run the game in the emulator or on your device.

Our app will now work. This is what the new game screen looks like after pressing Play on the menu screen:

Almost every part of our code has changed a little and we have added a lot to it as well. Let's go over the contents of MainActivity.java and look at it line by line. For context, here it is in full:

package com.packtpub.mathgamechapter3a.mathgamechapter3a;

 

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

 

 

public class MainActivity extends Activity implements View.OnClickListener{

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        final Button buttonPlay = 
          (Button)findViewById(R.id.buttonPlay);

        buttonPlay.setOnClickListener(this);

    }

 

    @Override

    public void onClick(View view) {

        Intent i;

        i = new Intent(this, GameActivity.class);

        startActivity(i);

    }

 

}

We have seen much of this code before, but let's just go over it a chunk at a time before moving on so that it is absolutely clear. The code works like this:

package com.packtpub.mathgamechapter3a.mathgamechapter3a;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

You would probably remember that this first block of code defines what our package is called and makes available all the Android API stuff we need for Button, TextView, and Activity.

From our MainActivity.java file, we have this:

public class MainActivity extends Activity implements View.OnClickListener{

Our MainActivity declaration with our new bit of code implements View.OnClickListener that gives us the ability to detect button clicks.

Next in our code is this:

@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

It is at the start of our onCreate method where we first ask the hidden code of onCreate to do its stuff using super.onCreate(savedInstanceState);. Then we set our UI to the screen with setContentView(R.layout.activity_main);.

Next, we get a reference to our button with an ID of buttonPlay:

Button buttonPlay = (Button)findViewById(R.id.buttonPlay);

buttonPlay.setOnClickListener(this);

Finally, our onClick method uses the Intent class to send the player to our GameActivity class and the related UI when the user clicks on the Play button:

 @Override

    public void onClick(View view) {

        Intent i;

        i = new Intent(this, GameActivity.class);

        startActivity(i);

    }

If you run the app, you will notice that we can now click on the Play button and our math game will ask us a question. Of course, we can't answer it yet. Although we have very briefly looked at how to deal with button presses, we need to learn more of Java in order to intelligently react to them. We will also reveal how to write code to handle presses from several buttons. This will be necessary to receive input from our multiple-choice-centric game_activity UI.

Decisions in Java

We can now summon enough of Java prowess to ask a question but a real math game must obviously do much more than this. We need to capture the player's answer, and we are nearly there with that—we can detect button presses. From there, we need to be able to decide whether their answer is right or wrong. Then, based on this decision, we have to choose an appropriate course of action.

Let's leave the math game aside for now and look at how Java might help us by learning some more fundamentals and syntax of the Java language.

More operators

Let's look at some more operators: we can already add (+), take away (-), multiply (*), divide (/), assign (=), increment (++), compare (==), and decrement (--) with operators. Let's introduce some more super-useful operators, and then we will go straight to actually understanding how to use them in Java.

Don't worry about memorizing every operator given here. Glance at them and their explanations. There, we will put some operators to use and they will become much clearer as we see a few examples of what they allow us to do. They are presented here in a list just to make the variety and scope of operators plain from the start. The list will also be more convenient to refer back to when not intermingled with the discussion about implementation that follows it.

  • ==: This is a comparison operator we saw this very briefly before. It tests for equality and is either true or false. An expression like (10 == 9);, for example, is false.
  • !: The logical NOT operator. The expression, ! (2+2==5).), is true because 2+2 is NOT 5.
  • !=: This is another comparison operator which tests if something is NOT equal. For example, the expression, (10 != 9);), is true, that is, 10 is not equal to 9.
  • >: This is another comparison operator which tests if something is greater than something else. The expression, (10 > 9);), is true. There are a few more comparison operators as well.
  • <: You guessed it. This tests whether the value to the left is less than the value to the right or not. The expression, (10 < 9);, is false.
  • >=: This operator tests whether one value is greater than or equal to the other, and if either is true, the result is true. For example, the expression, (10 >= 9);, is true. The expression, (10 >= 10);, is also true.
  • <=: Like the preceding operator, this operator tests for two conditions but this time, less than and equal to. The expression, (10 <= 9);, is false. The expression, (10 <= 10);, is true.
  • &&: This operator is known as logical AND. It tests two or more separate parts of an expression and all parts must be true in order for the result to be true. Logical AND is usually used in conjunction with the other operators to build more complex tests. The expression, ((10 > 9) && (10 < 11));, is true because both parts are true. The expression, ((10 > 9) && (10 < 9));, is false because only one part of the expression is true and the other is false.
  • ||: This operator is called logical OR. It is just like logical AND except that only one of two or more parts of an expression need to be true for the expression to be true. Let's look at the last example we used but replace the && sign with ||. The expression, ((10 > 9) || (10 < 9));, is now true because one part of the expression is true.

All of these operators are virtually useless without a way of properly using them to make real decisions that affect real variables and code. Let's look at how to make decisions in Java.

Decision 1 – If they come over the bridge, shoot them

As we saw, operators serve hardly any purpose on their own but it was probably useful to see just a part of the wide and varied range available to us. Now, when we look at putting the most common operator, ==, to use, we can start to see the powerful yet fine control that operators offer us.

Let's make the previous examples less abstract using the Java if keyword, a few conditional operators, and a small story: in use with some code and a made up military situation that will hopefully make the following examples less abstract.

The captain is dying and, knowing that his remaining subordinates are not very experienced, he decides to write a Java program to convey his last orders after he has died. The troops must hold one side of a bridge while awaiting reinforcements.

The first command the captain wants to make sure his troops understand is this: If they come over the bridge, shoot them.

So how do we simulate this situation in Java? We need a Boolean variable isComingOverBridge. The next bit of code assumes that the isComingOverBridge variable has been declared and initialized.

We can then use it like this:

if(isComingOverBridge){

  //Shoot them

}

If the isComingOverBridge Boolean is true, the code inside the opening and closing curly braces will run. If not, the program continues after the if block without running it.

Decision 2 – Else, do this

The captain also wants to tell his troops what to do (stay put) if the enemy is not coming over the bridge.

Now we introduce another Java keyword, else. When we want to explicitly do something and the if block does not evaluate to true, we can use else.

For example, to tell the troops to stay put if the enemy is not coming over the bridge, we use else:

if(isComingOverBridge){

  //Shoot them

}else{

  //Hold position

}

The captain then realized that the problem wasn't as simple as he first thought. What if the enemy comes over the bridge and has more troops? His squad will be overrun. So, he came up with this code (we'll use some variables as well this time):

boolean isComingOverTheBridge;

int enemyTroops;

int friendlyTroops;

//Code that initializes the above variables one way or another

 

//Now the if

if(isComingOverTheBridge && friendlyTroops > enemyTroops){

  //shoot them

}else if(isComingOverTheBridge && friendlyTroops < enemyTroops) {

  //blow the bridge

}else{

  //Hold position

}

Finally, the captain's last concern was that if the enemy came over the bridge waving the white flag of surrender and were promptly slaughtered, then his men would end up as war criminals. The Java code needed was obvious. Using the wavingWhiteFlag Boolean variable he wrote this test:

if (wavingWhiteFlag){

  //Take prisoners

}

But where to put this code was less clear. In the end, the captain opted for the following nested solution and changing the test for wavingWhiteFlag to logical NOT, like this:

if (!wavingWhiteFlag){//not surrendering so check everything else

  if(isComingOverTheBridge && friendlyTroops > enemyTroops){

    //shoot them

  }else if(isComingOverTheBridge && friendlyTroops < 
  enemyTroops) {

    //blow the bridge

  }

}else{//this is the else for our first if

  //Take prisoners

{

//Holding position

This demonstrates that we can nest if and else statements inside of one another to create even deeper decisions.

We could go on making more and more complicated decisions but what we have seen is more than sufficient as an introduction. Take the time to reread this if anything is unclear. It is also important to point out that very often, there are two or more ways to arrive at the solution. The right way will usually be the way that solves the problem in the clearest and simplest manner.

Switching to make decisions

We have seen the vast and virtually limitless possibilities of combining the Java operators with if and else statements. But sometimes a decision in Java can be better made in other ways.

When we have to make a decision based on a clear list of possibilities that doesn't involve complex combinations, then switch is usually the way to go.

We start a switch decision like this:

switch(argument){

 

}

In the previous example, an argument could be an expression or a variable. Then within the curly braces, we can make decisions based on the argument with case and break elements:

case x:

  //code to for x

  break;

 

case y:

  //code for y

  break;

You can see that in the previous example, each case states a possible result and each break denotes the end of that case as well as the point at which no further case statements should be evaluated. The first break encountered takes us out of the switch block to proceed with the next line of code.

We can also use default without a value to run some code if none of the case statements evaluate to true, like this:

default://Look no value

  //Do something here if no other case statements are true

break;

Supposing we are writing an old-fashioned text adventure game—the kind of game where the player types commands such as "Go East", "Go West", "Take Sword", and so on. In this case, switch could handle that situation like this example code and we could use default to handle the case of the player typing a command that is not specifically handled:

//get input from user in a String variable called command

switch(command){

 

  case "Go East":":

  //code to go east

  break;

 

  case "Go West":

  //code to go west

  break;

  case "Take sword":

  //code to take the sword

  break;

 

  //more possible cases

 

  default:

  //Sorry I don't understand your command

  break;

 

}

We will use switch so that our onClick method can handle the different multiple-choice buttons of our math game.

Java has even more operators than we have covered here. We have looked at all the operators we are going to need in this book and probably the most used in general. If you want the complete lowdown on operators, take a look at the official Java documentation at http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html.

Math game – getting and checking the answer

Here we will detect the right or wrong answer and provide a pop-up message to the player. Our Java is getting quite good now, so let's dive in and add these features. I will explain things as we go and then, as usual, dissect the code thoroughly at the end.

The already completed code is in the download bundle, in the following files that correspond to the filenames we will create/autogenerate in Android Studio in a moment:

  • Chapter 3/MathGameChapter3b/java/MainActivity.java
  • Chapter 3/MathGameChapter3b/java/GameActivity.java
  • Chapter 3/MathGameChapter3b/layout/activity_main.xml
  • Chapter 3/MathGameChapter3b/layout/activity_game.xml

As usual, I recommend following this tutorial step by step to see how we can create all of the code for ourselves.

  1. Open the GameActivity.java file visible in the editor window.
  2. Now we need to add the click detection functionality to our GameActivity, just as we did for our MainActivity. However, we will go a little further than the last time. So let's do it step by step as if it is totally new. Once again, we will give the buttons the ability to listen to the user clicking on them. Type this immediately after the last line of code we entered in the onCreate method but before the closing }. This time of course, we need to add some code to listen to three buttons:
    buttonObjectChoice1.setOnClickListener(this);
    
    buttonObjectChoice2.setOnClickListener(this);
    
    buttonObjectChoice3.setOnClickListener(this);
  3. Notice how the this keyword is highlighted in red indicating an error. Again, we need to make a modification to our code in order to allow the use of an interface, the special code element that allows us to add functionalities such as listening to button clicks. Edit the line as follows. When prompted to import another class, click on OK. Consider this line of code:
    public class GameActivity extends Activity {
    
    Change it to the following line:
    
    public class GameActivity extends Activity implements View.OnClickListener{

     

  4. Now we have the entire preceding line underlined in red. This indicates an error but it is where we should be at this point. We mentioned that by adding implements View.OnClickListener, we have implemented an interface. We can think of this like a class that we can use, but with extra rules. One of the rules of the OnClickListener interface is that we must implement one of its methods, as you might remember. If we wish to use the useful functionality this interface provides (listening to button presses). Now we will add the onClick method.
  5. Type the following code. Notice the opening curly brace, {, and the closing curly brace, }. These denote the start and end of the method. Notice that the method is empty; it doesn't do anything but an empty method is enough to comply with the rules of the OnClickListener interface and the red line that indicated an error has gone. Make sure that you type the following code outside the closing curly brace (}) of the onCreate method but inside the closing curly brace of our MainActivity class:
    @Override
    
        public void onClick(View view) {
    
    
        }
  6. Notice that we have an empty line between the { and } braces of our onClick method. We can now put some code in here to make the buttons actually do something. Type the following in between { and } of onClick. This is where things get different from our code in MainActivity. We need to differentiate between the three possible buttons that could be pressed. We will do this with the switch statement that we discussed earlier. Look at the case criteria; they should look familiar. Here is the code that uses the switch statements:
    switch (view.getId()) {
    
     
    
                case R.id.buttonChoice1:
    
                //button 1 stuff goes here
    
                    break;
    
     
    
                case R.id.buttonChoice2:
    
                //button 2 stuff goes here
    
                    break;
    
     
    
                case R.id.buttonChoice3:
    
               //button 3 stuff goes here
    
                    break;
    
     
    
            }

     

  7. Each case element handles a different button. For each button case, we need to get the value stored in the button that was just pressed and see if it matches our correctAnswer variable. If it does, we must tell the player they got it right, and if not, we must tell them they got it wrong. However, there is still one problem we have to solve. The onClick method is separate from the onCreate method and the Button objects. In fact, all the variables are declared in the onCreate method. If you try typing the code from step 9 now, you will get lots of errors. We need to make all the variables that we need in onClick available in onClick. To do this, we will move their declarations from above the onCreate method to just below the opening { of GameActivity. This means that these variables become variables of the GameActivity class and can be seen anywhere within GameActivity. Declare the following variables like this:
    int correctAnswer;
    
    Button buttonObjectChoice1;
    
    Button buttonObjectChoice2;
    
    Button buttonObjectChoice3;
  8. Now change the initialization of these variables within onCreate as follows. The actual parts of code that need to be changed are highlighted. The rest is shown for context:
    //Here we initialize all our variables
    
    int partA = 9;
    
    int partB = 9;
    
    correctAnswer = partA * partB;
    
    int wrongAnswer1 = correctAnswer - 1;
    
    int wrongAnswer2 = correctAnswer + 1;
    
    and
    
    TextView textObjectPartA = 
      (TextView)findViewById(R.id.textPartA);
    
     
    
    TextView textObjectPartB = 
      (TextView)findViewById(R.id.textPartB);
    
     
    
    buttonObjectChoice1 = (Button)findViewById(R.id.buttonChoice1);
    
           
    
    buttonObjectChoice2 = (Button)findViewById(R.id.buttonChoice2);
    
           
    
    buttonObjectChoice3 = (Button)findViewById(R.id.buttonChoice3);

     

  9. Here is the top of our onClick method as well as the first case statement for our onClick method:
    @Override
    
        public void onClick(View view) {
    
            //declare a new int to be used in all the cases
    
            int answerGiven=0;
    
            switch (view.getId()) {
    
     
    
                case R.id.buttonChoice1:
    
                //initialize a new int with the value contained in buttonObjectChoice1
    
                //Remember we put it there ourselves previously
    
                    answerGiven = Integer.parseInt("" + 
                        buttonObjectChoice1.getText());
    
     
    
                    //is it the right answer?
    
                    if(answerGiven==correctAnswer) {//yay it's the right answer
    
                        Toast.makeText(getApplicationContext(), 
                          "Well done!", 
                          Toast.LENGTH_LONG).show();
    
                    }else{//uh oh!
    
                        Toast.makeText(getApplicationContext(),"Sorry that's 
        wrong", Toast.LENGTH_LONG).show();
    
                    }
    
                    break;

     

  10. Here are the rest of the case statements that do the same steps as the code in the previous step except handling the last two buttons. Enter the following code after the code entered in the previous step:
      case R.id.buttonChoice2:
    
                    //same as previous case but using the next button
    
                    answerGiven = Integer.parseInt("" + 
                      buttonObjectChoice2.getText());
    
                    if(answerGiven==correctAnswer) {
    
                        Toast.makeText(getApplicationContext(), "Well done!", Toast.LENGTH_LONG).show();
    
                    }else{
    
                        Toast.makeText(getApplicationContext(),"Sorry that's wrong", Toast.LENGTH_LONG).show();
    
                    }
    
                    break;
    
     
    
                case R.id.buttonChoice3:
    
                    //same as previous case but using the next button
    
                    answerGiven = Integer.parseInt("" + 
                        buttonObjectChoice3.getText());
    
                    if(answerGiven==correctAnswer) {
    
                        Toast.makeText(getApplicationContext(), "Well done!", Toast.LENGTH_LONG).show();
    
                    }else{
    
                        Toast.makeText(getApplicationContext(),"Sorry that's wrong", Toast.LENGTH_LONG).show();
    
                    }
    
                    break;
    
     
    
            }
  11. Run the program, and then we will look at the code carefully, especially that odd-looking Toast thing. Here is what happens when we click on the leftmost button:

This is how we did it: In steps 1 through 6, we set up handling for our multi-choice buttons, including adding the ability to listen to clicks using the onClick method and a switch block to handle decisions depending on the button pressed.

In steps 7 and 8, we had to alter our code to make our variables available in the onClick method. We did this by making them member variables of our GameActivity class.

When we make a variable a member of a class, we call it a field.

In steps 9 and 10, we implemented the code that actually does the work in our switch statement in onClick. Let's take a line-by-line look at the code that runs when button1 is pressed.

case R.id.buttonChoice1:

First, the case statement is true when the button with an id of buttonChoice1 is pressed. Then the next line of code to execute is this:

answerGiven = Integer.parseInt(""+ buttonObjectChoice1.getText());

The preceding line gets the value on the button using two methods. First, getText gets the number as a string and then Integer.parseInt converts it to an int. The value is stored in our answerGiven variable. The following code executes next:

if(answerGiven==correctAnswer) {//yay it's the right answer

  Toast.makeText(getApplicationContext(), "Well done!", 
    Toast.LENGTH_LONG).show();

}else{//uh oh!

    Toast.makeText(getApplicationContext(),"Sorry that's wrong", 
      Toast.LENGTH_LONG).show();

                }

The if statement tests to see if the answerGiven variable is the same as correctAnswer using the == operator. If so, the makeText method of the Toast object is used to display a congratulatory message. If the values of the two variables are not the same, the message displayed is a bit more negative one.

The Toast line of code is possibly the most evil thing we have seen thus far. It looks exceptionally complicated and it does need a greater knowledge of Java than we have at the moment to understand. All we need to know for now is that we can use the code as it is and just change the message, and it is a great tool to announce something to the player. If you really want an explanation now, you can think of it like this: when we made button objects, we got to use all the button methods. But with Toast, we used the class directly to access its setText method without creating an object first. We can do this process when the class and its methods are designed to allow it.

Finally, we break out of the whole switch statement as follows:

break;

Self-test questions

Q1) What does this code do?

// setContentView(R.layout.activity_main);

Q2) Which of these lines causes an error?

String a = "Hello";

String b = " Vinton Cerf";

int c = 55;

a = a + b

c = c + c + 10;

a = a + c;

c = c + a;

Q3) We talked a lot about operators and how different operators can be used together to build complicated expressions. Expressions, at a glance, can sometimes make the code look complicated. However, when looked at closely, they are not as tough as they seem. Usually, it is just a case of splitting the expressions into smaller pieces to work out what is going on. Here is an expression that is more convoluted than anything else you will ever see in this book. As a challenge, can you work out: what will x be?

int x = 10;

int y = 9;

boolean isTrueOrFalse = false;

isTrueOrFalse = (((x <=y)||(x == 10))&&((!isTrueOrFalse) || (isTrueOrFalse)));

Summary

We went from knowing nothing about Java syntax to learning about comments, variables, operators, and decision making.

As with any language, mastery of Java can be achieved by simply practicing, learning, and increasing our vocabulary. At this point, the temptation might be to hold back until mastery of the current Java syntax has been achieved, but the best way is to move on to new syntax at the same time as revisiting what we have already begun to learn.

We will finally finish our math game by adding random questions of multiple difficulties as well as using more appropriate and random wrong answers for the multiple choice buttons.

To enable us to do this, we will first learn some more new on Java and syntax.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Learning Java by Building Android Games

Explore Title