Final level of the Android Application Development series. With this tutorial documentation, this will enable mobile developers to gain complete basic knowledge of Android Development. After completing all 3 of the levels, the developers can proceed with intermediary and advanced concepts.
2. 1
Table Of Contents
1. Prerequisite ...........................................................2
2. Workshop Objective .....................................................2
3. TableLayout and TableRow ...............................................2
4. Control Flow Statements ................................................3
5. Decision-making ........................................................3
6. Looping ................................................................5
7. Branching Statements ...................................................6
8. Array..................................................................7
9. Building a game - Tic-Tac-Toe ..........................................7
3. 2
1. Prerequisite
It is assumed that the learner has completed Android Application Development - Level 1 and Level
2 and have basic knowledge of object-orient programming concepts in Java.
2. Workshop Objective
Level 3 workshop aim to let learners to further improve skills of Android App Development by:
• Understanding a new concept - TableLayout and TableRow for designing UI using XML.
• Understanding Control Flow statements in depth to be used in Java.
• Understanding Loop and Array concepts.
• Apply these concepts to create an interactive computerized game.
3. TableLayout and TableRow
TableLayout is a type of ViewGroup which have only one child element i.e. TableRow. It displays
its child element as cells into columns and rows. TableRow view will be used as its child element
to build a row in table. Each row can have many cells or no cells at all. And each cell can hold one
View object i.e. ImageView, TextView or Button.
Figure 1: TableLayout and TableRow
4. 3
If TableRow is not used as child of TableLayout, it will act as LinearLayout ViewGroup. It is also
to be noted that by default, children of TableRow are horizontally oriented. Element tag for
TableLayout and TableRow to be used in activity_main.xml file as follows:
Table 1: TableLayout and TableRow Element
TableLayout This tag will allow to implement TableLayout ViewGroup. Same attributes
will be used as that of parent LinearLayout.
TableRow This tag will allow to implement TableRow View. Same attributes will be
used as that of child LinearLayout.
4. Control Flow Statements
Control flow is the order in which individual statements or methods(functions) of a program are
executed and evaluated. By default, our programs are executed from top to bottom in the order like
how it appears. However, to speed up execution process and to make our lives easier, control flow
statements in any programming language comes into play by employing decision-making, looping
and branching. This will allow to execute particular blocks of code conditionally, to repeat
execution, and/or change the normal sequential flow of control.
5. Decision-making
It is the way to control the flow of execution of a program or block of code in a program
conditionally. There are two ways to implement decision-making of the program - if-then-else
statements and switch case statements.
The if statement will executes a certain section of code if the test expression is evaluated to true.
Therefore, it must return a boolean value. if statement can have optional else if and else statements.
Codes inside the body of else statement are executed if the test expression for both if and else if
statements are false. E.g. as follows:
class posnegcheck {
public static void main(String[] args) {
int num = 0;
5. 4
if (num > 0) {
System.out.println("Number is positive.");
}
else if (num < 0) {
System.out.println("Number is negative.");
}
else {
System.out.println("Number is 0.");
}
}
}
The output will be "Number is 0." as both test expressions of if and else if statements fails.
Switch statement can be used as alternative to long if - else if statements to make code more
readable. switch statement evaluates it's expression (mostly variable) and compares with values(can
be expression) of each case label. It runs executes all statements that matches with case label. It is
to note that switch statement in Java only works with primitive data types - byte, short, char
and int, enumerated types (Java enums), String class and a few classes that wrap primitive types:
Character, Byte, Short, and Integer. Example as follows:
class Day {
public static void main(String[] args) {
int week = 4;
String day;
switch (week) {
case 1:
day = "Sunday";
break;
case 2:
day = "Monday";
break;
case 3:
day = "Tuesday";
break;
case 4:
day = "Wednesday";
break;
6. 5
case 5:
day = "Thursday";
break;
case 6:
day = "Friday";
break;
case 7:
day = "Saturday";
break;
default:
day = "Invalid day";
break;
}
System.out.println(day);
}
}
As week variable is assigned to 4, expression of switch statement is also set to 4. Therefore, block
of code under case 4. So the output that will be displayed is Wednesday.
Notice, the use of break statement. This statement terminates the execution of switch statement.
The break statements are important because if they are not used, all statements after the matching
case label are executed in sequence until the end of switch statement.
6. Looping
It is the means of repeating execution of a program or block of code in a program until certain
condition is met i.e. when test expression becomes false. It is the loops that makes our computers
interesting machines. There are two ways to implement loops in a program namely - while loop and
for loop.
while statement continually executes a block of statements while a particular condition is true. The
test expression inside the brackets is boolean expression. If the test expression is checked and turns
out to be true, lines of codes inside the while loop will be executed and then test expression will
be checked again. These statements will repeatedly get executed until test expression becomes
false. Example as follows:
7. 6
class Loop {
public static void main(String[] args) {
int i = 1;
while (i < 10) {
System.out.println("Line " + i);
i++;
}
}
}
The above piece of code will allow to display output from Line 1 to Line 9 in each new line. Initially,
i is assigned as one and i++ will allow to increase its original value by 1 or we can say increment
to be more specific. When i reaches to 10, the test expression becomes false. So the loop will
iterate 9 times and then it terminates.
for statement provides an easier way to iterate over a range of values. Similar to while loop, it
continues to execute block of code or a program repeatedly until test expression is evaluated to
return false. Inside for loop, there is initialization expression, which is executed only once. Then
there is test expression which is a boolean expression. If this boolean expression is true, the loop
will continue to execute and there is update variable in the for loop statement which will get updated
at the end of execution of block of code inside it. Once boolean expression returns false, the for
loop terminates and breaks out of it. E.g. as follows:
class Loop {
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
System.out.println("Line " + i);
}
}
The code above is equivalent to the example code of while loop. It will give exactly the same output
as that while loop code. After end of execution of code inside for loop, update variable i++, will
get updated by 1. When this update variable reaches to 10, the test expression becomes false and
for loop terminates.
7. Branching Statements
It consists of two statements - break, continue and return. These statements are used to create
sophisticated algorithm and looping constructs. break statement in java is used to break the loop
8. 7
and transfers control to the line immediate outside of loop. It is also used in switch cases to terminate
execution of block of code. continue is used to escape current iteration and transfers control back
to the start of the loop. return is used to explicitly return from a method(function). At any time in
a method, return statement can be used to cause execution to branch back to the caller of the
method. Hence it immediately terminates the method in which return statement is ran.
8. Array
Array is a container object that holds a number of values of a single type. Generally, in Java, arrays
are of static type i.e. at the time of array declaration, it is decided how many values will it hold.
Later, even if we need to update array length, we will not be able to. In order to overcome this issue,
Arraylist<E>, public class built by Java will be used. E is the data type - String, Integer, Double.
9. Building a game - Tic-Tac-Toe
By making use of the concepts we have explored and discovered in Level 1, Level 2 and this Level,
we will be building an interactive game to be played against the computer - Tic-Tac-Toe.
After creating project, set android:screenOrientation=“portrait” attribute in
AndroidManifest.xml file. This will allow to lock the screen to only vertical position of the
application even when the device is held horizontally.
Then write the following code in styles.xml file as follows:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">#8E24AA</item>
<item name="colorPrimaryDark">#4A0072</item>
<!-- Background color of buttons in the app -->
<item name="colorButtonNormal">#BA68C8</item>
</style>
</resources>
9. 8
❖ Discussion
Purple color theme is chosen for this application and color codes are set as per the Material
Design of UI.
Now write the following code in activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E1BEE7"
android:gravity="center"
android:id="@+id/table_layout">
<TableRow
android:id="@+id/Table_row_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="50pt"
android:layout_margin="3dp"
android:layout_weight="1"
android:onClick="BuClick"
android:text=""
android:textSize="50sp" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="50pt"
android:layout_margin="3dp"
android:layout_weight="1"
android:onClick="BuClick"
android:text=""
android:textSize="50sp" />
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="50pt"
android:layout_margin="3dp"
android:layout_weight="1"
android:onClick="BuClick"
android:text=""
12. 11
Figure 2: UI of Tic-Tac-Toe game
❖ Discussion
➢ RelativeLayout is coded to be the parent layout of the UI of this application. Within this layout
consists of TableLayout and a Button as its children. Background color is set as per the material
design of UI and color theme of this app.
➢ Attributes of TableLayout is set similar to that of LinearLayout. Within this layout consists of
three TableRows it’s children. To align its children in center of UI, gravity attribute is set to center.
➢ Each TableRow consists of three Buttons as its children. layout width and height attributes are
set to match_parent and wrap_content for all of the TableRows and orientation is set to horizontal.
➢ All of the Buttons attributes are set to occupy equal space inside TableRow. height is set to 50pt
and textSize of 50sp is set. onClick attribute - BuClick is set to be same for all of the buttons.
Default text is set to empty string.
➢ Button to start a new game is aligned and centered at the bottom onClick attribute - newGame is
assigned to it which is to be used as method in Java that will allow to restart a new game.
Write the following code in main_activity.java file above @Override:
13. 12
int ActivePlayer = 1;
ArrayList<Integer> Player1 = new ArrayList<Integer>();
ArrayList<Integer> Player2 = new ArrayList<Integer>();
Finally, write the following code below onCreate method:
public void BuClick(View view) {
Button Selected = (Button) view;
int CellID = 0;
switch ((Selected.getId())) {
case R.id.button1:
CellID = 1;
break;
case R.id.button2:
CellID = 2;
break;
case R.id.button3:
CellID = 3;
break;
case R.id.button4:
CellID = 4;
break;
case R.id.button5:
CellID = 5;
break;
case R.id.button6:
CellID = 6;
break;
case R.id.button7:
CellID = 7;
break;
case R.id.button8:
CellID = 8;
break;
case R.id.button9:
CellID = 9;
break;
}
PlayGame(CellID, Selected);
}
void PlayGame(int CellID, Button Selected) {
if (ActivePlayer == 1) {
Selected.setText("X");
Selected.setBackgroundColor(Color.GREEN);
Player1.add(CellID);
ActivePlayer = 2;
autoPlay();
15. 14
Winner = 2;
}
//col 2
if (Player1.contains(2) && Player1.contains(5) && Player1.contains(8)) {
Winner = 1;
}
if (Player2.contains(2) && Player2.contains(5) && Player2.contains(8)) {
Winner = 2;
}
//col 3
if (Player1.contains(3) && Player1.contains(6) && Player1.contains(9)) {
Winner = 1;
}
if (Player2.contains(3) && Player2.contains(6) && Player2.contains(9)) {
Winner = 2;
}
//diagonal 1
if (Player1.contains(1) && Player1.contains(5) && Player1.contains(9)) {
Winner = 1;
}
if (Player2.contains(1) && Player2.contains(5) && Player2.contains(9)) {
Winner = 2;
}
//diagonal 2
if (Player1.contains(3) && Player1.contains(5) && Player1.contains(7)) {
Winner = 1;
}
if (Player2.contains(3) && Player2.contains(5) && Player2.contains(7)) {
Winner = 2;
}
if (Winner != -1) {
if (Winner == 1) {
Toast.makeText(this, "Player 1 is the winner! ",
Toast.LENGTH_SHORT).show();
end = true;
}
if (Winner == 2) {
Toast.makeText(this, "Player 2 is the winner! ",
Toast.LENGTH_SHORT).show();
end = true;
}
}
if (end) {
Select1.setEnabled(false);
Select2.setEnabled(false);
Select3.setEnabled(false);
Select4.setEnabled(false);
Select5.setEnabled(false);
Select6.setEnabled(false);
16. 15
Select7.setEnabled(false);
Select8.setEnabled(false);
Select9.setEnabled(false);
}
}
void autoPlay() {
//To find empty cells
ArrayList<Integer> EmptyCells = new ArrayList<Integer>();
for (int cellID = 1; cellID < 10; cellID++) {
if (!(Player1.contains(cellID) || Player2.contains(cellID))) {
EmptyCells.add(cellID);
}
}
Random r = new Random();
int RandIndex = r.nextInt(EmptyCells.size());
int CellID = EmptyCells.get(RandIndex);
Button Selected;
switch (CellID) {
case 1:
Selected = (Button) findViewById(R.id.button1);
break;
case 2:
Selected = (Button) findViewById(R.id.button2);
break;
case 3:
Selected = (Button) findViewById(R.id.button3);
break;
case 4:
Selected = (Button) findViewById(R.id.button4);
break;
case 5:
Selected = (Button) findViewById(R.id.button5);
break;
case 6:
Selected = (Button) findViewById(R.id.button6);
break;
case 7:
Selected = (Button) findViewById(R.id.button7);
break;
case 8:
Selected = (Button) findViewById(R.id.button8);
break;
case 9:
Selected = (Button) findViewById(R.id.button9);
break;
default:
Selected = (Button) findViewById(R.id.button1);
break;
}
PlayGame(CellID, Selected);
}
17. 16
public void newGame(View view) {
refreshApp(this);
}
public static void refreshApp(AppCompatActivity appCompatActivity) {
appCompatActivity.recreate();
}
}
❖ Discussion
➢ ActivePlayer variable will indicates if the Player 1 or Player 2 is active. ArrayLists are declared
to store the data of Player 1 and Player 2 i.e. whenever Player 1 or Player 2 selects any of the
empty cells, it will be recorded in Player1 and Player2 ArrayLists.
➢ Method BuClick allows handling of all the buttons that are placed in the cells. So, whenever
buttons are selected, onClick attribute allows calling of the method BuClick Button object named
Selected is created which is handled by view. Therefore, all the buttons from 1 - 9 will be
controlled by view. For e.g. if we click button 1, view will be 1, if button 2, view will be button
2 and so forth.
➢ To uniquely identify the buttons, CellID integer type variable is declared. Therefore, via switch
statements, CellIDs are assigned in numeric ascending order convention with respect to the
particular cases. The test expression for switch statement Selected.getID() will allow to map to
unique ids that are named in xml files for the buttons. Then cases are set to R.id.button(1-9)
inside each of the cases, CellIDs are assigned respectively followed by break statement. Hence,
the buttons selected are well tracked in the program.
➢ method PlayGame will allow the user to play the game. It takes in two parameters - Id of selected
button and the button that is selected. Inside it, if first player is active, setText method is called
on the button object which sets its text attribute to “X”. Then on selected button object,
setBackgroundColor method is called that will allow the background color of the button to
change to green. Then, on Player1 ArrayList object, add method is called to which CellID
variable is passed. So the selection made by first player 1 is stored in Player1 ArrayList. Now,
player 2 is set to active. autoPlay method is called(which makes it look like the computer is
playing).
18. 17
➢ Then check for second player is performed similar to first player except that text is set to “O”,
background color is set to blue and autoPlay method is not called.
➢ setEnabled method is called on Selected button object and is set to false. This is done such that
the buttons that are already selected cannot be selected again.
➢ checkWinner method is called which will decided which player is winner.
➢ Inside method checkWinner, Winner is initialized to an arbitrary value and boolean flag to indicate
game is over is set to false. All of the button objects from 1 - 9 are created in order to enable the
buttons to set false after the game is over. Then series of if statements are implemented to check
the correct rows, columns and diagonals are selected in order to decide which player is the winner
of the game by setting Winner variable to 1 or 2.
➢ if statements are also implemented to display message via Toast constructor. If Winner variable
is set 1, Toast will display message that Player 1 is winner and if Winner variable is set to 1 and
Player 2 is winner if Winner variable is set to 2. So, at each of these if statements, end boolean
flag is set to true.
➢ Now, if statement is implemented in checkWinner method for which test expression is end
boolean parameter. So, when end boolean parameter is set to true, all the button objects on which
setEnabled method is called and is set to false such that no other buttons can be selected after
the game is over.
➢ method autoPlay is created that will make it look like to the user that the computer is playing.
Initially, ArrayList is created to check the empty cells. for loop is implemented that allows to
keep track of empty cells at each iteration. Loop will iterate till 9th iteration. Based on the size
of EmptyCell ArrayList, random integer is called that will range from 1 - 9 and it is assigned to
CellID variable.
➢ Now, via switch statement, random button will be selected. It is very much similar to the switch
statement implemented in BuClick method but it is done in reverse way. In this situation, CellID
is already initialized to a random number and accordingly the buttons will be selected by the
computer.
➢ Then, finally, PlayGame function is called and CellID variable and Selected Button object is
passed to it. So therefore, when autoPlay method will be called in PlayGame method after
ActivePlayer variable is assigned to 2, Player 2 will be the computer that acts based on the code
implementation in autoPlay method.
19. 18
➢ To restart New Game, newGame method is created which is onClick attribute of New Game button
in xml file. refreshApp method is created inside which, AppCompatAcitivity constructor is
passed. Inside refreshApp method, recreate method is called on appCompatAcitivity object.
Now, refreshApp method is called inside newGame to which this keyword is passed to reference
AppCompatAcitivity constructor.
References
Udacity. 2018. Udacity. [ONLINE] Available at: https://classroom.udacity.com/courses/ud834.
[Accessed 15 March 2018].
Udacity. 2018. Udacity. [ONLINE] Available at: https://classroom.udacity.com/courses/ud836.
[Accessed 15 March 2018].
tutorialspoint.com. 2018. Android Tutorial. [ONLINE] Available
at: https://www.tutorialspoint.com/android/index.htm. [Accessed 17 March 2018].