GGC       Java       Processing       IntelliJ       Java Visualizer

1. Chapter 1: Getting Started.

1.1. Programming basics

Computers are programmable machines that process information by manipulating data. As the data can represent any real world information, and programs can be readily changed, computers are capable of solving many kinds of problems.

Programs are created in a programming language by writing a series of instructions into a text file. The files containing the program (source) code are translated into executable applications or software. Most programs are intended to serve as interactive tools for people referred to as users. Users interact with programs in many ways including:

  • Text user interfaces using the keyboard and a console.

  • Graphical user interfaces (GUI) using a keyboard, mouse, monitor, touch screen, …​

  • Audio user interfaces using speakers and/or a microphone.

  • Combinations of all of the above along with emerging technologies like brain wave interfaces, 3D printers, virtual reality headsets, bio implants, …​

1.2. Programming Languages and Environments

There are many different programming languages for programmers to choose from. Each language has its own advantages and disadvantages, and new languages gain popularity while older ones slowly lose ground. In this book, we use the Java programming language. It is popular in both academia and industry.

There are many different environments where a programmer may write and test Java. We will setup a few in this chapter, but use a wide variety throughout the semester.

1.3. Get Processing

Processing is a Java based coding environment for graphics. We use it throughout the semester as a context for real world coding.

Processing Asg 1.1

Processing Example Script
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
size(500, 500);
background(0, 0, 0);

fill(255, 0, 0);
rect(0, 0, 50, 300);

fill(0, 255, 0);
ellipse(250, 250, 250, 100);

fill(0, 0, 255);
triangle(250, 100, 250, 400, 350, 100);

fill(255, 255, 255);
textSize(128);
text("word", 40, 120);

Proc Asg Ex1.1

Assignment Instructions

Play with the example code until you understand what everything does. Then, create your own image that uses at least 5 shapes and 1 phrase.

Turn In Instructions

Always create/save processing projects with the following pattern LastName_Asg_Chap_AsgNum (Ex: Siva_Asg1_1), then under the Tools menu, select Archive Sketch. That should create the .zip file you need to submit to the corresponding assignment dropbox in D2L.

Processing Asg 1.2

Notes:

  • The size is 500,500.

  • The grass is 100 pixels high.

  • The sun is 100 pixels wide.

Proc Asg1.2

Assignment Instructions

Duplicate the adjacent image perfectly and submit it in D2L.

1.4. Get IntelliJ

IntelliJ is a Java Integrated Development Environment. We use it throughout the semester for larger projects.

1.4.1. Install IntelliJ

  • Install IntelliJ: https://www.jetbrains.com/idea/download

  • Make Sure To Get Community (Free) Version

  • Create a new Java project.

    • Make sure to download a SDK if necessary (the default is fine).

    • Make sure to include sample code so you can run it to test.

IntelliJ Example

1.4.2. Configure IntelliJ

IntelliJ has a lot of fancy features. Several of them make reading code more difficult for beginners. Disable them by either:

  • Download Settings File and import them via the File | Manage IDE Settings | Import Settings menu …​

  • or disable them manually by following these instructions.

    • Open Preferences

    • Search for "Inlay Hints" and disable them all.

IntelliJ_Inlay
  • Search for "Smart Step" and disable Always do smart step into.

IntelliJ_SmartStep

2. Chapter 2: Data Types, Variables, and Expressions.

2.1. Data Types and Values

Programming is about processing data. Data is organized into different types. There are an endless number of data types in Java. In fact, many programmers spend most of their time coming up with new ones. Still, most Java coding is built on top of the basic data types below.

Table 1. Basic Data Types
Data Type Example Values

int

2, -2, 0, 834529

double

2.0, -2.235, 0.0, 8329.123782

boolean

true, false

char

'a', '!', '9', '+'

String

"Hello World!", "30043", "12 - 5"

Primitive versus Non-Primitive Data Types

int, double, boolean, and char are all primitive data types. There are several others which advanced programmers can choose to more efficiently use memory. Non-primitive types (also called Classes) are built out of combinations of primitive data.

Characters, Strings, and Quotes

In order to distinguish them from other things, chars and strings are always surrounded by single and double quotes respectively.

You should now be able to look at any line of Java code and identify all of its data values and their corresponding data type. Anything that is not a value, is something else that you will learn later.

2.2. Variables

Variables are (virtual) boxes that store values for reuse later. A variable has a name and a current value. Each variable can only hold one value at a time. Variables are created by specifying a data type and a name. They are assigned a value using the single equal sign (=). As Java executes one line at a time, variables come into existence on the line where they are first assigned.

CopyMe Asg 2.1

Variable Creation

Use the "Forward" button to check the process of each step. Only pay attention to the lines highlighted in yellow. The variable boxes will appear on the right hand side.

Comments

The // indicates a comment in the code. All text after the // is ignored by Java, allowing us as programmers to add descriptive comments to the code, or hide the code from Java.

Assignment Instructions

Figure out the variable names and corresponding values in the program above. Go do CopyMe Asg 2.1 in D2L.

2.3. Operations and Expressions

Processing data is all about operations (like +). Each type of data has its own set of relevant operations. Operations usually act on 2 values and return a value (Ex: 2 + 3 returns 5). As such, they can be chained into larger expressions (Ex: 3 * (2 + 6)). Although there is an order to operation processing (* happens before +), it is always best to explicitly specify the intended order using parenthese. Java always processes the deepest parentheses first.

Syntax for Values and Expressions

In Java, anywhere you can write a value, you can legally write an expression that returns the same type of data. For example, if it is legal to write int x = 15, then it must be legal to write int x = 100 * (10 - 5).

2.3.1. Numeric Operations

Both ints and double allow the same set of standard operations: +, -, *, /. If both sides of the operator are ints, the return value type is int. If at least one side is a double, the return value is a double.

Division

Dividing ints gives an int with any decimal places stripped off.(Ex: 5/2 returns 2). If there is at least one double, the return type is a double. (Ex: 5/2.0 returns 2.5)

The remainder operator (%) is mainly used with ints and returns the remainder of the integer based division (Ex: 14 % 5 returns 4 because 14 divided by 5 is 2 with a remainder of 4).

2.3.2. Comparison Operators

The comparison operators return boolean values. They can compare 2 numbers (ints or double) and characters.

Table 2. Comparison Operators

>

Greater Than

>=

Greater Than or Equal

<

Less Than

<=

Less Than or Equal

==

Equals

!=

Not Equals

Equality vs. Storage
Checking if two values are identical (==) is unrelated to storing a value in a variable (=).

2.3.3. Boolean Operations

Just like ints have numeric operators (+ - * /), booleans have their own operators (&& || !).

Boolean Operator: and
true && false

The and operator takes 2 boolean inputs and returns true only when both sides are true, false otherwise.

Boolean Operator: or
false || true

The or operator takes 2 boolean inputs and returns true when at least 1 side is true, false otherwise.

Boolean Operator: not
! true

The not operator takes 1 boolean input and returns the opposite (negated) boolean.

Boolean Equality

We can also use == and != with booleans (Ex: true != false returns true).

CopyMe Asg 2.2

Expressions

Can you predict the value for each variable?

Assignment Instructions

Figure out the variable names and corresponding values in the program above. Go do the CopyMe Asg in D2L.

Processing Asg 2.1

Processing Script
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
size(500, 500);
background(0, 0, 0);
int canvas_size = 500;
int center = 0; // Expression for 50% the canvas_size
int red1 = 0; // Expression for 90% of the canvas_size
int black1 = 0; // Expression for 100 less than red1
int red2 = 0; // Expression for 100 less than black1
int black2 = 0; // Expression for 100 less than red2
int red3 = 0; // Expression for 100 less than black2

fill(255, 0, 0);
circle(center, center, red1);
fill(0, 0, 0);
circle(center, center, black1);
fill(255, 0, 0);
circle(center, center, red2);
fill(0, 0, 0);
circle(center, center, black2);
fill(255, 0, 0);
circle(center, center, red3);

Assignment Instructions

Replace the 0s with the code described by the comments. When done, your picture should match the target picture perfectly. Make sure to make Java do the math using the correct expressions. Don’t just do the math on yourself and type in the result.

