CSCI-UA.0101-003
Intro To Computer Science (undergrad)
Fall 2011
Instructor: Ken Perlin

Class time/place: Monday / Wednesday 2-3:15pm, RM 102, WWH

Office hours: Tuesday 4-5pm, 715 Bwy, 12th floor

Grader: Jonathan Tompson

Students who have agreed to place their work on-line

This will mostly be a projects course. Showing up to class is essential. Basically you will learn how to be a good programmer by programming.

It will be a lot of work, but it will be fun. :-)

Here's a good book you might want to get as a reference for Java, which you can find at the NYU Book Store:

Introduction to Java Programming, Brief Version, 7/E
(If you already own the Sixth Edition you can use it for this course)
By Y Daniel Liang
Published by Prentice Hall, 2008
ISBN-10: 0136042589 ISBN-13: 9780136042587


We will start by creating very simple Java programs at the beginning of the semester, mostly to get you used to the Java syntax, and to make sure you know how to edit, compile and run a program.

Then we will progress to more interesting examples that use Java's built in libraries, which will let us do things involving graphics, sound and music.

The most important thing, if you're used to Python, is to get used to Java's very different way of creating and working with objects and object inheritance.

If you decide to take this course, be prepared to program. There will be a programming assignment every week, and you will need to do the work every week to keep up with the material. If you're the kind of person who waits until the end of the semester to catch up on your work, then you would definitely fail this class.

 

Direct links to the notes below:


Wednesday September 7

Today in class we went over how to write a simple "hello world" program. Although I did it from the command line, you will probably want to write your programs using an Integrated Development Environment (IDE) such as Eclipse.

You can download Eclipse from the Eclipse Downloads page. Be sure to download Eclipse IDE for Java Developers.

Installing Eclipse is slightly more involved if you are on Windows than if you are on a Mac. So if you are on Windows, you can read the Tutorial for installing Eclipse on Windows that Jonathan has put together.

The "Hello World" program itself is quite simple. I've put comment lines in the code below. Everying from the characters "//" to the end of a line is considered a comment, and is ignored by the program:

// You are creating an object of class "HellowWorld".

public class HelloWorld
{
// If a program is going to be run from the command line
// then it has to have a "main" method, with exactly
// this declaration (public static void) and with
// one argument of this type (an array of Strings):

public static void main(String args[]) {

   // A special object called "System.out" knows
   // how to print messages to the command line

   System.out.println("Hello world!");
   }
}
For Monday, try to get the HellowWorld program working from Eclipse, by following the Eclipse tutorial on writing a Hello World program.

Also for Monday, write a short essay on why you are interested in programming computers (ie: something you would like to do that you think programming will help you with), and put that essay on your index.html page on your NYUHome public web page.

In order to put this essay on your web page, you are going to need to log in to NYUHome, using your student id, as Jonathan showed in class, and follow the steps he showed in class:

If you are on Windows, a good easy to use text editor is WordPad (not NotePad, because it doesn't deal well with line breaks). Of course feel free to use whatever text editor you like.

If you are on a Mac and you want to edit a file that ends in ".html" with TextEdit, you need to change the preferences in TextEdit to show the actual file contents. The default view shows the file the way it looks in a web browser (that's what happened to Jonathan in class today when he tried to edit "index.html" after downloading it).

To set things properly in TextEdit:

Now you can open an html file in TextEdit and edit it like any other text file.


Monday September 12

Today we focused on some important built-in variable types, including char, int, float and double.

Unlike Python, Java requires you to explicitly declare the type of a variable before you assign it a value. This is shown in the example below, which we created in class today.

A char is generally used to store the individual characters in a String. It uses up one byte of storage, which is 8 bits. Therefore it can store 28 or 256 different values.

An int is a 32 bit integer. One bit is reserved for the sign (to determine whether the integer is positive or negative) and the other 31 bits give the magnitude. This allow values from about -231 to +231, or from about -2 Billion to +2 Billion.

A float is not used all that much. It's a form of scientific notation, with a single sign bit, an8 bit exponent storing a power of two shift, and a 23 bit mantissa.

I was slightly off in my description of double in class. It actually has an 11 bit exponent (sorry about that -- I was trying to go from memory).

There are total of 64 bits (8 bytes) in a double. The top bit is for the sign, then 11 bits for the exponent, then the remaning 52 bits for the mantissa.

You probably don't need to know more than that at this point, although we may revisit this topic later in the semester if we have time.

Constants that have a decimal point -- like 5.3 -- are interpreted by the compiler as double. If they don't have a decimal point, they are interpreted as an int.

Rules for combining ints and doubles:

In order to convert a double to an int, you need to cast it as an int. In Java you do this as follows:
int n = (int)(3.5 + i);
In the above expression, the result of (3.5 + i) is a double. Since you cannot assign a double into an int variable, you need to cast the double as an int, using the "(int)" operator.

Here is the example we created in class:

public class example1
{
   public static void main(String args[]) {

   // EXAMPLES OF DECLARING AND SETTING INTEGER VARIABLES

      int i = 4;
      int j = 10;
      int k = i + j;
      int m = 5 * k;

   // EXAMPLES OF DECLARING AND SETTING DOUBLE VARIABLES

      double x = 5 * k;
      double y = 5.0 * k;

   // EXAMPLE OF CASTING A DOUBLE EXPRESSION TO AN INT

      int n = (int)(50.1 * k);

      System.out.println(n);
   }
}

Your homework for Wednesday is to email your web URL to the grader. The subject line of your email should read "PERLIN CLASS". Your short essay should already be up on your web page.


Wednesday September 14

Your homework, which will be due Wednesday September 21, will be to create a program that tells a "procedural story" as we discussed in class, in which your program's output mixed printed text and variables.

Your program should incorpate arguments from the command line. To run a program with command line arguments from Eclipse:

choose the "Run..." option in Eclipse. From there it is clear how to set the command line arguments.

See if you can make your procedural story fun and interesting. As inspiration, you can use some subject that interests you, such as baseball stats, history, physics, fashion (eg; converting clothing sizes betw. U.S. and somewhere else), math puzzles, economics, geography or literature.

To upload your homework you will need to go into the Eclipse workspace folder in your computer's file system (on a Mac it is, by default, within the Documents folder).

Compressing your folder into a zip file:

You will end up with a file named something like HelloWorld.zip.

Upload this file into the public folder on the web site you use for this class. Then link to the zip file from your index.html file.

As we said in class, the syntax for embedding a link into an html file looks something like this:

My homework is in <a href=HelloWorld.zip>This compressed file</a>.

In class we covered the topic of Strings, and discussed the fact that the '+' operator is overloaded, so that it results in concatenation, if at least one of its two operands is a String. If the other operand is not a String, then that other operand becomes promoted to a String. For example:

System.out.println("The value is " + 3);
results in the print-out:
The value is 3
To make this happen, Java first promoted the number 3 to the String "3", and then this String was concatenated with the string "The value is ".

We ended up with the following program, which is an example of a kind of procedural story:


public class MathProblem
{
   public static void main(String args[]) {

// CHECK TO SEE THAT THE USER HAS ENTERED AT LEAST FOUR COMMAND LINE ARGUMENTS

      if (args.length < 4) {

 // IF THEY HAVEN'T, PRINT OUT A MESSAGE DESCRIBING CORRECT USAGE OF THIS PROGRAM.

         System.out.println();
         System.err.println("usage: MathProblem person1 person2 int double");
         System.out.println();
         return;
      }

// THE FIRST TWO COMMAND LINE ARGUMENTS ARE PEOPLE'S NAMES.

      String person1 = args[0];
      String person2 = args[1];

// THE LAST TWO COMMAND LINE ARGUMENTS NEED TO BE CONVERTED INTO STRINGS.

      int n = Integer.parseInt(args[2]);
      int m = 103;
      double x = Double.parseDouble(args[3]);

// THE OUTPUT INTERMIXES TEXT AND ARITHMETIC EXPRESSIONS.
// JUST TO BE SAVE, ALWAYS ENCLOSE ARITHMETIC EXPRESSIONS IN PARENTHESES.

      System.out.println();
      System.out.println();
      System.out.println();
      System.out.println(person1 + " has " + n + " bags of groceries.");
      System.out.println("Each bag has " + m + " twinkies.");
      System.out.println();
      System.out.println(person2 + " eats " + x + " bags of his twinkies.");
      System.out.println("How many twinkies does " + person1 + " have?");
      System.out.println();
      System.out.println("He has " + ((n - x) * m) + " twinkies.");
      System.out.println();
      System.out.println();
      System.out.println();
   }
}


Monday September 19

We introduce Java's boolean data type, which has only two possible values: true and false -- the two boolean typed constants in Java, and therefore reserved words (that is, you can't use them as variable names).

Boolean logic, originated by the mathematician George Boole, is a way of figuring out answers to questions about sets of things, in which the answers to questions like "Are there any items in this set such that...?" can either be true or false.

Because values can only be either true or false, boolean operations with two arguments have very simple results, which are often called truth tables:

NOT (complement of a set):

F → T (only true if the item is not in the set)
T → F
AND (intersection of two sets):
F F → F
T F → F
F T → F
T T → T (only true if the item is in both sets)
OR (union of two sets):
F F → F (only false if the item is in neither set)
T F → T
F T → T
T T → T
In Java we can construct boolean expressions through these arithmetic operators:
a < b // a is less than b
a <= b // a is less than or equal to b
a > b // a is greater than b
a >= b // a is greater than or equal to b
a == b // a equals b
a != b // a does not equal b
where a and b can be an arithmetic type, such as int or double.

The NOT operator (complement) is !, the AND operator (intersection) in Java is && and the OR operator (union) is ||. So to create an expression that is true only if the integer n is between 1 and 10, we could construct the expression:

n >= 1 && n <= 10
To create an expression that's false only if n is between 1 and 10, we could construct the expression:
! (n >= 1 && n <= 10)

To create an expression that is true if n is either between 1 and 10 or else between 101 and 110, we could construct the expression:

n >= 1 && n <= 10 || n >= 101 && n <= 110
The reason the above expression doesn't need any parentheses in it is that the precedence (order of execution) of the comparative operators <, <=, etc., is greater than the precedence of the logical operators && and ||.

The precedence of ! is greater than the precedence of either && or ||, which is why we needed the parentheses in the second expression above, so that the "!" would apply to the entire expression.

Also, the precedence of && is greater than || (you can think of && as being like boolean multiplication and || as being like boolean addition, to remember their relative precedence).

Just as in arithmetic expressions, if we want to change the order of execution, we need to use parentheses. You are already familiar with this concept, since you know that 1 + 3 * 5 is 16 (since multiplication has higher precedence than addition) but (1 + 3) * 5 is 20.

Booleans are used to change the flow of control in a program, through conditionals and loops. In Java, a conditional is either of the form:

if ( BOOLEAN-EXPRESSION )
   STATEMENT
or
if ( BOOLEAN-EXPRESSION )
   STATEMENT
else
   STATEMENT
where BOOLEAN-EXPRESSION means any constant, variable or expression of type boolean, and STATEMENT means any simple or compound statement. For example:
if ( n >= 0 )
   System.out.println("n is not negative.");
Because an if statement is just a statement like any other, you can use it as the STATEMENT in the else clause, and this lets you chain multiple if/else statements together (so there is no need for the elif that you have in Python). For example:
if ( n > 0 )
   System.out.println("n is positive.");
else if ( n < 0 )
   System.out.println("n is negative.");
else
   System.out.println("n is zero.");

The simplest way to do loops is with the while statement, but a better way is with the for statement. The for statement is harder to learn, but it produces much easier to debug code, since all of the flow of control (initializing the looping variable, checking the boolean expression, incrementing the looping variable) are together in one line at the top of the loop.

It is also a very general construct, as you can see in the last example below, where the looping variable is multiplied instead of added each time through.

Below is the code we wrote in class, which shows the use of both of these loop constructs:


public class ex1
{
   public static void main(String args[]) {
      System.out.println("This is my exciting result!");
      double x = 1.1;

      // while ( BOOLEAN EXPR )
      //     STATEMENT

      int m = 1;
      while (m <= 10) {

         // ... lots of stuff

         x = x * m;

         m = m + 1;
      }

      // for ( DECLARE AND INITIALIZE SOMETHING ; BOOLEAN EXPR ; INCREMENT )
      //    STATEMENT

      for (int n = 0 ; n < 10 ; n = n + 1 ) {
         x = x * n;
      }

      //System.out.println("And the result is: " + x);

      for (int i = 1 ; i < 100 ; i = i * 2 ) {
         System.out.println("i = " + i);
      }

      for ( x = 1.1 ; x < 100 ; x = x * 1.3 ) {
          System.out.println("x = " + x);
      }
   }
}


Wednesday September 21

Command-line programming in Windows:

  1. You need to locate the /java/bin/ path after installing the Java SE development environment (found here: http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u27-download-440405.html). By default it is C:\Program Files\Java\jdk1.6.0_XX\bin\.

  2. Click Start -> Settings -> Control Panel -> System. Click on the Advanced tab -> Environment Variables. In the system variables section, you need to modify the "Path" variable, and add ";" on the end. The semicolon separates path arguments and you must include it. For example, if the Variable Path had the value "C:\Windows\System32\", it needs to be "C:\Windows\System32\; C:\Program Files\Java\jdk1.6.0_XX\bin\".
  3. You may need to restart the computer, but now when you open the DOS cmd window (Start -> Run -> cmd), you can call "javac" and "java" commands directly from the command line like Ken does in class.

Simulating comand-line arguments in Eclipse:

  1. Menu -> Run -> Run Configurations... -> Arguments tab -> Program Arguments

  2. In the "Program Arguments" input window, on a single line you can enter the arguments that will go to your main function (just like you would from the command line from Unix or DOS).

  3. The VM arguments on the same page are for changing the parameters of the java runtime engine.

In class we talked about the other kinds of conditionals: conditional expressions and switch/case statements. These are language elements that Java inherited from the C programming language, on which it is partly based.

Conditional expressions let you embed flow of control decisions right into the middle of an expression, rather than needing to build an entire if/else statement.

The syntax for a conditional expression is:

BOOLEAN-EXPR ? EXPRESSION-TO-EXECUTE-IF-TRUE : EXPRESSION-TO-EXECUTE-IF-FALSE
The last two expressions must be of the same type. Exactly one of those two expressions will be executed.

For example, the following expression:

n < 10 ? 100 : 200
will have a value of 100 if n is 0, but will have a value of 200 if n is 20.

Either of the last two expressions can itself be a conditional expression, and this allows you to do the equivalent of chained if else if else ... statements. For example, the following are both valid conditional expressions. They both do the same thing:

n > 0 ? "positive" : n < 0 ? "negative" : "zero

n >= 0 ? n > 0 ? "positive" : "zero" : "negative

Because the ? and : operators have a very low precedence, you generally want to put a conditional expression in parentheses, when you use it in a larger expression. For example, consider the following code:

if (x > 0)
   y = 10 * (x + 1) - z;
else
   y = 10 * x - z;
There is a lot of repeated code here, which can lead to errors. Using conditional expressions we can rewrite this in a much simpler way:
y = 10 * (x > 0 ? x + 1 : x) - z;

Switch/case statements are a way to explicitly express the concept of having a number of discrete cases to choose from. The syntax is as follows:

switch ( INTEGER-EXPR ) {
case INTEGER-CONSTANT : STATEMENTS
case INTEGER-CONSTANT : STATEMENTS
...
}
The integer expression is evaluated, and then execution immediately jumps to the case with the matching integer value.

By default, after a case is executed, execution continues with the immediately following case. Often that is not what we want. Fortunately, there is also a special statement, break;, that jumps execution to the end of the switch/case statement.

For example, the following code assigns values to a String variable based on a numeric value.

String value = "unknown";
switch (n) {
case  1: value = "one"; break;
case  2: value = "two"; break;
case  3: value = "three"; break;
case  4: value = "four"; break;
case  5: value = "five"; break;
case  6: value = "six"; break;
case  7: value = "seven"; break;
case  8: value = "eight"; break;
case  9: value = "nine"; break;
case 10: value = "ten"; break;
}

There are also situations where it's useful to not use break statements. As we discussed in class, letting execution drop through from one case to the next can be used to compute triangular numbers or factorials:

int sum = 0;
switch (n) {
case 10: sum += 10;
case  9: sum +=  9;
case  8: sum +=  8;
case  7: sum +=  7;
case  6: sum +=  6;
case  5: sum +=  5;
case  4: sum +=  4;
case  3: sum +=  3;
case  2: sum +=  2;
case  1: sum +=  1;
}

int product = 0;
switch (n) {
case 10: product *= 10;
case  9: product *=  9;
case  8: product *=  8;
case  7: product *=  7;
case  6: product *=  6;
case  5: product *=  5;
case  4: product *=  4;
case  3: product *=  3;
case  2: product *=  2;
case  1: product *=  1;
}
One feature of switch/case statements that we did not discuss in class is the optional default statement. This lets you execute something in the case where none of the cases matches.

Here is an example of using the default statement. In this case we are using it to flag an error condition, when variable n has an unexpected value:

int value = 0;
switch (n) {
case 0: value =   1; break;
case 1: value =   2; break;
case 2: value =   4; break;
case 3: value =   8; break;
case 4: value =  16; break;
case 5: value =  32; break;
case 6: value =  64; break;
case 7: value = 128; break;
case 8: value = 256; break;
default:
System.out.println("error: n is out of range");
break;
}

We also discussed special-purpose shorthand that Java provides, also inherited from the C programming language.

Assignment operators: Anywhere you have an assignment that modifies a variable (eg: a = a + 1), you can place the operator to the left of the equals sign, as a kind of short-hand.

Below are some examples. In the left is the long way of saying it. In the right column is the more compact way, using an assignment operator:

n = n + 1; n += 1;
a = a * 2; a *= 2;
x = x / 3; x /= 3;

Special cases of assignment operator are the increment and decrement operators, which are particularly useful for controlling the value of looping variables.

The two increment operators are:

n++ // Increase n by one.  The value of this expression is what n was before the increment happened.
++n // Increase n by one.  The value of this expression is what n becomes after the increment happens.

The two decrement operators are:

n-- // Decrease n by one.  The value of this expression is what n was before the decrement happened.
--n // Decrease n by one.  The value of this expression is what n becomes after the decrement happens.
The choice of ++n or n++ allows you to have finer control over how looping variables do their thing.

For example, the following code:

int n = 0;
while (n++ < 4)
   System.out.println(n);
Results in four numbers being printed:
1
2
3
4
Whereas this slightly different code:
int n = 0;
while (++n < 4)
   System.out.println(n);
Results in only three numbers being printed:
1
2
3
Your homework:

Your homework, which will be due before class next Wednesday, September 28, is to write and upload a program that uses conditionals to tell a variable story. In other words, as the user of the program changes command line arguments, the story that your program prints should change.

Below I've three simple "variable stories" I wrote. One uses conditional expressions to vary the story, another uses an if/else statement to vary the story, and another uses a switch/case statement to vary the story.

Feel free to make your variable story about any topic you'd like. It can be about your favorite band, or fashion, or politics, or your best friend or your cat. It can describe your daily schedule, or what a plan of what you will eat for dinner each day of the week. It can describe a math problem, or produce a poem. Try to have fun with it.

Your story doesn't need to be complicated. The thing I'm mainly going to be looking for is that you can successfully use conditional expressions or statements to vary the output of a program.

Your program just needs to have three elements:

  • One or more command line arguments that will influence how the program will run;

  • One or more conditional expressions, if/else statements and/or switch/case statements that cause different things to happen, depending on the value(s) of your command line arguments;

  • Your program needs to print out some sort of text narrative.

Don't make your program look too much like the examples I've showed here. A safe way to make sure your program doesn't look too much like these programs is to start with a story topic or idea, and build your program around that.

 

Example 1 of a "variable story":

public class MyStory1
{
   public static void main(String args[]) {

      if (args.length < 2) {
         System.out.println("usage: MyStory1 Y/N name1 M/F name2 M/F");
         return;
      }

      boolean areFriends = args[0].equals("Y");

      String name1 = args[1];
      String name2 = args[3];

      boolean isMale1 = args[2].equals("M");
      boolean isMale2 = args[4].equals("M");

      System.out.println();
      System.out.println();
      System.out.println(name1 + " went to the store.");
      System.out.println("While buying something, " + (isMale1 ? "he" : "she") + " saw " + name2 + ".");
      System.out.println("This made " + name2 + " " + (areFriends ? "happy" : "miserable") + ".");
      System.out.println();
      System.out.println();
   }
}

Example input for the above program:

java MyStory1 Y Fred M Wilma F
which produces the following output:
Fred went to the store.
While buying something, he saw Wilma.
This made Wilma happy.

 

Example 2 of a "variable story":

public class MyStory2
{
   public static void main(String args[]) {

      if (args.length < 2) {
         System.out.println("usage: MyStory2 integer1 integer2");
         return;
      }

      int i = Integer.parseInt(args[0]);
      int j = Integer.parseInt(args[1]);

      System.out.println();
      System.out.println();
      System.out.println("John had the choice of having " + i + " apples or " + j + " apples.");
      if (i < j)
         System.out.println("Since " + i + " is less than " + j + ", he chose " + j + " apples.");
      else
         System.out.println("Since " + i + " is greater than " + j + ", he chose " + i + " apples.");
      System.out.println();
      System.out.println();
   }
}

Example command line input for the above program:

java MyStory2 10 20
which produces the following output:
John had the choice of having 10 apples or 20 apples.
Since 10 is less than 20, he chose 20 apples.

 

Example 3 of a "variable story":

public class MyStory3
{
   public static void main(String args[]) {

      if (args.length < 1) {
         System.out.println("usage: MyStory3 integer");
         return;
      }

      int n = Integer.parseInt(args[0]);
 
      String colorName = "not in the box";
      switch (n) {
      case 1: colorName = "red"; break;
      case 2: colorName = "orange"; break;
      case 3: colorName = "yellow"; break;
      case 4: colorName = "green"; break;
      case 5: colorName = "blue"; break;
      case 6: colorName = "indigo"; break;
      case 7: colorName = "violet"; break;
      }

      System.out.println();
      System.out.println();
      System.out.println("Mary got a brand new set of crayons, with the colors of the rainbow.");
      System.out.println("Crayon number " + n + " was " + colorName + ".");
      System.out.println();
      System.out.println();
   }
}
Example command line input for the above program:
java MyStory3 4
which produces the following output:
Mary got a brand new set of crayons, with the colors of the rainbow.
Crayon number 4 was green.


Monday, September 26

In class we talked about arrays. In Java, an array's index starts at 0. So, for example, an array of length 10 will have indices from 0 through 9.

You declare the type of an array by saying either:

TYPE NAME[];
or
TYPE[] NAME;
For example, the following are all correct ways to declare the type of an array:
String[] a;
int b[];
double values[];
boolean decisions[];
In Java, array memory is allocated at run time, by asking for memory from the heap. This can be done by using the "new" command, as follows:
String[] a = new String[10];
int b[] = new int[5];
double values[] = new double[3];
boolean decisions[] = new boolean[20];
Notice, in the above example, that the type of the allocated memory has to match the type of the array.

Once you've allocated memory for an array, then you can assign values to its elements:

String names[] = new String[4];

names[0] = "Bob";
names[1] = "Carol";
names[2] = "Ted";
names[3] = "Alice";
Java also allows you to combine memory allocation and value assignments into a single statement, by the following convenient shorthand:
String names[] = { "Bob", "Carol", "Ted", "Alice" };
An array is really just a pointer into memory. If you understand this, then it becomes more clear how arrays do what they do.

For example, consider the following statements:

int a[], b[];

a = new int[10]; // STATEMENT_1
b = a;           // STATEMENT_2
STATEMENT_1 above declares array a and allocates 10 words of memory for it from the heap. What is actually stored in a is the starting address of some memory area in the heap.

STATEMENT_2 above declares array b and assigns to it the same memory location that was already stored in array a.

So b is not a copy of a. Rather, both a and b are actually pointing to the same storage location.

This means that the following code:

int a[] = new int[10];  // a uses memory from the heap
int b[] = a;            // b uses the same memory that a uses.

a[0] = 10;
System.out.println(b[10]);
will result in the number 10 being printed.

If what you really want is a separate copy, then you need to allocate two different arrays, and copy the values from one into the other. For example, the following code:

// CREATE A NEW ARRAY a AND ASSIGN SOME VALUES TO IT:

int a[] = new int[10];

for (int i = 0 ; i < 10 ; i++)
   a[i] = i * i;

// CREATE A NEW ARRAY c AND COPY VALUES FROM a TO c

int c[] = new int[10];

for (int i = 0 ; i < 10 ; i++)
   c[i] = a[i];

// NOW ASSIGN A DIFFERENT VALUE TO a[5]:

a[5] = 1000;

System.out.println(a[5] + " " + c[5]);
will print out the numbers 1000 and 25. Since a and c are pointing to two different places in the heap, changing a value in a does not affect c.

Notice in the above example how useful it is to combine arrays and for loops. This is something people do a lot in programming.

To make this easier, Java lets you say NAME.length to find the length (number of elements) of an array. For example, the two loops below act in the same way:

int a[] = new int[10];

for (int i = 0 ; i < 10 ; i++)
   a[i] = i * i;

for (int i = 0 ; i < a.length ; i++)
   a[i] = i * i;
It's a good idea to use the NAME.length construct, because then you don't need to remember the length of an array, and if you change the length of the array later, it won't cause problems.

The elements of an array can be of any time -- even an array. This is how Java lets you have multiple dimension arrays. For example, the following statements are all equivalent ways of declaring a two dimensional array of doubles:

double foo1[][];  // foo1 is a two dimensional array.  Each element is a double.
double[] foo2[];  // foo2 is an array.  Each element is an array of double.
double[][] foo3;  // foo3 is the name of a two dimensional array of double.
Although the above three statements look different, the three declared arrays are actually of exactly the same type.

When thinking about arrays with more than one dimension, it's useful to remember that an array is just a pointer into memory. So an array of arrays is just an array of pointers into memory.

For example, the following statement does several things:

int foo[][] = new int[3][5];
The figure below shows this:

Here is some code we wrote in class, which shows a number of these ideas:

public class arrays2
{
   public static void main(String args[]) {

      String[] digitNames = { "zero","one","two","three","four","five","six","seven","eight","nine" };

      int a[] = new int[10];
      a[0] = 20;
      a[5] = 40;

      System.out.println("The length of array a is " + a.length);
      System.out.println();
      for (int i = 0 ; i < a.length ; i++)
         System.out.println("Element " + digitNames[i] + " of a is " + a[i]);
      System.out.println();


      double values[] = new double[6];
      values[5] = 3.14159;

      System.out.println();
      System.out.println("My values are:");
      for (int i = 0 ; i < values.length ; i++)
         System.out.println(values[i]);
      System.out.println();


      String names[] = { "Bob" , "Carol" , "Ted" , "Alice" };

      boolean doILikeThisPerson[] = { false , true , true, false};

      System.out.println();
      System.out.println("Who I like:");
      System.out.println();

      for (int i = 0 ; i < doILikeThisPerson.length ; i++)
         if (doILikeThisPerson[i])
            System.out.println("I like " + names[i]);
         else
            System.out.println("I do not like " + names[i]);

      System.out.println();
   }
}
This is the last example code we wrote in class, showing a triple dimensional array:
public class arrays3
{
   public static void main(String args[]) {
       int product[][][] = new int[100][100][100];
       for (int i = 0 ; i < product.length ; i++)
        for (int j = 0 ; j < product[i].length ; j++)
           for (int k = 0 ; k < product[i][j].length ; k++)
              product[i][j][k] = i * j * k;

       System.out.println( (product[34][45][56] + product[71][82][93]) );
    }
}


Wednesday, September 28

Methods are Java's name for what some other programming languages call functions or procedures. Next week we will learn about objects. Until then, all methods have to be declared static. The below is a simple example of defining and calling a method:

public static void main(String[] args) {
   myFirstMethod();
}

static void myFirstMethod() {
   System.out.println("This is my first method in Java.  Oh Boy!!!");
}
There are several things to notice in the above code: Methods can also have one or more arguments. WHen you call a method, the arguments you pass into it must have the same types as the arguments declared in the method definition. Here is a simple example:
public static void main(String[] args) {
   tellingAgeMethod("Fred", 27);
}

static void tellingAgeMethod(String name, int age) {
   System.out.println(name + "'s age is " + age);
}
Very often, methods do so useful work, and then return some value. Methods that have the same name but different numbers or types of arguments are actually different methods.

For example, the code below has two different methods both named "minimum". The compiler is able to tell that they are two different methods because one has two arguments and the other has three arguments:

Notice that if a method is not void, then it must contain one or more return statements. Each return statement must return a value, and eEvery possible path of execution of the method must reach a return statement:

public static void main(String args[]) {
int foo = 20;
int bar = 17;
int rho = 15;

System.out.println("The minimum of " + foo + " and " + bar + " is " + lo);
System.out.println("The minimum of " + foo + "," + bar + "," + rho + " is " + minimum(foo,bar,rho));
}

static int minimum(int a, int b) {
if (a < b)
   return a;
else
   return b;
}

static int minimum(int a, int b, int c) {
if (a < b && a < c)
   return a;
else if (b < c && b < a)
   return b;
else
   return c;
}
You can also pass arrays as arguments into methods. This is a way to pass lots of values into a method at the same time.
public static void main(String args[]) {
int myNumbers[] = { 314, 159, 265, -357, 897 };

System.out.println("The minimum of myNumbers is " + minimum(myNumbers));
}

static int minimum(int[] a) {
   int smallest = a[0];
   for (int n = 0 ; n < a.length ; n++)
      if (a[n] < smallest)
         smallest = a[n];
   return smallest;
}
Because an array is just a pointer into memory, when you "pass an array" as an argument into a method you are really just passing the memory address of where the array's values are stored in the heap. This means that a method can modify the values in the array, as shown in the following example:
public static void main(String args[]) {

   int arr1[] = new int[10];
   fillArray(arr1, 0, 5, 20);
   fillArray(arr1, 5,10, 30);
   for (int i = 0 ; i < arr1.length ; i++)
      System.out.println(i + " " + arr1[i]);
}

static void fillArray(int arr[], int lo, int hi, int value) {
   for (int i = lo ; i < hi ; i++)
     arr[i] = value;
}
In class we showed several other examples of using methods, such as this example of using a method to sum up all the numbers within a range of numbers, and return the result.
public static void main(String args[]) {
   System.out.println("The sum of the first 100 number is " + sumBetween(1, 100));
}

static int sumBetween(int lo, int hi) {
   int sum = 0;
   for (int i = lo ; i <= hi ; i++)
      sum += i;
   return sum;
   }
Finally, we showed how you can use methods to allow code to be executed in different order. In the example below, the first two calls to the method are funny, but the last two calls are not funny.

Note the use of the return statement in the middle of the method, which allows execution to return immediately to the calling method:

public class NeutrinoJokes
{
   public static void main(String args[]) {

      printFunnyStatement(2);  // This is funny
      printFunnyStatement(1);

      println();

      printFunnyStatement(1);  // This is not funny
      printFunnyStatement(2);
   }

   static void printFunnyStatement(int n) {
      switch (n) {
      case 1:
         System.out.println("Two neutrinos walk into a bar.");
         return;

      case 2:
         System.out.println("The bartender says 'We don't serve neutrinos here.'");
         return;
      }
   }
}
Your Homework:

Your homework, which is due before class on Wednesday, October 5, is to write a program that makes use of methods. Your program should contain one or more methods that take one or more arguments and do some computation, and at least one method that returns a result.

Show that you can call the same method with different arguments to get different results.

Ideally, I'd like you to be able to show the use of conditional statements inside your method. That is, depending on what argument values are passed into the method, it executes different code paths.

As usual, I'd like you to be creative, and to draw on your own interests. Think about things you'd like to do that have a particular structure, but that can have different values, such as cooking recipes, algebraic formulas, MadLibs, poetry, or musical melodies and harmonies.


Monday, October 3

Our first lecture about objects in Java. An object is basically a way to create abstraction, by putting data and the methods that work on that data all in one place. People who use objects need only worry about what they actually do, not the innards of how they work.

Abstraction makes programs much easier to write and to maintain, and makes it much easier for different people to work together, especially as programming projects get very large, and involve many different people.

The example of creating a new class of objects that we went over in class was Complex numbers -- a type that is not built into Java itself, but which can be quite useful. The Java class below, in a file called Complex.java, shows how data and methods are both located inside an object.

Note how we use "getter" methods, like getReal() and getImag(), to allow access to the values of these variables. Providing this extra level of indirection means that in the future we will still have the option to change how we store this data inside the Complex class, without anybody needing to change the way they use it.

public class Complex
{
   private double real, imag;

   public Complex() {
   }

   public Complex(double r, double i) {
      real = r;
      imag = i;
   }

   public double getReal() {
      return real;
   }

   public double getImag() {
      return imag;
   }

   public String toString() {
      return "(" + real + "," + imag + ")";
   }

   public void copy(Complex c) {
      if (c != null) {
         real = c.real;
         imag = c.imag;
      }
      else {
         real = 0;
         imag = 0;
      }
   }

   public void add(Complex c) {
      if (c != null) {
         real += c.real;
         imag += c.imag;
      }
   }

   public void multiply(Complex c) {
      if (c != null) {
         double r = real;
         double i = imag;

         real = r * c.real - i * c.imag;
         imag = r * c.imag + i * c.real;
      }
      else {
         real = 0;
         imag = 0;
      }
   }
}

What makes objects really interesting is that they can be instantiated. Every time you create an object instance using the new operator, you allocate an object instance from the Heap (the same place from which you get memory for arrays).

Unless data is declared to be static, a new copy of that data is created with every object instance. For example, real and imag are not static variables. Therefore, every different Complex object instance will contain a different value for these variables.

The code, below, creates two instances of Complex, and tests out their methods:

public class objex1
{
   public static void main(String args[]) {
      Complex c1 = new Complex(2, 3.5);

      Complex c2 = new Complex(4, 7.5);

      System.out.println();
      System.out.println("old c1,c2 = " + c1 + " " + c2);
      System.out.println();

      c1.add(c2);

      System.out.println("new c1,c2 = " + c1 + " " + c2);
      System.out.println();

      c1.multiply(c2);

      System.out.println("newest c1,c2 = " + c1 + " " + c2);
      System.out.println();

   }
}


Wednesday, October 5

We continue our discussion of objects by talking about object inheritance. For example, here is an object class called Shape:

public class Shape
{
   public Shape() {
   }
   public Shape(double width, double height) {
      this.width = width;
      this.height = height;
   }
   public String toString() {
      return "Shape{width=" + width + ",height=" + height + "}";
   }
   public double area() {
      return width * height;
   }
   public double perimeter() {
      return 0;
   }
   protected double width, height;
}
We can think of this as a base class, or all-encompassing super class, which we can extend to create classes of objects that have more specific functioning. Here are some examples. Note the use of the keyword super to refer to the superclass (which in this case is Shape):

public class Rectangle extends Shape
{
   public Rectangle() {
      super();
   }
   public Rectangle(double width, double height) {
      super(width, height);
   }
   public String toString() {
      return "Rectangle{width=" + width + ",height=" + height + "}";
   }
   public double area() {
     return width * height;
   }
   public double perimeter() {
     return width + height + width + height;
   }
}

public class RightTriangle extends Shape
{
   public RightTriangle() {
      super();
   }
   public RightTriangle(double width, double height) {
      super(width, height);
   }
   public String toString() {
      return "RightTriangle{width=" + width + ",height=" + height + "}";
   }
   public double area() {
      return width * height / 2;
   }
   public double perimeter() {
      return width + height + Math.sqrt(width * width + height * height);
   }
}

public class Oval extends Shape
{
   public Oval() {
      super();
   }
   public Oval(double width, double height) {
      super(width, height);
   }
   public String toString() {
      return "Oval{width=" + width + ",height=" + height + "}";
   }
   public double area() {
      return width * height * Math.PI / 4;
   }
   CHALLENGE: CAN YOU FIGURE OUT HOW TO IMPLEMENT A perimeter() METHOD?
}
In class we tested out these object classes with the following example code:
public class objex2
{
   public static void main(String[] args) {
      Shape myShape = new Shape(3.0, 4.0);
      Rectangle myRectangle = new Rectangle(3.0, 4.0);
      RightTriangle myTriangle = new RightTriangle(3.0, 4.0);
      Oval myOval = new Oval(3.0, 4.0);

      System.out.println(myShape + " " + myShape.area() + " " + myShape.perimeter());
      System.out.println();

      System.out.println(myRectangle + " " + myRectangle.area() + " " + myRectangle.perimeter());
      System.out.println();

      System.out.println(myTriangle + " " + myTriangle.area() + " " + myTriangle.perimeter());
      System.out.println();

      System.out.println(myOval + " " + myOval.area() + " " + myOval.perimeter());
      System.out.println();
   }
}
HOMEWORK, DUE WEDNESDAY OCTOBER 12 (which will count as your midterm):

This homework assignment asks you to use together all of the concepts we've covered so far, including primitive types (int, boolean, double), Strings, conditionals, arrays, methods, objects and object inheritance.

First, observe the following code: Note that we are creating an array of Shape, and populating this array with different kinds of shapes -- Rectangle, RightTriangle and Oval.

public static void main(String[] args) {
   Shape myShapes[] = new Shape[3];

   myShapes[0] = new Rectangle(20, 20);
   myShapes[1] = new RightTriangle(20, 20);
   myShapes[2] = new Oval(20, 20);

   for (int i = 0 ; i < myShapes.length ; i++)
   System.out.println(myShapes[i].area());
}

When we run this program, each object will run the correct method, and the folllowing three values will be printed for area():

400.0
200.0
314.1592653589793

Think about what's going on here. The myShapes[] array does not know that its elements are different types. After all, the array itself is of type Shape[]. But each element keeps track of its own type, so when we run a method of any of those array elements, the correct method is invoked.

Your assignment is to write a computer program that incorporates Strings, conditionals, arrays, methods, objects object inheritance, and arrays of objects, in an interesting and fun way. Feel free to reuse ideas from one of your previous assignments if you'd like.

I've really enjoyed the creativity that people have shown in their assignments so far. Again, feel free to draw on your own interests, whether cooking recipes, algebraic formulas, MadLibs, poetry, history, or music.

In this assignment, I'd like you to create at least two different object classes, one of which should be an extension of the other. Your program should contain at least one array of objects, where all of the objects in the array are extended from the same super-class (as in the example I showed above).

Here is an example (don't actually write this program -- it's just an example You are throwing a party, you've asked your friends to please bring cash instead of presents (a useful technique for avoiding overcrowded parties).

You want to keep track of how much money your party makes for you. You write a program that contains an array of names of people you expect to show up. The base class can be Person, and the extended classes can be Guy and Gal.

Within each Person class, you implement a method to tell you how much money that person gave you, and another method to tell you what gender that person is.

You write a program that answers questions like: "Who gave me the most money?", or "Which guy gave me the least money?"

Ok, I didn't say it was a good example, but it gives you the idea of a program that uses Strings, conditionals, arrays, methods, objects object inheritance, and arrays of objects.

I'm sure your program will be far more interesting and fun. :-)


Wednesday, October 12

In this lecture we introduced Java Applets, which allow you to create interactive graphics in a web browser. In Eclipse, you should create a new project, and give it a source file that starts out something like this:

import java.awt.*;

public class MyApplet extends BufferedApplet {
   public MyApplet() {
   }

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      // DRAWING COMMANDS GO HERE
   }
}
In the following paragraphs, I'm going to keep calling this project "MyApplet", but you will probably want to actually name it something else, to reflect what your applet really does. So everywhere you see "MyApplet" below, you should replace it with the real name for your project.

In order to compile and run your applet class, you will need to download my "helper class" BufferedApplet.java to your computer, and drag that file into the same (default package) where Eclipse is showing your MyApplet.java.

Eclipse sets a default resolution for your applet of 200×200. In order to change the resolution, click on the word Run along the top. You will then see a list of menu items. Select the menu item Run Configurations.... In the pop-up window that appears, click on the Parameters tab. You will then see options to set Width and Height.

You can debug your homework within Eclipse, but in order to show your work on the Web, which you will need to do for next Wednesday, you will need an html file that contains an applet tag. Let's suppose you called the project MyApplet. In the Eclipse workspace folder youyou will find the sub-folder workspace/MyApplet/. In that folder you should place a file called index.html that contains something like the following:

<applet codebase=bin code=MyApplet width=640 height=480>
</applet>

Then you should upload the entire MyApplet folder onto your class page, so that there is a folder called MyApplet which sits in the same folder where your main class index.html is.

In order to allow people to find and run this java applet, you will need to link to this page from your main class page. To do that you put a line something like this into your main index.html:

<a href=MyApplet>Click here to run my applet</a>

Here is the source code for the applet we developed in class, with that nice picture of a cube:


import java.awt.*;

public class Applet2 extends BufferedApplet {

   Font myFont = new Font("Helvetica", Font.BOLD | Font.ITALIC, 60);
   
   public Applet2() {
   }

   int[] X = { 200-40, 300-40, 300, 200 }; // X-COORDS OF THE POLYGON
   int[] Y = { 200-40, 200-40, 200, 200 }; // Y-COORDS OF THE POLYGON

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      // BACKGROUND
      
      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      // TOP OF THE CUBE

      g.setColor(Color.black);
      g.fillPolygon(X, Y, 4);

      // FRONT OF THE CUBE

      g.setColor(Color.gray);
      g.fillRect(200, 200, 100, 100);

      // MAKE A NICE TEXT LABEL

      g.setColor(Color.blue);
      g.setFont(myFont);
      g.drawString("This is my cube", 10, 50);
   }

}