Hint: (9 / 10) returns 0 in Java.

Proc Asg2.1

2.3.4. String Operations

Indexes

Strings in Java can vary in length from 0 characters to millions of characters (limited only by the computer’s memory). As such, we often need to break down strings into shorter fragments or individual characters in order to process them. String processing starts with the concept that each character in a string has a unique index which represents its position in the string. Indexes start with the first chracter at position 0, and end with the last character at position length - 1. The indexes for the string "Hi There" are below. Note that the string is of length 8, and thus has indexes from 0 to 7.

Table 3. Indexes

String Characters:

H

i

T

h

e

r

e

Indexes:

0

1

2

3

4

5

6

7

DotMethods

Although we can use + with strings, for the most part, we use dot methods. We will discuss methods in more detail in the next chapter, but for now you need to know the following list of string dot methods:

  • .length()

  • .charAt(int index)

  • .substring(int begin_index, int end_index)

  • .indexOf(String substring)

  • .equals(String other)

CopyMe Asg 2.3

String expressions

Can you predict the value for each variable?

Assignment Instructions

Figure out the variable names and corresponding values in the program above. Go do the CopyMe Asg in D2L.

Plus Strings

When adding to strings all other data types are first converted to a string.

String Equality

Never use == with strings. Use .equals() instead.

String indexOf()

This method tries to find the starting index of a substring. If it fails it returns -1.

2.4. Varying Variables

Variables can be modified using the = sign. Variables can only hold 1 value. The previous value is lost. Do not specify the data type when modifying a variable. Specifying a data type attempts to create a new variable.

CopyMe Asg 2.4

Modifying Variables

Can you predict the value for each variable at each line of code?

Assignment Instructions

Figure out the variable names and corresponding values in the program above at each line of code. Go do the CopyMe Asg in D2L.

The += Operator

The += operator is a short hand for adding to a variable. Thus, x += 3 is identical to x = x + 3.

Processing Asg 2.2

Processing Script
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
size(500, 500);
background(0, 0, 0);
int r = 0;
int g = 64;
int b = 0;

int x = 130;
int y = 300;
int w = 30;
int h = 50;

fill(r, g, b);
rect(x, y, w, h);

//Section 1: Modify 4 variables
fill(r, g, b);
rect(x, y, w, h);

//Copy/paste the 4 formulas from Section 1
fill(r, g, b);
rect(x, y, w, h);

//Copy/paste the 4 formulas from Section 1
fill(r, g, b);
rect(x, y, w, h);


Assignment Instructions

Fill out Section 1 in the code with formulas to modify 4 variables. Copy/paste those formulas into the 2 sections below. The code should produce an image identical to the one on the right.

Notes:

  • Each bar has 64 more shades of green.

  • The gap between the bars is the same as the width.

  • Each bar is 50 pixels taller than the previous bar.

Proc Asg2.2

3. Chapter 3: Methods

3.1. Calling Methods

In chapter 1 we used methods from Processing like size(), fill(), and rect(). In Chapter 2, we introduced dot methods for strings like .length() and .substring(). Calling methods tells Java to perform tasks with specific parameter values.

For example, consider the call to the rect() method below.

Example call to rect() method
rect(100, 200, 300, 50)

Calling the rect() method requires that we specify the name of the method followed by parentheses containing 4 integer parameters representing the x, y, width, height of our rectangle. That tells Java to go execute the code necessary to draw a rectangle.

3.2. Defining New Methods

Before a method can be called, it must be defined. Most methods we have used this semester have been pre-defined for you by other programmers. Here, we introduce how to define your own custom methods. Once defined, you and other programmers will be able to use them like any other method. Thus, by defining your own methods, you are adding new functionality to Java. The fundamental approach to solving large programming problems is breaking them down into small method definitions, and then calling those methods to solve the original complex problem.

Consider the Processing example below:

Example method definition and 2 calls.
void pacman(int x, int y) { (1)
  fill(255, 255, 0);
  circle(x, y, 50);
  fill(0, 0, 0);
  triangle(x, y, x + 25, y - 25, x + 25, y + 25);
} (2)

pacman(50, 200); (3)
pacman(300, 300); (4)
1 The first line is called the method signature and has multiple parts:
  • void - this method will not return a value (we cover return values later)

  • pacman - the method’s name.

  • (int x, int y) - this method has 2 integer parameter variables called x and y.

  • { - starts the block the method will execute when called.

2 } - ends the block the method will execute when called.
3 Example of calling the pacman method and setting x, y to 50, 200 respectively.
4 Example of calling the pacman method and setting x, y to 300, 300 respectively.

Processing Ex 3.1

Drawing 2 PacMans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void pacman(int x, int y) {
  fill(255, 255, 0);
  circle(x, y, 50);
  fill(0, 0, 0);
  triangle(x, y, x + 25, y - 25,
  	x + 25, y + 25);
}

void setup() { (1)
  size(500, 500);
  background(0, 0, 0);

  pacman(50, 200);
  pacman(300, 300);
}

1 Note: For now on almost all code will go inside a method definition. Processing will always start by calling the setup() method automatically, so we put our size(), background() and other code here.

Proc Example3.1

Processing Asg 3.1

Drawing Ghosts
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
size(500, 500);
background(0, 0, 0);

int x = 250;
int y = 250;
fill(0, 0, 255);
rect(x - 25, y - 30, 50, 60);
fill(255, 255, 255);
circle(x - 10, y - 20, 10);
circle(x + 10, y - 20, 10);
fill(0, 0, 0);
rect(x - 15, y + 20, 10, 10);
rect(x + 5, y + 20, 10, 10);

Proc Asg3.1

Assignment Instructions