HOMEWORK due Wednesday Oct 19 before class:

Your homework will be to create your own cool picture using java.awt.Graphics primitives in an Applet. We showed a few of these in class, including setColor(), fillRect(), fillPolygon(), and drawString().

The most important thing for now is to start to play around with this. An object of class Graphics is the object you draw onto, and that object contains all the cool drawing methods to let you do so. You can find comprensive documentation on the Graphics class here.


Monday, October 17

Here was the first Java applet we developed in class today, which displays the primary (additive) and secondary (subtractive primary) color:

import java.awt.*;

public class MyApplet1 extends BufferedApplet
{
   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setColor(new Color(255, 0, 0, 128)); // RED
      g.fillOval(100, 100, 150, 170);

      g.setColor(new Color(0, 255, 0, 128)); // GREEN
      g.fillOval(200, 100, 150, 170);

      g.setColor(new Color(0, 0, 255, 128)); // BLUE
      g.fillOval(300, 100, 150, 170);


      g.setColor(new Color(0, 255, 255, 128)); // CYAN
      g.fillOval(100, 200, 150, 170);

      g.setColor(new Color(255, 0, 255, 128)); // MAGENTA
      g.fillOval(200, 200, 150, 170);

      g.setColor(new Color(255, 255, 0, 128)); // YELLOW
      g.fillOval(300, 200, 150, 170);

      g.setColor(new Color(0, 0, 0, 128)); // BLACK
      g.fillOval(400, 200, 150, 170);
   }
}
Here is the applet we wrote to visualize which numbers are prime between 1 and 144:
import java.awt.*;

public class MyApplet2 extends BufferedApplet
{
   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      for (int i = 0 ; i < 144 ; i++) {
         int x = 40 + 45 * (i % 12);
         int y = 40 + 45 * (i / 12);

	 g.setColor(isPrime(i + 1) ? Color.pink : Color.cyan);

	 g.fillRoundRect(x, y, 35, 35, 10, 10);
	 g.setColor(Color.black);
	 g.drawString("" + (i + 1), x + 5, y + 22);
	 g.drawRoundRect(x, y, 35, 35, 10, 10);
      }
   }
   
   boolean isPrime(int n) {
      if (n <= 1)
         return false;
      for (int i = 2 ; i < n ; i++)
         if (n % i == 0)
	    return false;
      return true;
   }
}
Here is the first version of the program we developed in class today that makes a thingie bounce around within your applet screen:
import java.awt.*;

public class MyApplet3 extends BufferedApplet
{
   Font myFont = new Font("Helvetica", Font.BOLD, 24);
   int x = 50;
   int y = 50;
   int changeInX = 4;
   int changeInY = 4;
   Color shadowColor = new Color(0, 0, 0, 64);
   Color foregroundColor = new Color(255, 255, 128);

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setColor(Color.pink);
      g.fillRect(100, 50, 200, 300);