The code above draws one ghost in the center of the canvas (try it out). Modify the code so that it defines 2 methods, ghost() and setup(), similar to example 3.1 above. Then, from inside setup()`s block, call the ghost() method 3 times so a ghost appears in 3 locations: (100, 100), (400, 100), and (100, 400). When done, your image should match the one here.

3.3. public, static, class, and main

In this book we use some examples (like Processing) that are technically not 100% Java. These examples circumvent some of the complex syntax that a pure Java program requires. In other examples (like Java Visualizer) we stick with pure Java. In pure Java, programmers are required to organize and annotate their code with keywords that prevent other programmers from misusing code. These keywords are class, public, and static. For now, when you see one, just copy it and move on. Below are some very rough descriptions in the context of methods in case you are curious.

  • class: a collection of methods.

  • public: anyone can execute this method.

  • static: this method can only acces certain kinds of data.

  • main(): this is the start method for Java (similar to setup() in Processing). Java always automatically executes the main method when it starts.

We will learn the full meaning of these keywords later.

CopyMe Asg 3.1

Modifying Variables

Can you predict the value for each variable at each line of code?

Assignment Instructions

Figure out the variable names and corresponding values in the program above at each line of code. Note, each method has its own set of variables. Go do the CopyMe Asg in D2L.

3.4. Variables, Blocks, and Scope

When variables are created they are automatically assigned a block (chunk of code between {}) where they exist. Any attempt to use that variable outside of its block will fail. We call that block, the variable’s scope.

Example of variable scope.
{ (1)
	int w = 10;
	{ (2)
		int x = w + 1;

	} (3)

	{ (4)
		int y = w + 2;
		int z = y * 3;

	} (5)
} (6)
1 The start of block 1, the outer most block. w belongs to this block and can be used anywhere inside of it.
2 The start of the a block 2, a block inside block 1. x belongs to this block and can be used anywhere inside of it. w can also be used here because we are still inside block 1.
3 The end of block 2. x is no longer visible after this.
4 The start of the a block 3, another block inside block 1. y and z belong to this block and can be used anywhere inside of it. w can also be used here because we are still inside block 1.
5 The end of block 3. y and z are no longer visible.
6 The end of block 1. w is no longer visible after this.
Parameter Variables

A method’s parameter variables belong to the method’s block even though they are created just before the block’s {.

3.5. Processing, setup(), and draw().

Earlier we introduced Processing’s setup() method, which is called automatically when Processing starts. Here we introduce the draw() method, which is called after setup() and repeated every 60 seconds enabling animations!

Processing Ex 3.2

Animating a Box
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
int box_x = 0; (1)

void setup(){ (2)
  size(500, 500);
}

void draw(){ (3)
   // reset the canvas
  background(0, 0, 0);
  rect(box_x, 200, 50, 100);
  box_x += 1;
}

1 variables created here can be used by either setup() or draw() and retain their value between draw() calls.
2 setup() is automatically called by Processing before the first draw()
3 draw() is automatically called by Processing 60 times per second (once per frame)

Processing Asg 3.2

Assignment Instructions

Duplicate the animation in the video on the right. Combine the techniques from Processing Examples 3.1 and 3.2. When done correctly, your code should have 3 methods; pacman(), setup(), and draw().

Note: PacMan starts at (0, 0) and moves 1 pixel across and down per frame.

3.6. Return Values

Up until now, every method definition we have seen has used the void keyword to declare that the method did not return a value. Now we demonstrate using a data type instead of void to setup return values.

CopyMe Asg 3.2

Returning Values

Can you predict the value for each variable at each line of code?

Assignment Instructions

Figure out the variable names and corresponding values in the program above at each line of code. Go do the CopyMe Asg in D2L.

Return Extis A Method

No code inside a method will be executed after a return statement. Return immediately exits a method. Even if a method has no return value (void), the return statement can be used to exit the method.

4. Chapter Four: Conditions

4.1. Making Decisions

Computers make decisions that give the illusion of "thinking". For example, a digital thermostat turns on or off the heater depending on the current temperature in the room. IBM’s Big Blue computer decides what chess piece to move next when beating world chess champions. Google’s self-driving car decides when to apply the brakes depending on what is in front of it. All computer decisions are based on conditions built out of a simple logic called Boolean logic.

4.2. If Statements

Boolean logic allows a program to make a decision based on a condition. The if statement executes specific lines of code only when the condition is true. If the condition is false, the lines are skipped. The lines of code to be executed are grouped into a block using {}.

CopyMe Asg 4.1

If Statements

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Processing Ex 4.1

If statement and the mouse
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
void setup(){
  size(500, 500);
}

void draw(){
  background(0, 0, 0);

  fill(0, 255, 0);
  rect(mouseX, 0, 10, 500); (1)

  if (mousePressed) { (2)
	fill(0, 0, 255);
    rect(0, mouseY, 500, 10); (3)
  }
}
1 Variable int mouseX is automatically created by Processing. It is the x coordinates of the mouse pointer.
2 Variable boolean mousePressed is automatically created by Processing. It is true when a mouse button is pressed.
3 Variable int mouseY is automatically created by Processing. It is the y coordinates of the mouse pointer.

Copy/Paste the code and test it yourself.

Processing Asg 4.1

Assignment Instructions

Duplicate the functionality in the video.

  • Put the background() method call in setup() so canvas is not reset.

  • Requires 1 if statement so circles only show up when mouse button is pressed.

  • Requires mouseX, mouseY, and mousePressed.

  • Circles have diameter 50.

4.3. If, Else

As we learned above, if statements will either execute or skip 1 block of code depending on the condition. In some situations, we want to choose between 2 blocks of code depending on the condition. This can be done with the if …​else…​ statement.

CopyMe Asg 4.2

If Else Statements

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Processing Ex 4.2

If Else statement
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

void setup(){
  size(500, 500);
}

void draw(){
  if(mouseX >= 250) {
    background(0, 0, 255);
  } else {
    background(0, 255, 0);
  }
}

Watch the background change color as the mouse moves around.

Processing Asg 4.2

Assignment Instructions

Duplicate the functionality in the video. The box should highlight yellow when the mouse is over it. It should return to grey as soon as the mouse moves off. Use 1 if else statement.

  • Colors Used:

    • (0, 0, 0)

    • (255, 255, 0)

    • (200, 200, 200)

    • (255, 255, 255)

  • The box is drawn with:

rect(100, 200, 300, 100);

  • The text is size 100 and drawn with:

text("Button", 105, 290);

4.4. Else If

As we learned above, if else statements will execute 1 block out of 2 options, the if block or the else block. What if we want to force Java to choose 1 block out of 3 or more options? The answer is the _else if block.

CopyMe Asg 4.3

Else If Statements

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Processing Asg 4.3

Assignment Instructions

Duplicate the functionality in the video by completing the code below using else if statements. The background color should remain the default (grey) until the user clicks a colored square. Clicking anywhere else should do nothing.

Use Else If
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

void setup(){
  size(500, 500);
}

void draw(){
  fill(255, 0, 0);
  rect(0, 0, 50, 50);
  fill(0, 255, 0);
  rect(0, 50, 50, 50);
  fill(0, 0, 255);
  rect(0, 100, 50, 50);

}

4.5. While

As we learned above, the if statement allows us to execute a code block one time if a condition is true. The while statement, on the other hand, allows us to execute a code block repeatedly while a condition is true. This allows our code to loop potentially infinite times. To prevent infinite looping, the code block typically modifies the variable used in the condition. For example, the value of x is increased with every loop in the code snippet below.

While Statement
int x = 1;
while (x < 5) {
	x += 1;
}

CopyMe Asg 4.4

While Statements

Can you predict where the yellow line will go?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Break!

Although it is not used in the example above, the break statement immediately exits a loop (as opposed to allowing it to run until the while condition is false).

int x = 1;
while (x < 5) {
	x += 1;
	if (x % 2 == 0) {
		break;
	}
}

Processing Asg 4.4

Assignment Instructions

Duplicate the image by completing the code. Follow the instructions in the comment precisely.

Proc Asg4.4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void setup(){
  size(400, 400);
  background(0, 0, 0);
}

void draw(){
  fill(255, 255, 255);

  // Instead of calling drawRow() twice,
  // use a while loop to call it 8 times.
  // Each time the y value should go up by 50
  // and the boolean should flip
  drawRow(0, false);
  drawRow(50, true);
}

void drawRow(int y, boolean blackStart){
  int x = 0;
  if (blackStart) {
    x += 50;
  }

  while (x <= 350) {
    rect(x, y, 50, 50);
    x += 100;
  }
}

5. Chapter Five: Arrays

Arrays are collections of values combined into a single entity. They enable a single variable to store multiple values, like a cubbyhole holding different items in each space.

5.1. Indexes

The indexes of each value in an array are identical to the indexes for each character in a string. They start with the first value at position 0 and end with the last value at position length - 1. The indexes for the array ["Apple", "Plum", "Kiwi"] are below. Note that the array is of length 3 and thus has indexes from 0 to 2.

Array Values:

"Apple"

"Plum"

"Kiwi"

Indexes:

0

1

2

CopyMe Asg 5.1

Default values

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Default Values

Arrays of primitive types like int and double have the default value of zero. Arrays of non-primitive types like String have the default value of null which means no value. This is different than the empty string "".

Array Length

Each array has its own length property accessible via the .length variable.

5.2. Loops

In many situations, we want to access every value of an array one at a time. This is accomplished by using each index from 0..length - 1 in a loop.

CopyMe Asg 5.2

Running Total

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

Processing Asg 5.1

Assignment Instructions

Duplicate the image by completing the code. Follow the instructions in the comment precisely.

Proc Asg5.1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void setup(){
  size(500, 500);
}

void draw(){
  background(0, 0, 0);
  int[] ys = new int[]{0, 50, 100, 150};
  String[] labels = new String[]{
    "Resume", "Save", "Load", "Quit"
  };

  // Loop the code below to draw all 4 buttons.
  drawYellowButton(0, ys[0], labels[0]);
}

void drawYellowButton(int x, int y, String label) {
  fill(255, 255, 0);
  rect(x, y, 100, 50);
  fill(0, 0, 0);
  textAlign(CENTER, CENTER);
  textSize(20);
  text(label, 50, 25 + y);
}

5.3. Counting

Computers are extremely fast at looping through arrays and searching for values that match criteria. They can process billions of values per second!

CopyMe Asg 5.3

Counting

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

5.4. For Loops and Break

While loops that follow the standard template below can be reduced to for loops.

Standard While Loop
int i = 0; (1)
while (i < 5) { (2)
	// do stuff repeatedly (3)
	i += 1; (4)
}
1 Init a variable for tracking the loop
2 Test if the loop should continue
3 The stuff that needs to be repeated
4 Modify the variable tracking the loop
Standard For Loop
for(int i = 0; i < 5; i++) {  (1) (2) (4)
	// do stuff repeatedly (3)
}
1 Init a variable for tracking the loop
2 Test if the loop should continue
3 The stuff that needs to be repeated
4 Modify the variable tracking the loop
Increment Operator ++

When you want to add 1 you can use ++ instead of += 1 .

CopyMe Asg 5.4

For Loops and Break

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

break

The break statement immediately exits a loop.

6. Chapter Six: The Console and …​

In this chapter we fill in some gaps we skipped in previous chapters that allow us to condense code and interact with a console (a.k.a. termina/shell/command line).

6.1. Type Conversion

So far we have introduced int, doubles, boolean, characters, and Strings. Here we demonstrate how to convert from one to the other with casting for primitives and other methods for Strings.

Example of casting.
int a = ((int) 3.5); (1)
1 The cast operation uses parentheses to treat a value as a different type.

CopyMe Asg 6.1

Data Type Conversion

Can you predict the value for each variable at each line of code?

Assignment Instructions

Go do the CopyMe Asg in D2L.

6.2. The Console

A console, also known as a shell or terminal, is a user interface which allows programs to interact with humans through text. Unlike graphical user interfaces, a console does not allow for images, sound, video, or even mouse input.

There are a variety of methods which allow us to display (print) text to the console and read (input) data from the console.

CopyMe Asg 6.2

The Console

Can you predict the program output.

Assignment Instructions

Go do the CopyMe Asg in D2L.

print() vs. println()

The only difference between System.out.println() and System.out.print() is whether or not a new line is appended at the end of the string. So if you call print("Dog"); print("Dog"); print("Dog"); you get DogDogDog all on the same line. Otherwise, with println("Dog"); println("Dog"); println("Dog"); you would get Dog on 3 separate lines.

6.3. Procedural Programming

At this point, we have learned how to solve small problems (roughly less than 10 lines of code). How do we solve large problems? There are a variety of strategies to divide and conquer large problems in programming including Object Oriented, Procedural, and Functional programming. Although Java is designed for Object Oriented programming, we choose to first explore procedural programming as it was historically the earliest and easiest approach. A procedure is another word for function or method, and in Java, is typically created with the public static keywords. We have been defining these since chapter 3. The goal is to divide the large problem into smaller methods, implement those methods, and then call them in a combination that solves the original problem.

The following exercise (to be completed by you) demonstrates the procedural approach to programming.

Kirby and Friends Play Through
Kirby and Friends Project
import java.util.Scanner;

public class Main {

    /**
     * @param a     an array of strings
     * @return      a random string from the array
     * Ex: getRandomString(new String[]{"am", "be", "ok"}) -> "be"
     */
    public static String getRandomString(String[] a) {
        return "";
    }

    /**
     * @param s         a string
     * @param percent   a percentage between 0.0 and 1.0
     * @return          percentage of a string
     * Ex: getPercentString("hello", 0.4) -> "he"
     */
    public static String getPercentString(String s, double percent){
        return "";
    }

    /**
     * @param s     a string
     * @return      the number of underscores ('_') in the string
     * Ex: countUnderScores("s_m__e") -> 3
     */
    public static int countUnderScores(String s) {
        return 0;
    }

    /**
     * @param answer            string with correct answer and no blanks
     * @param guessedLetters    string with letters guessed so far
     * @return                  string with underscores for letters not yet guessed
     * Ex: getAnsWithBlanks("sample", "mes") -> "s_m__e"
     */
    public static String getAnsWithBlanks(String answer, String guessedLetters){
        return "";
    }

    /**
     * Prompts the user (via standard input) to guess a letter.
     * Repeats the question as long as the user's reply is not length 1.
     * @return the string of length 1 containing the user's guess
     * Example assuming user enters 'Bob', then 'e':
     * getUserGuess() -> "e"
     */
    public static String getUserGuess(){
        return "";
    }

    /**
     * Plays the entire game assuming the methods above are correctly implemented.
     */
    public static void playKirbyFriends() {
        String[] all_friends = new String[] {"mario", "zelda", "kong", "fox", "mac"};
        String secret = getRandomString(all_friends);
        String kirby = "<(˶ᵔᵕᵔ˶)>";
        String guessedLetters = "";
        String answerBlanks = getAnsWithBlanks(secret, guessedLetters);
        double correctPercent = 0.0;

        for(int numTurns = 1; numTurns <= 10; numTurns++) {
            System.out.println("ANSWER:\t" + answerBlanks);
            if(correctPercent >= 1.0) {
                break;
            }
            System.out.println("TURN:\t" + numTurns + " out of 10");
            String g = getUserGuess();
            System.out.println();

            guessedLetters += g;
            answerBlanks = getAnsWithBlanks(secret, guessedLetters);
            correctPercent = (secret.length() - countUnderScores(answerBlanks)) /
                    ((double) secret.length());
            System.out.println("TRIES:\t" + guessedLetters);
            System.out.println("KIRBY:\t" + getPercentString(kirby, correctPercent));
        }

        System.out.println();
        if(correctPercent < 1.0) {
            System.out.println("GAME OVER");
        } else {
            System.out.println(kirby + " Hiii " + secret + "!");
            System.out.println("YOU WIN!");
        }
    }

    public static void main(String[] args) {
        playKirbyFriends();
    }
}
MultiLine Comments

When you want to comment multiple lines in a row, start with a /* and end with a */.

Javadoc

The @param and @return commenting syntax is the standard way by which we describe a method’s parameters and return value.

Notice how the final method, playKirbyFriends(), is mostly variable creation and prints to the user. In fact, without those, the logic is short and sweet.

Procedural Programming
public static void playKirbyFriends() {
	String secret = getRandomString(all_friends); (1)
	String answerBlanks = getAnsWithBlanks(secret, guessedLetters); (4)

	for(int numTurns = 1; numTurns <= 10; numTurns++) {
		if(correctPercent >= 1.0) {
			break;
		}
		String g = getUserGuess(); (5)

		guessedLetters += g;
		answerBlanks = getAnsWithBlanks(secret, guessedLetters); (4)
		correctPercent = (secret.length() - countUnderScores(answerBlanks)) /
				((double) secret.length()); (3)
		System.out.println("KIRBY:\t" + getPercentString(kirby, correctPercent)); (2)
	}
}
1 Call to getRandomString()
2 Call to getPercentString()
3 Call to countUnderScores()
4 Call to getAnsWithBlanks()
5 Call to getUserGuess()

Thus a complex problem, when broken down into simpler pieces, can have a straightforward solution. This is also known as problem decomposition. In the next chapter, we dive into Object Oriented Programming, the problem decomposition technique Java was designed for!

7. Chapter Seven: Object Oriented Programming

Object Oriented Programming (OOP) stems from the idea that we can create new complex data types, complete with their own operations, from existing data types. This turns out to be a superior strategy for large problems than procedural programming, and as such is now industry standard.

7.1. Data Types Review

Let us review the main data types and corresponding operations we have learned so far.

Table 4. Data Types and Operations
Data Type Example Value Operations

int

2

+ - * / % < > != == ...

double

2.0

+ - * / < > ...

boolean

true

&& || !

char

's'

== !=

String

"Dog"

+ .length() .charAt() .substring() .indexOf() .equals()

You will immediately notice several irregularities with the String data type:

  • String has a capitalized S.

  • A string is a combination of a simpler data types (chars).

  • String operations (besides +) are dot methods. They have a name with parentheses and parameters.

This is all due to the fact that Strings are not primitive data types.

7.2. Classes and Objects

Primitive data types, like int or boolean, are never capitalized and can only be manipulated with operators, like + or &&. Non-primitive types, like String, are called classes. They should always be capitalized and can use dot methods like .substring(). Furthermore, they can be much more sophisticated, containing complex combinations of other data types.

To defina a new data type in Jave, we use the keyword class (like class of car). Once this new data type is created, we can create values of that type. We call those values objects or instances.

Table 5. Primitive Types / Classes and Values / Objects
Primitive Type Example Value

int

2

boolean

true

Class (non-primitive type)

Example Object (value)

String

"Dog"

Date

3/14/2023

Terminology

Instead of saying "Dog is a value of type String.",
We should say "Dog is an object of class String."

The meaning is identical, but we keep it classy!

7.3. Defining a New Class

Every data type has 4 essential pieces:

  • The Name

  • The Data - Fields or Instance Variables

  • How to Initialize it - Constructor

  • The Operations / Functionality - Instance Methods

Date Example
class Date { (1)
    int month; (2)
    int day; (2)
    int year; (2)

    Date(String s) { (3)
        this.month = Integer.parseInt(s.substring(0, 2));
        this.day = Integer.parseInt(s.substring(3, 5));
        this.year = Integer.parseInt(s.substring(6, 10));
    }

    boolean laterThan(Date other) { (4)
        if (this.year > other.year){
            return true;
        }
		// COMPLETE THIS AS AN EXERCISE
		return false;
    }
}
1 The class name.
2 The fields that the class is composed of.
3 The constructor (always same name as the class) initializes fields.
4 An instance method (there are usually several of these).
This

The this keyword references the current object. Thus, if we are working with 3/14/2023, this.month refers to 3. If we are working with 5/4/2023, this.month refers to 5.

7.4. Using a Class

There is no point in creating a new data type if we don’t then create values of that type. Values of a class are called objects and are instantiated with the new keyword.

Date Example
public class Main {
    public static void main(String[] args) {
        Date a = new Date("03/14/2023"); (1)
        Date b = new Date("05/04/2023"); (2)
        boolean c = b.laterThan(a); (3)
    }
}
1 An object of class Date.
2 Another object of class Date.
3 Calling an instance method on object b.
main method

The main method could theoretically be in any class including Date. In fact, each class can have it’s own main method just for testing purposes.

7.5. Instance Methods

Instance methods can of course call other instance methods on the same instance / object. Use the this keyword to explicitly call instance methods using the same object. For example, since 2 dates must be either earlier, later, or equal to each other, we could implement the logic for earlier than by checking that it is not later than nor equal to another date.

Earlier Than Example
class Date {

	//COMPLETE AS AN EXERCISE

	boolean earlierThan(Date other) {
		return (!this.equals(other)) && (!this.laterThan(other)); (1)
	}
}
1 Note how we use this to call other methods on the same object. Of course, we need to correctly implemented .laterThan() and .equals() methods first.

7.6. Classes in Processing

Of course, classes are a very useful way to organize processing code. Take a look at the exercise below.

Processing Asg 7.1

Assignment Instructions

Duplicate the functionality in the video by defining a Button class.

Notes From Video:

  • Buttons are usually light grey (200, 200, 200)

  • Buttons highlight grey (125, 125, 125) when the mouse moves over.

  • Buttons become dark grey (75, 75, 75) when the mouse moves over and is pressed down.

  • Button labels are black (0, 0, 0) size 20 text in the center of the button.

Button Class Tester
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Button a; (1)
Button b; (1)
int score;
void setup() {
  size(500, 500);
  a = new Button(10, 10, 200, 50, "1 Point per Click"); (2)
  b = new Button(10, 70, 200, 50, "60 Points per Second!"); (2)
  score = 0;
}

void draw() {
  background(0, 0, 0);
  a.update(); (3)
  b.update(); (3)
  if(a.submitted()) { (4)
      score++;
  }
  if(b.heldDown()) { (5)
      score++;
  }

  fill(255, 255, 255);
  textSize(50);
  textAlign(CENTER, CENTER);
  text("Score: " + score, 255, 255);
}
1 Create a class called Button so these variables work.
2 The constructor takes 4 ints (like Rect()) and a string for the label.
3 Button has an instance method called update() which the tester calls every frame.
4 Button has an instance method called submitted() which returns true the frame in which the button was pressed.
5 Button has an instance method called heldDown() which returns true every frame the button is currently down.

Button Class Details:

  • The Button class needs 7 fields:

    • leftX, topY, widthX, and heightY are initialized directly from constructor parameters and will be used to draw the rectangle in update().

    • label is initialized directly from the constructor parameter and will be used to draw the button label in update().

    • hasMouseOver is a boolean that is initialized by the constructor to false. The update() method will set it to true only if the mouse is currently over the button.

    • downFrameCount is an integer initialized by the constructor to 0. It get’s incremented by update() every frame the button is held down by the mouse, but goes back to zero if the mouse is not currently holding down the button.

  • The Button class 3 instance methods:

    • update() does not return a value. It will modify the hasMouseOver and downFrameCount fields. It will also draw the rectangle (with correct color) and black label.

    • heldDown() returns true when the downFrameCount is greater than zero.

    • submitted() returns true when the downFrameCount is exactly 1.

7.7. The toString() Method

Anytime Java wants to convert any object into a String, it calls the toString() instance method. If your class does not have one, it uses a default version which tells us very little. Take a look at the example below:

toString() Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Point {
    double x;
    double y;

    Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public String toString() { (1)
        return "Point: (" + this.x + ", " + this.y + ")"; (2)
    }
}
1 The toString() method must always have this exact signature (including public).
2 Build and return a String that describes the object.
Use of toString()
1
2
3
4
5
6
7
8
9
public class Main {
    public static void main(String[] args) {
        Point a = new Point(3.5, 7);
        Point b = new Point(-1, 3.14);
        System.out.println(a.toString()); (1)
        String s = "Boat at " + b.toString(); (2)
        System.out.println(s);
    }
}
1 The println() method needs a String so we use .toString() to convert the Object into a String.
2 The + operator needs a String so we use .toString().
Console Output
Point: (3.5, 7.0)
Boat at Point: (-1.0, 3.14)

IntelliJ Asg 7.1

Assignment Instructions

Create a Point class with all the instance methods necessary to make the tester below work correctly. The Point class will have only 2 fields, x and y, both of type double.

Point Class Tester
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Main {
  public static void main(String[] args) {
    Point a = new Point(3.5, 7); (1)
    Point b = new Point(-1, 1); (1)
    Point c = a.add(b); (2)
    Point d = a.sub(b); (2)
    Point e = a.mult(2.0); (3)
    Point f = b.div(2.0); (3)
    int g = a.getXInt(); (4)
    int h = f.getYInt(); (4)
    double i = b.mag(); (5)
    boolean j = a.notZero(); (6)

    System.out.println("a is " + a.toString() + (7)
      "\nb is " + b.toString() + (8)
      "\nc is " + c.toString() +
      "\nd is " + d.toString() +
      "\ne is " + e.toString() +
      "\nf is " + f.toString() +
      "\ng is " + g +
      "\nh is " + h +
      "\ni is " + i +
      "\nj is " + j);
  }
}
1 Constructor takes 2 doubles.
2 All arithmetic instance methods return new Points.
3 The mult() and div() methods take doubles as parameters.
4 Remember casting.
5 The magnitude of a point is calculated as Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2))
6 true unless both x and y are zero.
7 Point needs a toString() method for this to work.
8 Remember '\n' is the newline character.
Console Output
a is Point: (3.5, 7.0)
b is Point: (-1.0, 1.0)
c is Point: (2.5, 8.0)
d is Point: (4.5, 6.0)
e is Point: (7.0, 14.0)
f is Point: (-0.5, 0.5)
g is 3
h is 0
i is 1.4142135623730951
j is true

7.8. Object Composition

The fields of a class can be other classes. As an example, the Date class from section 7.3 was made out of 3 int values representing month, day, and year, but we might create a Student class out of 2 objects, String and Date, representing name and birthday. The technique of using objects to build more complex objects is called object composition.

Processing Asg 7.2

Note: This assignment depends on the Point class code created previously. Copy it into a separate processing tab.

Instructions Part 1

Create a Ball class so that the test code makes the picture shown.

The Ball class should have:

  • 2 fields:

    • Point pos - represents the current position of the ball.

    • int radius - represents the half the diameter of the ball.

  • A constructor that takes 3 int parameters x, y, and r. Use these parameters to initialize the 2 fields.

  • An update method that uses the circle() method to draw the circle in the correct location.

    • The circle should be drawn without changing the fill() color.

    • The circle() method takes 3 integers representing the center and the diameter of the circle.

Ball Test 1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Ball a;
Ball b;

void setup() {
  size(500, 200);
  a = new Ball(100, 100, 20);
  b = new Ball(400, 100, 100);
}

void draw() {
  background(0, 0, 0);

  fill(0, 255, 0);
  a.update();

  fill(0, 0, 255);
  b.update();
}

Proc Ball1

Instructions Part 2

Modify the Ball class to give the ball velocity so that the test code makes the animation shown.

New field called vel:

  • vel is of type Point

  • vel is initialed by the constructor to new Point(0, 0)

  • setVelocity() is a new instance method which updates vel to a new Point(). It takes 2 doubles to create the new Point().

  • update() method needs be altered to change the Ball’s position:

    • If vel is not zero, update pos by adding the vel and pos together. Use the Point instance methods to do this.

    • Draw the circle after modifying the position.

Ball Test 2
1
2
3
4
5
6
7
8
...

void setup() {
  ...
  a.setVelocity(0.5, 0);
}

...
Instructions Part 3

Modify the Ball class to give the ball gravity so that the test code makes the animation shown.

New field called grav:

  • of type Point

  • initialed by the constructor to new Point(0, 0.098)

  • Used by the existing update() method to change the Ball’s velocity:

    • If the vel is not zero, update the vel field by adding the grav and vel together. Use the Point instance methods to do this.

    • Make sure you update the velocity before you update the position.

Ball Test 3
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Ball a;
Ball b;

void setup() {
  size(800, 300);
  a = new Ball(50, 200, 20);
  b = new Ball(700, 150, 100);
  a.setVelocity(3.5, -5.5);
}

void draw() {
  background(0, 0, 0);

  fill(0, 255, 0);
  a.update();

  fill(0, 0, 255);
  b.update();
}

Processing Asg 7.3

Note: This assignment depends on the Ball, Button, and Point classes created previously and the Cannon class provided below. Copy them into separate processing tabs.

Assignment Instructions

Duplicate the functionality in the video. The colors and positions of shapes do not need to match exactly. You do not need to write any new classes for this assignment.

The Cannon class is complex, but the comments above the methods describe their functionality. You will need the constructor, update(), rotateLeft() and fire() methods to complete this.

Notes From Video:

  • Hold down the left/right buttons to tilt the Cannon.

  • Click the Fire button to shoot once.

Cannon Class
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
class Cannon {
  Point pos;
  int shots;
  int maxShots;
  Ball[] amo;
  int canLength;
  int canHeight;
  int power;
  int degrees;

  /**
  * Constructs a Cannon
  * @param x  center of the square cannon base.
  * @param y  center of the square cannon base.
  */
  Cannon(int x, int y) {
    this.pos = new Point(x, y);
    this.shots = 0;
    this.maxShots = 100;
    this.amo = new Ball[this.maxShots];
    this.canLength = 60;
    this.canHeight = 20;
    this.power = 10;
    this.degrees = 45;
  }

  /**
  * @return true if there is amo left.
  */
  boolean hasAmo() {
    return shots < maxShots;
  }

  /**
  * Note: will cap rotation in the range 15 to 75 degrees
  * @param d  number of degrees to rotate (can be negative).
  */
  void rotateLeft(int d) {
    int temp = degrees + d;
    if(temp < 15) {
      temp = 15;
    } else if (temp > 75) {
      temp = 75;
    }
    degrees = temp;
  }

  /**
  * Draws the cannon and the cannon balls.
  * Should be called every frame.
  */
  void update() {
    for(int i = 0; i < this.shots; i++) {
      Ball b = this.amo[i];
      fill(0, 0, 0);
      b.update();
    }

    fill(0, 0, 0);
    //draw square base
    int size = this.canHeight + 10;
    square(pos.getXInt()-size/2, pos.getYInt()-size/2, size);

    pushMatrix(); //enable transformations
    translate(pos.getXInt(), pos.getYInt()); // origin is base of cannon
    rotate(radians(-degrees)); //rotate happens about origin.
    rect(0, -this.canHeight/2, this.canLength, this.canHeight);
    popMatrix(); //disable transformations
  }

  /**
  * Fires a Cannon Ball
  * @param percent  between 0 and 1.
  */
  void fire(double percent) {
    if(this.hasAmo()) {
      //direction the cannon is pointing.
      Point v = new Point(1, -Math.tan(Math.toRadians(this.degrees)));
      v = v.div(v.mag()); //unit vector

      Point d = v.mult(this.canLength); //dist to cannon mouth
      Point p = this.pos.add(d); //spawn point
      Ball b = new Ball(p.getXInt(), p.getYInt(), this.canHeight/2);

      Point f = v.mult(4+percent*power); //shot vector
      b.setVelocity(f.getXInt(), f.getYInt());
      this.amo[this.shots] = b;
      this.shots += 1;
    }
  }
}

8. Chapter Eight: Reusable Classes

A general strategy when designing classes is to make them as reusable as possible. Ideally, classes are not just reused by you in your current project, but by other programmers across many projects across many years. To accomplish this we need classes to be flexible, but also robust. Programmers who know very little about the inner workings of a class should not be able to accidentally break its logic. To create flexibility and safeguards we will need several new keywords including public, private, and static.

8.1. Naming Conventions

As we get into more traditional layouts for class files, it is important that we take a moment to summarize the naming conventions most Java programmers stick to. As names cannot contain spaces, we use a technique called CamelCase to combing separate words into a name capitalizing the first letter of extra words in the name.

  • Class Names:

    • Example: LaserTurret

    • Typically a noun

    • Starts with an uppercase letter followed by CamelCase.

  • Variable Names:

    • Example: zipCode

    • Typically a noun

    • Starts with a lowercase letter followed by CamelCase.

  • Method Names:

    • Example: confirmPurchase

    • Typically a verb

    • Starts with a lowercase letter followed by CamelCase.

8.2. Protecting Fields

Fields, also know as instance variables, are the members of a class that make up its data. We can control whether or not other classes use them directly by declaring them as public or private.

In the example below we use the public access modifier to allow the Main class to access the Point class’s fields:

Point class with public fields
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Point {
  public double x; (1)
  public double y; (1)

  Point(double x, double y) {
    this.x = x;
    this.y = y;
  }

  public String toString() {
    return "Point: (" +
      this.x + ", " +
      this.y + ")";
  }
}
1 Declaring fields as public.
Point class tester
1
2
3
4
5
6
7
8
9
public class Main {
  public static void main(String[] args) {
    Point a = new Point(3.5, 7);
    Point b = new Point(-1, 3.14);
    System.out.println(a.x); (1)
    b.y = 50; (2)
    System.out.println(b.toString());
  }
}
1 Accessing public field x
2 Accessing public field y
Console Output
3.5
Point: (-1.0, 50.0)

In the example below we use the private access modifier to prohibit the Main class from accessing the Point class’s fields:

Point class with private fields
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Point {
  private double x; (1)
  private double y; (1)

  Point(double x, double y) {
    this.x = x;
    this.y = y;
  }

  public String toString() {
    return "Point: (" +
      this.x + ", " +
      this.y + ")";
  }
}
1 Declaring fields as private.
Point class tester
1
2
3
4
5
6
7
8
9
public class Main {
  public static void main(String[] args) {
    Point a = new Point(3.5, 7);
    Point b = new Point(-1, 3.14);
    System.out.println(a.x); (1)
    b.y = 50; (2)
    System.out.println(b.toString());
  }
}
1 Compile Error: x has private access
2 Compile Error: y has private access

Protecting fields with the private access modifier is standard practice as it prevents other programmers (writing other classes) from accidentally modifying fields to unacceptable values. For example, we would not want someone setting the month/day/year fields of the Date class to 50/50/2020 as this is not a valid calendar date.

8.3. Protecting Methods

Instance methods provide the operations of a class. We can control whether or not other classes use them directly by declaring them as public or private.

In the example below we use the public access modifier to allow the Main class to access the Point class’s methods (and constructor):

Point class with public methods
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Point {
  private double x;
  private double y;

  public Point(double x, double y){(1)
    this.x = x;
    this.y = y;
  }

  public Point add(Point other) { (2)
    double tx = this.x + other.x;
    double ty = this.y + other.y;
    return new Point(tx, ty);
  }

  public String toString() {
    return "Point: (" +
      this.x + ", " +
      this.y + ")";
  }
}
1 Declaring constructor as public.
2 Declaring instance method as public.
Point class tester
1
2
3
4
5
6
7
8
public class Main {
  public static void main(String[] ag){
    Point a = new Point(3.5, 7); (1)
    Point b = new Point(-1, 3.14); (1)
    Point c = a.add(b); (2)
    System.out.println(c.toString());(3)
  }
}
1 Using public constructor.
2 Using public add() method.
3 Using public toString() method.
Console Output
Point: (2.5, 10.14)

In the example below we use the private access modifier to prohibit the Main class from accessing the Point class’s methods:

Point class with private methods
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Point {
  private double x; (1)
  private double y; (1)

  private Point(double x, double y){(1)
    this.x = x;
    this.y = y;
  }

  private Point add(Point other) { (2)
    double tx = this.x + other.x;
    double ty = this.y + other.y;
    return new Point(tx, ty);
  }

  public String toString() {
    return "Point: (" +
      this.x + ", " +
      this.y + ")";
  }
}
1 Declaring constructor as private.
2 Declaring instance method as private.
Point class tester
1
2
3
4
5
6
7
8
public class Main {
  public static void main(String[] ag){
    Point a = new Point(3.5, 7); (1)
    Point b = new Point(-1, 3.14); (1)
    Point c = a.add(b); (2)
    System.out.println(c.toString());
  }
}
1 Compile Error: Point(double,double) has private access
2 Compile Error: add(Point) has private access

Making instance methods accessible with the public access modifier is standard practice. It is rare that we would want to prevent other classes from calling an instance method.

8.4. Getters and Setters

We can control read versus write acces to fields by making the fields private and creating instance methods to get (read) or set (modify) the fields as needed.

The example below creates a version of the Point class that only has getter methods for the fields, but no setter methods. As a result, this class is called immutable. An object of this class can never be modified.

Point class with only getters
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Point {
  private double x;
  private double y;

  public Point(double x, double y){
    this.x = x; (1)
    this.y = y; (1)
  }

  public double getX() { (2)
  	return this.x;
  }

  public double getY() { (2)
  	return this.y;
  }

  public Point add(Point other) {
    double tx = this.x + other.x;
    double ty = this.y + other.y;
    return new Point(tx, ty);
  }
}
1 Only the constructor sets the field values.
2 Getter methods allow other classes to read the field values.
Point class tester
1
2
3
4
5
6
7
8
public class Main {
  public static void main(String[] ag){
    Point a = new Point(3.5, 7);
    Point b = new Point(-1, 3.14);
    System.out.println(a.getX()); (1)
    System.out.println(b.getY()); (1)
  }
}
1 Getting the field values.
Console Output
3.5
3.14

The example below creates an example Employee class that has a combination of getter and setter methods for the fields. As a result, the employeeID field can never be modified, but the name and salary fields can be.

Employee class with Getters and Setters
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Employee {
  private int employeeID;
  private String name;
  private double salary;

  public Employee(int id, String n, double s){
    this.employeeID = id;
    this.name = n;
    this.salary = s;
  }

  public int getEmployeeID() { (1)
    return this.employeeID;
  }

  public String getName() { (1)
    return this.name;
  }

  public void setName(String name) { (2)
    this.name = name;
  }

  public double getSalary() { (1)
    return this.salary;
  }

  public void setSalary(double salary) { (2)
    this.salary = salary;
  }
}
1 Declaring Getter Method
2 Declaring Setter Method
Employee class tester
1
2
3
4
5
6
7
8
9
public class Main {
  public static void main(String[] args){
    Employee a = new Employee(900084112, "Lisa", 75000.00);
    Employee b = new Employee(900084111, "Sam", 50000.00);
    System.out.println(a.getEmployeeID() + ":" + a.getName() + " $" + a.getSalary()); (1)
    b.setSalary(b.getSalary() * 1.2); (2)
    System.out.println(b.getEmployeeID() + ":" + b.getName() + " $" + b.getSalary()); (1)
  }
}
1 Calling Getters
2 Calling Setter

Processing Asg 8.1

Instructions Part 1

Create a Ghost class to create a PacMan Ghost.

The Ghost class should have:

  • all private fields

  • a public constructor and public update() method such that the tester produces the image show.

  • Note you can find the code to draw a ghost in Chapter 3: Drawing Ghosts.

Proc Asg8.2a

Ghost Tester 1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Ghost a;
Ghost b;
void setup() {
  size(500, 500);
  a = new Ghost(100, 100);
  b = new Ghost(400, 400);
}

void draw() {
  background(0, 0, 0);
  a.update();
  b.update();
}
Instructions Part 2

Create getters and setters for the Ghost’s fields. Make sure the setters prevent the ghost from going totally off screen.

Ghost Tester 2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Ghost a;
Ghost b;
void setup() {
  size(500, 500);
  a = new Ghost(100, 100);
  b = new Ghost(400, 400);
}

void draw() {
  background(0, 0, 0);
  a.update();
  b.update();
  if(keyPressed){
    if(key == 'w') {
      a.setY(a.getY() - 1);
    }
    if(key == 's') {
      a.setY(a.getY() + 1);
    }
    if(key == 'a') {
      a.setX(a.getX() - 1);
    }
    if(key == 'd') {
      a.setX(a.getX() + 1);
    }
  }
}
Optional Challenge

Make the ghosts blink.

Hint: You need an extra field in the Ghost class to control how much blue to draw the ghost with. In the video, the ghosts lose 5 blue per frame until they have none, then reset back to full blue.

Processing Asg 8.2

Note: This assignment depends on the Ball, Button, Cannon, and Point classes created previously. Copy them into separate processing tabs.

Instructions Part 1

Create a VertMeter class to create vertical meters (bars) that can be filled to a specified percentage.

The VertMeter class should have:

  • all private fields

  • a public constructor and public instance methods such that the tester works like the video.

VertMeter Tester
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
VertMeter bar;
void setup() {
  size(500, 500);
  bar = new VertMeter(225, 250, 50, 100);
}

void draw() {
  background(0, 0, 0);
  bar.update();
  double p = bar.getPercent();
  if(mouseX < 250) {
    bar.setPercent(p - 0.01);
  } else {
    bar.setPercent(p + 0.01);
  }
}

Notes from video:

  • The meter starts out 50% full (0.5).

  • Thanks to logic in setPercent(), the meter never goes below 0% (0.0) or above 100% (1.0) full.

Instructions Part 2

Integrate a power meter into the cannon project from Processing Assignment 7.3.

8.5. Static Fields

We have covered regular fields, also known as instance variables since the beginning of chapter 7. These fields hold values specific to an object (a.k.a instance or value) of a class. For example, every instance of Date had its own month, day, and year. There are some situations where fields have the same value across all instances. For example, consider a Student class. Each student might have their own gpa field, but every student would share the same maxGpa value (4.0) representing the highest possible grade point average. Such a field would be marked as static and would be called a class variable instead of an instance variable because all instances (objects) would share the same value.

Student class with a static field
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Student {
  private int studID;
  private String name;
  private double gpa;
  public static double maxGpa = 4.0; (1)

  public Student(int ID, String n, double g) {
    this.studID = ID;
    this.name = n;
    this.gpa = g;
  }

  public int getStudID() {
    return this.studID;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public double getGpa() {
    return this.gpa;
  }

  public void setGpa(double gpa) {
  	if(gpa < 0) {
  	  gpa = 0;
  	}
  	if(gpa > Student.maxGpa) { (2)
  	  gpa = Student.maxGpa; (2)
  	}
    this.gpa = gpa;
  }

  public double getPercentGrade() {
    return this.gpa / Student.maxGpa; (2)
  }
}
1 Declaring a class variable with static. The value is initialized here because a construtor does not need to be called before it is used.
2 Using a static variable requires the class name because it is not specific to this object.
Student class tester
1
2
3
4
5
6
7
8
public class Main {
  public static void main(String[] args) {
    System.out.println("MAX GPA: " + Student.maxGpa); (1)
    Student a = new Student(900012345, "Bob", 3.0);
    System.out.println(a.getName() + " has GPA: " + a.getGpa() +
        " which is " + (100 * a.getPercentGrade()) + "% of max.");
  }
}
1 Note we reference the class variable directly from the class name.
Console Output
MAX GPA: 4.0
Bob has GPA: 3.0 which is 75.0% of max.

8.6. Static Methods

Most of the methods we write in a class reference fields (instance variables), but every once in a while we might write a method that does not reference any instance variables. These methods should be declared as static making them class methods. Class methods, like class variables, do not need an object to be constructed before they are called.

Student class with a static method
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class Student {
  private int studID;
  private String name;
  private double gpa;
  public static double maxGpa = 4.0;
  public static int requiredCredits = 123;

  public Student(int ID, String n, double g) {
    this.studID = ID;
    this.name = n;
    this.gpa = g;
  }

  public int getStudID() {
    return this.studID;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public double getGpa() {
    return this.gpa;
  }

  public void setGpa(double gpa) {
    this.gpa = gpa;
  }

  public double getPercentGrade() {
    return this.gpa / Student.maxGpa;
  }

  public static int maxCreditPoints() { (1)
    return (int) Student.maxGpa * Student.requiredCredits; (2)
  }
}
1 Declaring a class method with static.
2 The method does not use any instance variables, so it can be declared static.
Student class tester
1
2
3
4
5
public class Main {
  public static void main(String[] agrs) {
    System.out.println("MAX CREDIT POINTS: " + Student.maxCreditPoints()); (1)
  }
}
1 Note we reference the class method directly from the class name.
Console Output
MAX CREDIT POINTS: 492

9. Chapter Nine: ArrayList

In Chapter 5 we learned about arrays as a way of storing multiple values in 1 variable. Here we introduce the ArrayList class which does the exact same thing with a couple of advantages.

9.1. Array vs. ArrayList

Arrays and ArrayLists
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList; (1)
public class Main {
    public static void main(String[] args) {
        String[] a = new String[3]; (2)
        a[0] = "Sam";
        a[1] = "Lisa";
        a[2] = "Bob";

        ArrayList<String> b = new ArrayList<String>(); (3)
        b.add("Sam"); (4)
        b.add("Lisa"); (4)
        b.add("Bob"); (4)

        for(int i = 0; i < b.size(); i++) { (5)
            System.out.println(a[i] + " " + b.get(i)); (6)
        }
    }
}
1 We need an import statment before using ArrayList
2 Regular arrays require a pre-defined length.
3 ArrayList requires a class type between <>, but no length.
4 The .add() instance method adds values
5 The .size() instance method gets the length of the ArrayList
6 The .get() instance method gets values
Console Output
Sam Sam
Lisa Lisa
Bob Bob

9.2. Useful ArrayList Instance Methods

The ArrayList has a lot of handy methods. Below is the list we need for now:

  • .add(Object o)

  • .get(int index)

  • .set(int index, Object o)

  • .remove(int index)

  • .size()

  • .indexOf(Object o) (requires the class have a propper .equals() method)

ArrayList Example

Can you predict the printed output?

Processing Asg 9.1

Note: This assignment depends on the Point class code created previously. Copy it into a separate processing tab.

Instructions Part 1

Create a Target class so that the test code makes the picture shown.

The Target class should have:

  • 2 fields:

    • Point pos - represents the current position of the target.

    • int radius - represents the half the diameter of the target.

  • A constructor that takes 2 int parameters x, y. Use these parameters to initialize the pos field. The radius field should always be set to 20.

  • An update method that uses the circle() method multiple times to draw the circles in the correct location.

    • The circles are red, white, and red.

    • The inner most circle has half the radius of the white circle. The white circle has half the radius of the outer circle.

Target Test 1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Target t1;
Target t2;

void setup() {
  size(500, 300);
  t1 = new Target(100, 100);
  t2 = new Target(400, 200);
}

void draw() {
  background(0, 0, 0);

  t1.update();
  t2.update();
}

Proc Asg9.1a

Instructions Part 2

Create a TargetMgr class so that the test code makes the animation shown.

  • TargetMgr needs 7 fields:

    • leftX, topY, widthX, and heightY are ints initialized directly from constructor parameters and will be used in update() to restrict where Targets spawn.

    • frameGap is an int initialized directly from the last constructor parameter and will be used to control how often Targets spawn.

    • frameCountDown is an int that represents how many more frames are left before the next Target spawns. The constructor initializes it to zero.

    • targetList is is an ArrayList of Targets that keeps up with all current Targets. The constructor initializes it to an empty list.

  • TargetMgr needs 1 instance method called update():

    • It does not return a value or take parameters.

    • It loops through the targetList and calls the update() method on each Target.

    • After the loop, if the frameCountDown is greater than zero, it reduces the frameCountDown by 1.

    • Otherwise, it:

      • resets the frameCountDown to frameGap

      • creates a new Target randomly positioned within the box defined by leftX, topY, widthX, and heightY

      • adds the new Target to the targetList.

Target Test 2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
TargetMgr tm;

void setup() {
  size(500, 500);
  tm = new TargetMgr(200, 200, 100, 100, 20);
}

void draw() {
  background(0, 0, 255);

  fill(0, 255, 0);
  rect(200, 200, 100, 100);

  tm.update();
}

Processing Asg 9.2

Note: This assignment depends on the Ball, Button, Cannon, Point, Target, TargetMgr, and VertMeter classes created previously. Copy them into separate processing tabs.

Instructions Part 1

Make the Ball capable of destroying Targets.

  • Add a getter instance method to the TargetMgr class for the targetList field.

  • Add a destroy instance method to the Ball class.

    • The method should not return anything.

    • It should have 1 parameter of type ArrayList<Target>.

    • It should loop through all the targets in the target list (parameter) and check if the distance between a target and this ball is less than 30.

    • Note: The formula for calculating the distance between 2 points called a and b is: a.sub(b).mag()

    • If a ball is is close enough to a target, it should be removed from the target list.

Destroy Target Test
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
TargetMgr tm;
Ball b1;
Ball b2;

void setup() {
  size(500, 500);
  tm = new TargetMgr(200, 200, 100, 100, 20);
  b1 = new Ball(220, 50, 10);
  b2 = new Ball(50, 250, 10);
}

void draw() {
  background(0, 0, 255);

  fill(0, 255, 0);
  rect(200, 200, 100, 100);

  tm.update();

  fill(0, 0, 0);
  b1.update();
  b1.destroy(tm.getTargetList());
  b2.update();
  b2.destroy(tm.getTargetList());

  //wait 2 seconds, then go
  if(frameCount == 120) {
    b1.setVelocity(1, 0);
    b2.setVelocity(10, 0);
  }
}
Instructions Part 2

Put it all together!

  • Integrate the TargetMgr into the cannon project main code from Processing Assignment 8.2.

  • Make sure the TargetMgr is configured to spawn targets in a reasonably large area such that every target created will be hittable by the cannon.

  • Modify the Cannon class:

    • Add 1 field of type ArrayList<Target>.

    • Add 1 parameter to the constructor of type ArrayList<Target> and use it to initialize the field.

    • Find the loop that calls the update() instance method on all the Balls in the amo field and have it call the destroy() instance method using the new field.

  • In setup() of the main code, call the Cannon constructor with new list of targets from the TargetMgr.

Cannon Ball Loop
1
2
3
4
5
6
7
8
...
for(int i = 0; i < this.shots; i++) {
  Ball b = this.amo[i];
  fill(0, 0, 0);
  b.update();
  b.destroy(???);
}
...
Main code setup method
1
2
3
4
5
6
7

void setup() {
...
  tm = new TargetMgr(300, 50, 750, 250, 50);
  can = new Cannon(50, 200, tm.getTargetList());
...
}