      g.setColor(Color.cyan);
      g.fillRect(350, 250, 200, 300);

      drawThingie(g, x, y);

      if (x + 250 >= w)
         changeInX = -4;

      if (x <= 0)
         changeInX = 4;

      if (y + 80 >= h)
         changeInY = -4;

      if (y <= 0)
         changeInY = 4;

      x += changeInX;
      y += changeInY;

      animating = true;
   }

   void drawThingie(Graphics g, int x, int y) {

      g.setColor(shadowColor);
      g.fillRoundRect(x + 10, y + 10, 250, 80, 15, 15);

      g.setColor(foregroundColor);
      g.fillRoundRect(x, y, 250, 80, 15, 15);

      g.setColor(Color.black);
      g.drawRoundRect(x, y, 250, 80, 15, 15);

      g.setFont(myFont);
      g.drawString("This is my third applet!", x + 10, y + 50);

   }
}
Here is the second version of the program we developed in class today that makes thingies bounce around within your applet screen. In this version, we created a Thingie class, and then instanced an entire array full of bouncing Thingies.

This listing contains two files: MyApplet4.java and thingie.java.

Notice that we put the drawing logic and the behavior logic into the Thingie class itself:

import java.awt.*;

public class MyApplet4 extends BufferedApplet
{
   Thingie[] thing = new Thingie[10];
   {
      for (int i = 0 ; i < thing.length ; i++)
         thing[i] = new Thingie(50, 50, 4 + (thing.length - i), 4 + i * 4);
   }

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setColor(Color.pink);
      g.fillRect(100, 50, 200, 300);

      g.setColor(Color.cyan);
      g.fillRect(350, 250, 200, 300);

      for (int i = 0 ; i < thing.length ; i++) {
         thing[i].draw(g);
         thing[i].behavior(0, 0, w, h);
      }

      animating = true;
   }
}



import java.awt.*;

public class Thingie
{
   Font myFont = new Font("Helvetica", Font.BOLD, 24);
   int x, y, changeInX, changeInY;
   Color shadowColor = new Color(0, 0, 0, 64);
   Color foregroundColor = new Color(255, 255, 128);

   public Thingie(int x, int y, int changeInX, int changeInY) {
      this.x = x;
      this.y = y;
      this.changeInX = changeInX;
      this.changeInY = changeInY;
   }

   public void draw(Graphics g) {

      g.setColor(shadowColor);
      g.fillRoundRect(x + 10, y + 10, 250, 80, 15, 15);

      g.setColor(foregroundColor);
      g.fillRoundRect(x, y, 250, 80, 15, 15);

      g.setColor(Color.black);
      g.drawRoundRect(x, y, 250, 80, 15, 15);

      g.setFont(myFont);
      g.drawString("This is my third applet!", x + 10, y + 50);
   }

   public void behavior(int x, int y, int w, int h) {

      if (this.x + 250 >= x + w)
         changeInX = -4;

      if (this.x <= x)
         changeInX = 4;

      if (this.y + 80 >= y + h)
         changeInY = -4;

      if (this.y <= y)
         changeInY = 4;

      this.x += changeInX;
      this.y += changeInY;
   }
}


Wednesday, October 19

Here are detailed instructions, from Jonathan Tompson, about how to load an applet onto your web page.

In class, we wrote several applets, which are listed below. Each of them shows a different aspect of interacting with user input. The first example, InteractiveApplet, shows how to use the mouseX and mouseY variables from my BufferedApplet class to see whether or not the mouse is on top of a particular rectangle.

import java.awt.*;

public class InteractiveApplet extends BufferedApplet
{
   int x0 = 100, y0 = 200, width0 = 200, height0 = 50;
   int x1 = 100, y1 = 100, width1 = 200, height1 = 50;
   Color boringPaleYellow = new Color(255, 255, 200);
   Color vibrantExcitingYellow = new Color(255, 255, 0);

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      boolean isOverRectangle0 = mouseX >= x0 && mouseX < x0 + width0 &&
                                 mouseY >= y0 && mouseY < y0 + height0 ;

      boolean isOverRectangle1 = mouseX >= x1 && mouseX < x1 + width1 &&
                                 mouseY >= y1 && mouseY < y1 + height1 ;

      g.setColor(isOverRectangle0 ? vibrantExcitingYellow : boringPaleYellow);
      g.fillRect(x0, y0, width0, height0);
      g.setColor(isOverRectangle0 ? Color.red : Color.black);
      g.drawRect(x0, y0, width0, height0);

      g.setColor(isOverRectangle1 ? vibrantExcitingYellow : boringPaleYellow);
      g.fillRect(x1, y1, width1, height1);
      g.setColor(isOverRectangle1 ? Color.red : Color.black);
      g.drawRect(x1, y1, width1, height1);

      animating = true;
   }
}
The second applet, InteractiveApplet2, shows how to create a separate class, which we call MyRectangle, making an array of those rectangles. This greatly simplifies the applet logic.

This applet also shows how to use my

keyDown[]
and
wasKeyDown[]
arrays to detect keyboard events. In particular, we detect the 'a' key being held down, using the logic:
      if (keyDown['a'])
	 ...
and detect whether the 'a' key has just lifted up after being clicked, using the logic:
      if (wasKeyDown['a'] && ! keyDown['a'])
	 ...
import java.awt.*;

public class InteractiveApplet2 extends BufferedApplet
{
   Font myFont = new Font("Helvetica", Font.BOLD, 24);

   MyRectangle mr[] = new MyRectangle[10];
   {
      for (int n = 0 ; n < mr.length ; n++)
         mr[n] = new MyRectangle(55 + 55 * n, 100, 50, 200);
   }

   int activeButton = -1;

   int bgState = 0;
   Color bgColor[] = { Color.white, Color.pink };

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(bgColor[bgState]);
      g.fillRect(0, 0, w, h);

      boolean clickedDown = ! wasMouseDown && mouseDown;
      boolean clickedUp = wasMouseDown && ! mouseDown;

      if (clickedDown)
         activeButton = -1;

      String text = "Key is up!!!";
      if (keyDown['a'])
         text = "Key a is down!!!";

      // WHEN KEY a GOES UP, CYCLE THROUGH BG COLORS

      if (wasKeyDown['a'] && ! keyDown['a'])
         bgState = (bgState + 1) % bgColor.length;

      g.setColor(Color.black);
      g.setFont(myFont);
      g.drawString(text, 5, 30);

      for (int n = 0 ; n < mr.length ; n++) {
         boolean isOverMe = mr[n].draw(g, mouseX, mouseY, clickedUp && n == activeButton);
	 if (clickedDown && isOverMe)
	    activeButton = n;
      }

      animating = true;
   }
}

Here is the actual MyRectangle
class used by the above applet.

import java.awt.*; public class MyRectangle { int x = 100, y = 200, width = 200, height = 50; int state = 0; Color[] boringPale = { new Color(255, 255, 200), // boring yellow new Color(200, 200, 255), // boring blue }; Color[] vibrantExciting = { new Color(255, 255, 0), // exciting yellow new Color(100, 100, 255), // exciting blue }; public MyRectangle(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } public boolean draw(Graphics g, int mouseX, int mouseY, boolean clickedUp) { boolean isOverRectangle = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height ; if (isOverRectangle && clickedUp) state = (state + 1) % boringPale.length; g.setColor(isOverRectangle ? vibrantExciting[state] : boringPale[state]); g.fillRect(x, y, width, height); g.setColor(isOverRectangle ? Color.red : Color.black); g.drawRect(x, y, width, height); return isOverRectangle; } }
Your Homework, which is due next Wednesday before class:

Your homework for next Wednesday is to write an applet (it could be a variation on the one you already wrote for the previous assignment) that incorporates mouse and keyboard events from the user. As usual, try to have fun, use your imagination, pick a topic that interests or inspires you as the theme/goal of your program.


Monday, October 24

/*----------------------------------------------------------
   This is the first applet we implemented on Monday
   October 24.  It just shows two different pale
   yellow rectangles, and how you can move your
   mouse to hover over either of them to make that
   rectangle turn bright yellow.
*/

import java.awt.*;

public class InteractiveApplet1 extends BufferedApplet
{
   int x0 = 100, y0 = 200, width0 = 200, height0 = 50;
   int x1 = 100, y1 = 100, width1 = 200, height1 = 50;
   Color boringPaleYellow = new Color(255, 255, 200);
   Color vibrantExcitingYellow = new Color(255, 255, 0);

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      boolean isOverRectangle0 = mouseX >= x0 && mouseX < x0 + width0 &&
                                 mouseY >= y0 && mouseY < y0 + height0 ;

      boolean isOverRectangle1 = mouseX >= x1 && mouseX < x1 + width1 &&
                                 mouseY >= y1 && mouseY < y1 + height1 ;

      g.setColor(isOverRectangle0 ? vibrantExcitingYellow : boringPaleYellow);
      g.fillRect(x0, y0, width0, height0);
      g.setColor(isOverRectangle0 ? Color.red : Color.black);
      g.drawRect(x0, y0, width0, height0);

      g.setColor(isOverRectangle1 ? vibrantExcitingYellow : boringPaleYellow);
      g.fillRect(x1, y1, width1, height1);
      g.setColor(isOverRectangle1 ? Color.red : Color.black);
      g.drawRect(x1, y1, width1, height1);

      animating = true;
   }
}

/*----------------------------------------------------------
   This shows a first version of how we can make a
   "smarter" rectangle, by creating a new object
   class MyRectangle.  When you click on a rectangle,
   that rectangle toggles color between yellow and
   blue.

   Notice the code right after the statement that
   starts "MyRectangle mr[] = ...".  Putting code
   in curly braces, outside of any method, is a
   way of initializing things at the time that
   an object is instantiated.  In this case, the
   object that has just been instantiated is the
   applet itself, InteractiveApplet1, and we are
   are using that code between curly braces to
   instantiate the elements of the mr[] array.
   
   The applet keeps track of which rectangle you
   clicked down on.  Only the rectangle that you
   click down on is allowed to change color, and
   then only if your "click-up" is also on that
   same rectangle.  Dragging your mouse on or
   off or between rectangles does not result
   in any color change.

   In this version the logic for this is partly
   in the applet itself and partly in the rectangle
   logic.  This places too much of a burden on
   the applet to keep track of things.  In Wednesday's
   class we will show how to make truly smart
   interactive objects that contain all of the
   information about whether you had clicked down
   on that object.

   This applet also shows some keyboard logic.  When
   you click up on the 'a' key, the background
   changes color, and a large text message changes.
   So it's also an example of how to display text
   in large sizes.
*/

import java.awt.*;

public class InteractiveApplet2 extends BufferedApplet
{
   Font myFont = new Font("Helvetica", Font.BOLD, 24);

   MyRectangle mr[] = new MyRectangle[10];
   {
      for (int n = 0 ; n < mr.length ; n++)
         mr[n] = new MyRectangle(55 + 55 * n, 100, 50, 200);
   }

   int activeButton = -1;

   int bgState = 0;
   Color bgColor[] = { Color.white, Color.pink };

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(bgColor[bgState]);
      g.fillRect(0, 0, w, h);

      boolean clickedDown = ! wasMouseDown && mouseDown;
      boolean clickedUp = wasMouseDown && ! mouseDown;

      if (clickedDown)
         activeButton = -1;

      String text = "Key is up!!!";
      if (keyDown['a'])
         text = "Key a is down!!!";

      // WHEN KEY a GOES UP, CYCLE THROUGH BG COLORS

      if (wasKeyDown['a'] && ! keyDown['a'])
         bgState = (bgState + 1) % bgColor.length;

      g.setColor(Color.black);
      g.setFont(myFont);
      g.drawString(text, 5, 30);

      for (int n = 0 ; n < mr.length ; n++) {
         boolean isOverMe = mr[n].draw(g, mouseX, mouseY, clickedUp && n == activeButton);
	 if (clickedDown && isOverMe)
	    activeButton = n;
      }

      animating = true;
   }
}

/*----------------------------------------------------------
   MyRectangle is a very naive implementation of a graphical
   object that tries to be responsive to mouse events.  On
   Wednesday we are going to be more careful in constructing
   such graphical objects, but this is good enough for now.
*/

import java.awt.*;

public class MyRectangle
{
   int x = 100, y = 200, width = 200, height = 50;

   int state = 0;

   Color[] boringPale = {
      new Color(255, 255, 200), // boring yellow
      new Color(200, 200, 255), // boring blue
   };
   Color[] vibrantExciting = {
      new Color(255, 255,   0), // exciting yellow
      new Color(100, 100, 255), // exciting blue
   };

   public MyRectangle(int x, int y, int width, int height) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
   }

   public boolean draw(Graphics g, int mouseX, int mouseY, boolean clickedUp) {

      boolean isOverRectangle = mouseX >= x && mouseX < x + width &&
                                mouseY >= y && mouseY < y + height ;

      if (isOverRectangle && clickedUp)
         state = (state + 1) % boringPale.length;

      g.setColor(isOverRectangle ? vibrantExciting[state] : boringPale[state]);
      g.fillRect(x, y, width, height);
      g.setColor(isOverRectangle ? Color.red : Color.black);
      g.drawRect(x, y, width, height);

      return isOverRectangle;
   }
}

/*----------------------------------------------------------
   This applet modifies the previous one to allow you to
   click down and up on any key on the keyboard.  The text
   message shows which key(s) you are pressing down.

   The first version below (commented out) only detected
   one key.  The final version of this applet tries to
   detect all the keys you are pressing.  In reality,
   this can't detect all possible key combinations, due to
   hardware limitations on the actual computer keyboard.

   Important things here are the use of the length() method
   on a String to see long that String is, and also the
   use of the charAt(int n) method to find the identity
   of the single character at location n in a String.
*/

import java.awt.*;

public class InteractiveApplet3 extends BufferedApplet
{
   int fontHeight = 40;
   Font myFont = new Font("Helvetica", Font.BOLD, fontHeight);

   MyRectangle mr[] = new MyRectangle[10];
   {
      for (int n = 0 ; n < mr.length ; n++)
         mr[n] = new MyRectangle(55 + 55 * n, 100, 50, 200);
   }

   int activeButton = -1;

   int bgState = 0;
   Color bgColor[] = { Color.white, Color.pink };

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      g.setColor(bgColor[bgState]);
      g.fillRect(0, 0, w, h);

      boolean clickedDown = ! wasMouseDown && mouseDown;
      boolean clickedUp = wasMouseDown && ! mouseDown;

      if (clickedDown)
         activeButton = -1;

      String text = "All keys are up!!!";

      // VERSION ONE -- FIRST KEY DETECTED ONLY
/*
      for (int key = 0 ; key < keyDown.length ; key++)
         if (keyDown[key]) {
            text = "Key '" + (char)key + "' is down!!!";
	    break;
         }
*/
      // VERSION TWO -- ALL KEYS DETECTED

      String keysDown = "";
      for (int key = ' ' ; key < 128 ; key++)
         if (keyDown[key])
	    keysDown += (char)key;

      if (keysDown.length() > 1)
         text = "Keys '" + keysDown + "' are down!!!";
      else if (keysDown.length() > 0)
         text = "Key '" + keysDown + "' is down!!!";

      // WHEN KEY a GOES UP, CYCLE THROUGH BG COLORS
/*
      if (wasKeyDown['a'] && ! keyDown['a'])
         bgState = (bgState + 1) % bgColor.length;
*/
      g.setColor(Color.black);
      g.setFont(myFont);
      g.drawString(text, 5, fontHeight);

      for (int n = 0 ; n < mr.length ; n++) {
         boolean isOverMe = mr[n].draw(g, mouseX, mouseY, clickedUp && n == activeButton);
	 if (clickedDown && isOverMe)
	    activeButton = n;
      }

      animating = true;
   }
}

/*----------------------------------------------------------
   As we played in class with the previous applet, the question
   came up of what English words contain only unique letters
   in alphabetical order.  So we made an applet to look into
   this.  I found a list on-line of the 852 words of Basic
   English, and turned this list into a java class
   Words.java.

   InteractiveApplet4 displays all of these words.  We use
   interactiveapplet4.html as the html file,
   so that the applet will display at high resolution --
   1440 × 830 pixels.

   As the user clicks on keys 'a' through 'z', the applet
   highlights words of different lengths, where 'a'=0, 'b'=1,
   'c'=2, etc.  We also display the number of words of
   the chosen length.  Note how we are able to superimpose
   this information without any visual interference, by
   making the text very large and a light color (pink).

   Also, we draw a rectangle around all words where all
   the letters are in alphabetical order.  In class we
   showed how to implement a boolean method called
   inAlphabeticalOrder(String word) to compute this,
   and it turned out to be surprisingly easy.
*/

import java.awt.*;

public class InteractiveApplet4 extends BufferedApplet
{
   Words wordlist = new Words();

   int largeFontHeight = 60;
   int smallFontHeight = 12;

   Font largeFont = new Font("Helvetica", Font.BOLD, largeFontHeight);
   Font smallFont = new Font("Helvetica", Font.BOLD, smallFontHeight);

   int letterCount = 0;

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();

      for (int n = 'a' ; n <= 'z' ; n++)
      if (wasKeyDown[n] && ! keyDown[n]) {
         letterCount = n - 'a';
	 break;
      }

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setFont(largeFont);
      g.setColor(Color.pink);
      g.drawString("letter count is " + letterCount, 10, 50);

      g.setFont(smallFont);

      int colWidth = 7 * smallFontHeight;
      int rowHeight = smallFontHeight;

      int nRows = h / smallFontHeight;

      int n = 0;
      for (int col = 0 ; col < 30 ; col++)
         for (int row = 0 ; row < nRows ; row++) {
            if (n < wordlist.size()) {
               g.setColor(wordlist.word(n).length() == letterCount ? Color.red : Color.black);
	       int x = 5 + col * colWidth;
	       int y = smallFontHeight + row * rowHeight;
	       g.drawString(wordlist.word(n), x, y);
	       if (isInAlphabeticalOrder(wordlist.word(n)))
	          g.drawRect(x, y - smallFontHeight, colWidth - 10, smallFontHeight);
            }
	    n++;
         }
   }

   boolean isInAlphabeticalOrder(String word) {
      int chMax = 0;
      for (int i = 0 ; i < word.length() ; i++) {
         int ch = word.charAt(i);
	 if (ch <= chMax)
	    return false;
         chMax = ch;
      }
      return true;
   }
}


Wednesday, October 26

At the start of this class I showed a simple way to create audio sounds. The example applet I showed to do this, together with all of the source code, is at http://mrl.nyu.edu/~perlin/audio-example/.

Also, if you want to get the actual time on the clock, you can call this method in the System class:

   System.currentTimeMillis()
This returns the time in milliseconds. I generally like to get the time in seconds, so what I usually do is something like this:
   double time = System.currentTimeMillis() / 1000.0;
You might want to use this to figure out how much time has elapsed since your applet started running. The key to doing that is to check the time when the applet starts running, and then keep taking the difference between that initial time and the current time.

Here is some sample code to give you the general idea:

import java.awt.*;

public class MyApplet extends BufferedApplet
{
   double startTime = System.currentTimeMillis() / 1000.0;
   ...
   public void render(Graphics g) {
      ...
      double time = System.currentTimeMillis() / 1000.0 - startTime;
      ...
   }
   ...
}

Following are the various java classes we implemented in class on Wednesday October 26.



/*------------------------------------------------------
 This is the version of a rectangle java class that we
 created during class on Wednesday October 26.  We
 didn't actually use this version in the following
 examples.  Instead we used the Rectangle java class
 that comes with the java.awt library.
*/

public class MyRectangle
{
   int x, y, width, height;

   public MyRectangle(int x, int y, int width, int height) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
   }

   // BOOLEAN METHOD SAYING WHETHER THIS PIXEL IS IN THE RECTANGLE

   public boolean contains(int x, int y) {
      return x >= this.x && x < this.x + width &&
             y >= this.y && x < this.y + height;
   }
}

/*------------------------------------------------------
   Here is a simple applet we created to show how
   the contains() method of a Rectangle can be used
   to see whether a mouse has clicked inside
   an instance of a Rectangle.

   In this case, the variable "drawColor" is
   toggled between red and black, which changes
   the color of the displayed rectangle.
*/

import java.awt.*;

public class TestSliders1 extends BufferedApplet
{
   Rectangle mr1 = new Rectangle(100, 100, 120, 80);
   Color drawColor = Color.black;

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();
      
      // TOGGLE THE DRAW COLOR

      if (wasMouseDown && ! mouseDown) // MOUSE UP ACTION
         if (mr1.contains(mouseX, mouseY))
            if (drawColor == Color.black)
               drawColor = Color.red;
            else
               drawColor = Color.black;

      // DRAW EVERYTHING

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setColor(drawColor);
      g.drawRect(mr1.x, mr1.y, mr1.width, mr1.height);
   }
}

/*------------------------------------------------------
   This is a Widget base-class that we implemented
   in class on Wednesday October 26.  Note how it
   extends the java class java.awt.Rectangle.  This
   class handles basic functionality like a default
   display capability and the ability to get input
   focus (by setting the boolean variable haveFocus)
   when the mouse clicks down inside the Widget
   instance.
   
   Note how this java class has public methods for
   mouseDown(x,y), mouseDrag(x,y) and mouseUp(x,y).
   The client program can call the methods to tell
   the Widget what the user is doing.  As the
   Widget class is extended in various ways to
   make different kinds of custom widgets, these
   methods can be overriden to create different
   kinds of behaviors in response to user input.

   In particular, we can extend this java class to
   create the specific functionality ofthe Slider
   class that we then implemented.
*/

import java.awt.*;

public class Widget extends Rectangle
{
   public Widget(int x, int y, int width, int height) {
      super(x, y, width, height);
   }

   public void setColor(Color color) {
      this.color = color;
   }

   public void mouseDown(int x, int y) {
      haveFocus = contains(x, y);
   }

   public void mouseDrag(int x, int y) {
      if (haveFocus) {
        ; // ...
      }
   }

   public void mouseUp(int x, int y) {
      if (haveFocus) {
        ; // ...
        haveFocus = false;
      }
   }

   public void draw(Graphics g) {
      g.setColor(haveFocus ? color.darker() : color);
      g.fillRect(x, y, width, height);

      g.setColor(Color.black);
      g.drawRect(x, y, width, height);
   }

   Color color = Color.white;
   boolean haveFocus = false;
}

/*------------------------------------------------------
   This simple applet just tests out the functionality
   of our Widget base class.  Note how we call the
   mouseDown, mouseDrag and mouseUp methods of
   the Widget instance.

   The Widget's default behavior is to display in
   a darker color when it has input focus.
*/

import java.awt.*;

public class TestSliders2 extends BufferedApplet
{
   Widget w1 = new Widget(100, 100, 120, 80);
   {
      w1.setColor(Color.yellow);
   }

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();
      
      // DRAW EVERYTHING

      if (! wasMouseDown && mouseDown)
         w1.mouseDown(mouseX, mouseY);

      if (wasMouseDown && mouseDown)
         w1.mouseDrag(mouseX, mouseY);

      if (wasMouseDown && ! mouseDown)
         w1.mouseUp(mouseX, mouseY);

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      w1.draw(g);
   }
}

/*------------------------------------------------------
   Here is the implementation of a Slider java class
   that we created during Wednesday's class, by extending
   our Widget class.  Note in particular that is makes
   use of the boolean variable haveFocus, inherited
   from the Widget class, so that the slider will only
   respond if the user starts the action by clicking
   inside the slider.

   Note that the Slider is smart enough to prevent
   its value from getting too small or too large.
   It will still respond to mouse dragging even
   when the mouse moves off of the slider, but the
   Slider's value won't be set outside of its
   allowable range.
*/

import java.awt.*;

public class Slider extends Widget
{
   public Slider(int x, int y, int width, int height) {
      super(x, y, width, height);
   }

   public void setValue(int value) {
      this.value = value;
   }

   public int getValue() {
      return value;
   }

   public void setVertical(boolean tf) {
      isVertical = tf;
   }

   public void mouseDown(int x, int y) {
      super.mouseDown(x, y);
      if (haveFocus)
         value = computeValue(x, y);
   }

   public void mouseDrag(int x, int y) {
      if (haveFocus)
         value = computeValue(x, y);
   }

   public void draw(Graphics g) {
      int r = height / 8;

      super.draw(g);

      // CHANGE THIS TO MAKE A VERTICAL SLIDER

      g.setColor(Color.black);
      g.fillRect(x, y + height / 2 - r / 2, width, r);

      g.setColor(color.brighter());
      g.fillRect(x + value - r, y + height / 2 - 2 * r, 2 * r, 4 * r);
      g.setColor(Color.black);
      g.drawRect(x + value - r, y + height / 2 - 2 * r, 2 * r, 4 * r);
   }

   // CHANGE THIS TO MAKE A VERTICAL SLIDER

   int computeValue(int x, int y) {
      return Math.max(0, Math.min(width - 1, x - this.x));
   }

   private int value = 0;
   boolean isVertical = false;
}

/*------------------------------------------------------
   Here is a java applet we implemented in class to
   show our Slider class in action.  Here we are
   using array of two sliders to adjust, respectively,
   the horizontal and vertical positions of a red disk.

   Notice how much easier it is to write programs
   once you have smart objects doing the heavy
   lifting.  Once we had the Slider object implemented,
   it took less than one minute of class time to
   write the code that lets the two sliders control
   the disk's position.
*/

import java.awt.*;

public class TestSliders3 extends BufferedApplet
{
   Slider sliders[] = {
      new Slider(100, 100, 120, 80),
      new Slider(100, 300, 120, 40),
   };
   {
      for (int n = 0 ; n < sliders.length ; n++)
         sliders[n].setColor(Color.magenta);
   }

   int ballX = 300;
   int ballY = 300;

   public void render(Graphics g) {
      int w = getWidth();
      int h = getHeight();
      
      // DRAW EVERYTHING

      if (! wasMouseDown && mouseDown)
         for (int n = 0 ; n < sliders.length ; n++)
           sliders[n].mouseDown(mouseX, mouseY);

      if (wasMouseDown && mouseDown)
         for (int n = 0 ; n < sliders.length ; n++)
           sliders[n].mouseDrag(mouseX, mouseY);

      if (wasMouseDown && ! mouseDown)
         for (int n = 0 ; n < sliders.length ; n++)
           sliders[n].mouseUp(mouseX, mouseY);

      ballX = 200 + sliders[0].getValue();
      ballY = 200 + sliders[1].getValue();

      g.setColor(Color.white);
      g.fillRect(0, 0, w, h);

      g.setColor(Color.red);
      g.fillOval(ballX - 60, ballY - 60, 120, 120);
      g.setColor(Color.black);
      g.drawOval(ballX - 60, ballY - 60, 120, 120);

      for (int n = 0 ; n < sliders.length ; n++)
         sliders[n].draw(g);
   }
}

HOMEWORK due Wednesday November 2

I'm not asking you to understand any new material beyond what we covered last week. For those of you who are confident, use this week to make your applets even cooler -- feel free to build on the Slider code and other capabilities that I showed in class this week.

For those of you who have been straggling behind, next Wednesday November 2 is your absolute drop dead date to catch up on everything I've assigned so far, including last week's applet assignments and finishing up the midterm.


Monday, October 31

On Monday we started our discussion of interfaces. Interfaces are Java's way of allowing multiple inheritance -- giving objects the ability to inherit properties from more than one ancestor class.

The basic idea of interfaces is that an object implements a sort of contract, by providing an implementation of whatever methods that the interface specifies. In this way, objects that don't actually share a common ancestry of superclasses can be referred to together. For example, they can appear in the same array.

Here is a very simple example:

public interface SaysName
{
   // NOTICE THAT THE METHOD IS DECLARED, BUT NOT IMPLEMENTED.

   public void sayMyName();
}


public class Fred extends Person implements SaysName { public void sayMyName() { System.println("I am Fred."); } }
public class Corvette extends Automobile implements SaysName { public void sayMyName() { System.println("I am a Corvette."); } }
public class test { public static void main(String[] args) { SaysName items[] = { (SaysName)(new Fred()), (SaysName)(new Corvette()), }; for (int n = 0 ; n < items.length ; n++) items[n].sayMyName(); } }
Here is the somewhat more elaborate Halloween themed example we developed in class:

public interface Flashable
{
   public void setFlashing(boolean tf);
}


import java.awt.*; public class TestSliders4 extends BufferedApplet { Slider sliders[] = { new Slider(100, 100, 120, 80), new Slider(100, 300, 120, 40), }; { for (int n = 0 ; n < sliders.length ; n++) sliders[n].setColor(Color.magenta); } EyeBall eyeballs[] = { new EyeBall(200, 300, 40, Color.green.darker()), new EyeBall(200, 200, 60, Color.red), }; Flashable[] things = new Flashable[sliders.length + eyeballs.length]; { int index = 0; for (int n = 0 ; n < sliders.length ; n++) things[index++] = (Flashable) sliders[n]; for (int n = 0 ; n < eyeballs.length ; n++) things[index++] = (Flashable) eyeballs[n]; } double startTime = System.currentTimeMillis() / 1000.0; public void render(Graphics g) { int w = getWidth(); int h = getHeight(); // ELAPSED TIME SINCE THE APPLET STARTED double time = System.currentTimeMillis() / 1000.0 - startTime; int nFlash = (int)(time % things.length); for (int n = 0 ; n < things.length ; n++) things[n].setFlashing(n == nFlash); // DRAW EVERYTHING if (! wasMouseDown && mouseDown) for (int n = 0 ; n < sliders.length ; n++) sliders[n].mouseDown(mouseX, mouseY); if (wasMouseDown && mouseDown) for (int n = 0 ; n < sliders.length ; n++) sliders[n].mouseDrag(mouseX, mouseY); if (wasMouseDown && ! mouseDown) for (int n = 0 ; n < sliders.length ; n++) sliders[n].mouseUp(mouseX, mouseY); for (int n = 0 ; n < eyeballs.length ; n++) { int x = 300 + n * 200; eyeballs[n].setX(x + sliders[0].getValue() / (3 - n)); int y = 100 + n * 20; eyeballs[n].setY(y + sliders[1].getValue() / (3 - n)); } g.setColor(Color.white); g.fillRect(0, 0, w, h); int ghoulX = (eyeballs[0].getX() + eyeballs[1].getX()) / 2; int ghoulY = (eyeballs[0].getY() + eyeballs[1].getY()) / 2; g.setColor(Color.green); g.fillOval(ghoulX - 200, ghoulY - 200, 400, 400); g.setColor(Color.black); g.fillOval(ghoulX - 20 - 10, ghoulY + 65, 20, 20); g.fillOval(ghoulX + 20 - 10, ghoulY + 65, 20, 20); for (int n = 0 ; n < eyeballs.length ; n++) eyeballs[n].draw(g); for (int n = 0 ; n < sliders.length ; n++) sliders[n].draw(g); animating = true; } }
import java.awt.*; public class Slider extends Widget implements Flashable { public Slider(int x, int y, int width, int height) { super(x, y, width, height); } public void setValue(int value) { this.value = value; } public int getValue() { return value; } public void setFlashing(boolean tf) { isFlashing = tf; } public void setVertical(boolean tf) { isVertical = tf; } public void mouseDown(int x, int y) { super.mouseDown(x, y); if (haveFocus) value = computeValue(x, y); } public void mouseDrag(int x, int y) { if (haveFocus) value = computeValue(x, y); } public void draw(Graphics g) { int r = height / 8; // HIGHLIGHT ME IF I AM FLASHING if (isFlashing) { g.setColor(Color.red); g.fillRoundRect(x - 20, y - 20, width + 40, height + 40, 40, 40); } super.draw(g); // CHANGE THIS TO MAKE A VERTICAL SLIDER g.setColor(Color.black); g.fillRect(x, y + height / 2 - r / 2, width, r); g.setColor(color.brighter()); g.fillRect(x + value - r, y + height / 2 - 2 * r, 2 * r, 4 * r); g.setColor(Color.black); g.drawRect(x + value - r, y + height / 2 - 2 * r, 2 * r, 4 * r); } // CHANGE THIS TO MAKE A VERTICAL SLIDER int computeValue(int x, int y) { return Math.max(0, Math.min(width - 1, x - this.x)); } private int value = 0; boolean isVertical = false; boolean isFlashing = false; }
import java.awt.*; public class Widget extends Rectangle { public Widget(int x, int y, int width, int height) { super(x, y, width, height); } public void setColor(Color color) { this.color = color; } public void mouseDown(int x, int y) { haveFocus = contains(x, y); } public void mouseDrag(int x, int y) { if (haveFocus) { ; // ... } } public void mouseUp(int x, int y) { if (haveFocus) { ; // ... haveFocus = false; } } public void draw(Graphics g) { g.setColor(haveFocus ? color.darker() : color); g.fillRect(x, y, width, height); g.setColor(Color.black); g.drawRect(x, y, width, height); } Color color = Color.white; boolean haveFocus = false; }
import java.awt.*; public class EyeBall extends Ball implements Flashable { public EyeBall(int x, int y, int radius) { super(x, y, radius); } public EyeBall(int x, int y, int radius, Color color) { super(x, y, radius); this.color = color; } public void setFlashing(boolean tf) { isFlashing = tf; } double angle = 0; public void draw(Graphics g) { double sin = Math.sin(angle); int wobble = isFlashing ? (int)(sin * radius / 4) : 0; g.setColor(Color.black); g.fillOval(x - radius - 5, y - radius - 5, 2 * radius + 10, 2 * radius + 10); g.setColor(ghoulWhite); g.fillOval(x - radius, y - radius, 2 * radius, 2 * radius); g.setColor(color); g.fillOval(wobble + x - radius / 2, y - radius / 2, radius, radius); g.setColor(Color.black); g.fillOval(wobble + x - radius / 4, y - radius / 4, radius / 2, radius / 2); angle += 0.4; } Color ghoulWhite = new Color(255, 245, 140); boolean isFlashing = false; }


Wednesday, November 2

In this class we began implementing a more ambitious example of using interfaces. In this example, we allow objects of different classes to share the property that they can be sorted. The way we will do this is by having each object implement a compareTo() method. As long as sorting algorithms can call an object's compareTo() method, then that object can be sorted by the algorithm.

HOMEWORK due Wednesday November 9

Your assignment is going to be relatively easy this week. I really want to make sure you understand the concept of interfaces. So rather than implement lots of computer software, I'd like you to (1) write a short essay describing what you might use interfaces for, and then (2) write a interface that specifes one or more methods to express your concept.

Feel free to be creative. The key is to think of what kinds of functionality might be shared by very different objects. In the first example I gave above from Monday's course notes, that shared functionality was being able to say one's own name. In the second example, the one we implemented in class on Monday, it was being able to visually "flash" in some way.

For this assignment your concept can be from any realm of literature, history, science, the visual arts, math, music, human relationships, or any other subject that interests you. See whether you can come up with an interface that contains two or more methods.


Monday, November 7

In Monday's class we finished implementing a demonstration applet ex2.java (which you can run here) of a sorting algorithm MySort.java.

Then in the next version of our applet ex3.java (which you can run here) we modified the class of items to be sorted so that they extended an interface Sortable.java.

This allowed our sorting algorithm to rely only on those methods within the items being sorted which implement the methods of Sortable:

public interface Sortable
{
   public int compareTo(Sortable obj);
   public String getLabel();
}
Then we broke out the items to be sorted into a separate class called Thing1.java. Once we did this, the new version of our applet ex4.java (which you can run here) became very small and easy to read.

To show the power of interfaces, we implemented a completely new kind of object Thing2.java, which also implemented the Sortable interface. This allowed us to easily write another applet ex5.java (which you can run here) which used the same sorting algorithm.


Wednesday, November 9

In Wednesday's class we identified the sort we had been using as an ExchangeSort.java, and we decided to use interfaces to be able to try out different sorting algorithms on the same data sets.

To do this we created an interface Sort.java:

public interface Sort
{
   public void init(Sortable items[]);
   public boolean update();
   public int getI();
   public int getJ();
}
In applets ex6.java (which you can run here) and ex7.java (which you can run here) we reimplemented our two examples from Monday, now using this interface.

This allowed us to try out an alternate sorting algorithm, BubbleSort.java, which also implements the Sort interface.

Applets ex6b.java (which you can run here) and ex7b.java (which you can run here) reimplemented our two examples, using BubbleSort rather than ExchangeSort.

We also modified Thing1.java so that its height varies with the numeric value of its label. This makes it easier to see the sorting algorithms in action.

HOMEWORK due Wednesday, November 16

Your homework for next Wednesday is to implement a Java applet of your own choosing that makes use of interfaces. As usual, try to have fun with it, pick a topic that interests you. Do something that really takes advantage of the flexibility and modularity that interfaces provide.


Monday, November 14

Monday was a guest lecture by Jonathan Tompson, in which he talked about how the Heap manages memory, and different forms of garbage collection. Notes on that lecture will be forthcoming soon.


Wednesday, November 16

In this class we introduced Java's concept of packages, which is a way of organizing code, so that classes that coordinate with each other on some larger task can be placed together. In Eclipse you can create a package using the menu system, and then drag java files into the package folder.

From the command line, to create a package named foobar you would do the following things:

Packages also allow you to selectively hide methods or variables, to protect against deliberate or inadvertent meddling in the inner workings of your code. We discussed the four different levels of access you can use when declaring any method or variable, which can be summarized in the following chart:
private
default
protected
public
Seen by all classes everywhere yes
Seen by classes in this package and classes that extend this class yes yes
Seen by classes in this package yes yes yes
Seen by this class yes yes yes yes
We create a number of examples in class, to show packages in use. You can access that code by downloading
packages1.zip.

Make sure to look at the README.txt file in each subfolder of packages1.

HOMEWORK due Wednesday, November 23

Either by making a new java applet, or by enhancing one you have already written, create an applet that makes use of at least one package of your own creation. The package should contain at least two different java classes.

there should be some logic behind why you put those java classes in a package together, such as "these are all my interactive widgets", or "these are the classes that construct different kinds of cool text messages", or "these classes all do different parts of the physics of my applet", or "these classes all do various kinds of fancy graphics". or "these classes all analyze my word list in different ways".


Monday, November 21

In class on Monday we discussed inner classes and we went through several examples of how to create and use them. The code we wrote during this class can be downloaded from inner-classes.zip.


Wednesday, November 23

Because so many people were already gone for Thanksgiving, Wednesday's class was a review of all the material from the start of the semester.

Since it is the Thanksgiving weekend, and because a number of people are still finishing up their interface java applet assignments, I'm not going to give any new homework this week. Try to catch up on all your assignments.


Monday, November 28

The first lecture about exception handling. We wrote some example programs in class to illustrate the principles of catching exceptions. You can download that source code here.


Wednesday, November 30

We did two sorts of examples in class: (1) A very trivial example to show how to create a hierarchy of exceptions, and then to throw and catch those exceptions; (2) The beginning of an interactive graph drawing applet, which you will be able to use to build your own exception classes.

Our first, trivial example, was in two phases. The first example shows a hierarchy of custom made exception classes, in which each exception object contains no actual methods or data.

The second example shows a variation on the first example, in which we add methods and data to our custom made exception classes.

You should make sure you understand the above two examples, because you will be using them as a guide when you do your assignment.

Your assignment, due next Wednesday, December 7, will consist of two parts: (1) Add some interesting features to the GraphMaker applet; (2) Create and demonstrate the use of a custom Exception hierarchy for the GraphMaker applet.

  1. There was only time in the last thirty minutes of class for me to make a bare-bones implementation of the GraphMaker applet. I'd like you to make some interesting custom changes to the applet. Your changes don't need to be extensive. I'd just like to see that you tried to do something interesting.

    Here are a few ideas for possible improvements you can make to the GraphMaker applet, but feel free to make different changes, if you feel inspired:

    • Move a node
    • Delete an edge
      • requires a method to find an edge, given its two node indices
    • Change a node color
    • Change a node shape
    • Change an edge color
    • Display node indices
    • Add text labels to nodes
    • Allow user to type text on a node to set its text label
    • Allocate new nodes from deleted node slots when possible
    • Make your graph do something. Here are some ideas:
      • propagate colors from one node to another
      • function as a programmable calculator

  2. In addition, I'd like you to think about what sorts of exceptions you would like to catch. In other words, what kinds of gestures can the user try that would be a problem for your applet, and that should be flagged by throwing an exception. Here are some example ideas:

    • Attempt to drag from background
    • Attempt to delete a node that has edges
    • Attempt to drag to off-screen

    Create a simple hierarchy of custom Exception classes. Each of your exceptions should create a clear text message explains what the problem is. That message should be accessible via a getMessage() method which is defined in the Exception class.

    In your applet, display a message string, informing the user about any exceptions you have caught.


Monday and Wednesday, December 5-7

During the two classes this week I implemented the first version of the game that will get you started on your final project. I cleaned it up a bit after Wednesday's class, and you can download the cleaned up version as game.zip.

As you can see, I do not make any use of packages, or inner classes, or Exception handling, or abstract classes, or interfaces, or subclassing (ie: using "extend"), nor permissions declarations such as "private" and "protected".

In other words, I don't make much use of the structural features that Java provides to properly manage software projects.

Your final assignment, which is due Wednesday, December 21, is going to be to build a project based on what I have built (or you can go in another direction instead, if you get permission from me to do so). In your expanded game/animation/art project (whichever direction you want to take it), I expect you to demonstrate that you can incorporate packages, inner classes, throwing and catching Exceptions, abstract classes, interfaces, and subclassing, and can properly use the "private" and "protected" permission declarations.

I will be providing more ideas in the next day or so, but meanwhile I want to get the code up on-line so that you can start to play around with it.

IMPORTANT: Professor Berger will be going over material that will relate to this final project in next week's Monday and Wednesday classes, so I very strongly recommend that you attend those lectures.

here are some suggestions for things you might try in this final project. Obviously many other ideas are possible as well: