| CSCI A201/A597Lecture Notes 19 Spring 2000 |
I am going to give a solution to assignment 7 using top-down design and
procedural abstraction below. We will rely on chapter 4 in your textbook.
Your solution to assignment 7 cannot use procedural abstraction, instead
you should write all the code inside your main method as we
have been doing until now.
This is an example of a top-down design. You can use this to clarify any last minute questions about the assignment but please don't turn the code below as your solution to the assignment as is since it is not going to be accepted.
This also serves as an introduction to assignment 8, to be posted later today (the task is to solve the lab listed as 4.8 in your book, on pages 125 and 126). We will develop our program in stages. The code will reflect the stages, and subsequent refinements to it in later stages will bring the program closer to its final form.
We start with the simplest program and test it right away.
frilled.cs.indiana.edu%ls -l dgerm*
-rw------- 1 dgerman 152 Mar 21 09:12 dgerman7.java
frilled.cs.indiana.edu%cat dgerman7.java
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
System.out.println("Hello");
}
}
frilled.cs.indiana.edu%javac dgerman7.java
frilled.cs.indiana.edu%java dgerman7
Hello
frilled.cs.indiana.edu%
In this program I simply follow the naming conventions for this assignment
and call the file and the public class inside by the username
of my grader followed by the number of the assignment.
As I have done in the past I am presenting here the development stages done
on a Unix machine, where emacs is the editor used to write the
text of the source code, cat is a utility that will list the
contents of the file (so that I can show the source code), and the rest is
like up until now, with javac being used for compilation and
java for running the resulting .class file.
So now I have a program and it's working. But it's not doing much yet.
The only part in it that is related to the assignment is the one that is
marked in blue. It imports the classes
that are needed, all classes from the element package and the
Color class in the java.awt package, and sets up
the basic framework of the application.
The first thing that we will do will be to create a procedure that will
print Hello for us. Just like the next assignment asks us to
do, and as the book describes in section 4.6, we will be placing all of our
methods in a class by the name of Library.
So here's the first change to our program (that still works the same):
frilled.cs.indiana.edu%ls -ld dger*.java
-rw------- 1 dgerman 246 Mar 21 09:54 dgerman7.java
frilled.cs.indiana.edu%cat dgerman7.java
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printGreeting();
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
}
frilled.cs.indiana.edu%javac dgerman7.java
frilled.cs.indiana.edu%java dgerman7
Hello
frilled.cs.indiana.edu%
Not much is new in terms of functionality, except the organization of the
program is different. A second class definition has been added, it contains
the definition of only one method, which is called from the main
method of the original class definition. The new method always prints the
same greeting: Hello. We can add a second method definition that will print a custom greeting, provided that we pass the adequate information to it. Details on how this works are provided in the book on pages 100-111 and will also be provided in class today. Here's the code:
frilled.cs.indiana.edu%ls -ld dgerman7.java
-rw------- 1 dgerman 400 Mar 21 10:04 dgerman7.java
frilled.cs.indiana.edu%cat dgerman7.java
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printGreeting();
Library.printCustomGreeting("Hello again!");
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
}
frilled.cs.indiana.edu%javac dgerman7.java
frilled.cs.indiana.edu%java dgerman7
Hello
Hello again!
frilled.cs.indiana.edu%
Now we have a procedure that receives the custom greeting as a String,
calls it greeting inside, and prints it out in the same way as before.
The difference though is that this new procedure can print any greeting it is being
told to print, whereas the other one only prints Hello.
Inside the new procedure greeting is like a variable and is called
a formal parameter. Any String that we pass to this new method at the
time we invoke it will be known as greeting inside the body of the
method. (The body of the method is always in between the curly braces, as was the
case with main, or some for loops and while
statements). Let's now return to homework 7.
In class I may be developing things using Symantec, for a change. You will see that
the editor is nice, and the overall edit compile and run loop is also well supported.
However we should always be prepared to use javac and java
to compile and run.
Getting back to homework 7 can be done as follows.
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printCustomGreeting("Welcome to Homework Seven!");
DrawingWindow d = new DrawingWindow();
// now we are ready to draw in d...
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
}
Remember the notations from last time:
So let's start by defining some variables in main then drawing the grid.
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
// Greet the user. Where does this greeting get printed?
Library.printCustomGreeting("Welcome to Homework Seven!");
// Create a drawing window
DrawingWindow d = new DrawingWindow();
// Now we are ready to draw in d...
int xL, // Coordinate of left vertical border of grid
yL, // Coordinate of top horizontal border of grid
// (xL, yL) is top left corner of grid
cols, // Number of columns we want in grid
lines, // Number of lines we want in grid
width, // Width in pixels of a cell in the grid
height; // Height in pixels of a cell in the grid
// Initialize the declared variables, one by one.
xL = 20;
yL = 30; // Top left corner coordinates are arbitrary
cols = 11;
lines = 7; // Matches the example shown in diagram.
width = 12;
height = 12; // Cells in grid will actually be squares.
// By default a drawing window's size is 200 x 200 pixels.
Library.drawGrid(d, xL, yL, cols, lines, width, height);
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
public static void drawGrid(DrawingWindow dW, // The Window
int x, // xL
int y, // yL
int c, // cols
int l, // lines
int w, // cell width
int h) { // cell height
System.out.println(" I should be drawing the grid now ... ");
}
}
We have defined the variables that we need (xL, yL,
cols, lines, width, height)
in main and we have initialized them to some reasonable values. The
rest of our program will be centered around these values, just like the lecture
we had on Thursday before the break. There is another variable that is used in
main, the one that holds the reference to the window on which we
are going to draw.
The first step in our development process is to make it very explicit that
we want to first draw the grid. We set aside a separate procedure (or method) in
the Library class and give it a reasonable name: drawGrid.
As part of the design process we acknowledge that we need to pass this procedure a
lot of information for it to be able to draw what we want. We pass it everything we
have defined thus far in main, as variables declared in main
will not be know outside its body. The new procedure definition will have to match
the number and type of arguments, but can use different names for them, which is
what we have done in our example. The body of the procedure is empty now, but for
debugging purposes we have placed a println statement in it to see
that the procedure is executed (and the message gets printed). Our next step is
to flesh out the body of the procedure.
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
// Greet the user. Where does this greeting get printed?
Library.printCustomGreeting("Welcome to Homework Seven!");
// Create a drawing window
DrawingWindow d = new DrawingWindow();
// Now we are ready to draw in d...
int xL, // Coordinate of left vertical border of grid
yL, // Coordinate of top horizontal border of grid
// (xL, yL) is top left corner of grid
cols, // Number of columns we want in grid
lines, // Number of lines we want in grid
width, // Width in pixels of a cell in the grid
height; // Height in pixels of a cell in the grid
// Initialize the declared variables, one by one.
xL = 20;
yL = 30; // Top left corner coordinates are arbitrary
cols = 11;
lines = 7; // Matches the example shown in diagram.
width = 12;
height = 12; // Cells in grid will actually be squares.
// By default a drawing window's size is 200 x 200 pixels.
Library.drawGrid(d, xL, yL, cols, lines, width, height);
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
public static void drawGrid(DrawingWindow dW, // The Window
int x, // xL
int y, // yL
int c, // cols
int l, // lines
int w, // cell width
int h) { // cell height
System.out.println(" Drawing of grid starts... ");
for (int i = 0; i < l; i++) {
for (int j = 0; j < c; j++) {
Rect r = new Rect(x + j * w, y + i * h, w, h);
dW.draw(r);
}
System.out.println(" Done with line: " + i);
}
}
}
The program prints the grid and reports after completing every line. For the fun
of it we can draw the grid in slow motion. Let's add the wait1second
(defined on page 102 of your text) to our Library of methods, and
call it after we draw each cell. Here's the code (some comments have been taken
under the assumption that by now we have understood the code that they referred to).
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printCustomGreeting("Welcome to Homework Seven!");
DrawingWindow d = new DrawingWindow();
int xL = 20, yL = 30, cols = 11, lines = 7, width = 12, height = 12;
Library.drawGrid(d, xL, yL, cols, lines, width, height);
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
public static void drawGrid(DrawingWindow dW, // The Window
int x, // xL
int y, // yL
int c, // cols
int l, // lines
int w, // cell width
int h) { // cell height
System.out.println(" Drawing of grid starts... ");
for (int i = 0; i < l; i++) {
for (int j = 0; j < c; j++) {
Rect r = new Rect(x + j * w, y + i * h, w, h);
dW.draw(r);
Library.wait1second();
}
System.out.println(" Done with line: " + i);
}
}
public static void wait1second() {
long now, then;
now = System.currentTimeMillis();
then = now + 1000;
while (System.currentTimeMillis() < then) {
// do nothing (keep checking))
}
}
}
Once we test this out we need to either take it out (make it a comment) or
make the grid smaller since it would otherwise take so much longer to draw
the grid the more lines and columns it has.
Let's draw the two buttons erase and quit:
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printCustomGreeting("Welcome to Homework Seven!");
DrawingWindow d = new DrawingWindow();
int xL = 20, yL = 30, cols = 11, lines = 7, width = 12, height = 12;
Library.drawGrid(d, xL, yL, cols, lines, width, height);
Rect erase = new Rect(10, 10, 30, 10);
Rect quit = new Rect(10 + 30, 10, 30, 10);
Library.drawButtons(d, erase, quit);
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
public static void drawGrid(DrawingWindow dW, // The Window
int x, // xL
int y, // yL
int c, // cols
int l, // lines
int w, // cell width
int h) { // cell height
System.out.println(" Drawing of grid starts... ");
for (int i = 0; i < l; i++) {
for (int j = 0; j < c; j++) {
Rect r = new Rect(x + j * w, y + i * h, w, h);
dW.draw(r);
// Library.wait1second();
}
System.out.println(" Done with line: " + i);
}
}
public static void wait1second() {
long now, then;
now = System.currentTimeMillis();
then = now + 1000;
while (System.currentTimeMillis() < then) {
// do nothing (keep checking))
}
}
public static void drawButtons(DrawingWindow d, Rect e, Rect q) {
d.draw(e);
d.setForeground(Color.blue);
d.fill(q);
d.setForeground(Color.black);
d.draw(q);
}
}
Now we need to wait for mouse input (a mouse click) and when we detect one
to take the action. We do this in an infinite loop that waits (pauses) for
every click but does not limit the number of clicks we can process.
public class dgerman7 {
public static void main(String[] args) {
Library.printCustomGreeting("Welcome to Homework Seven!");
DrawingWindow d = new DrawingWindow();
int xL = 20, yL = 30, cols = 11, lines = 7, width = 12, height = 12;
Library.drawGrid(d, xL, yL, cols, lines, width, height);
Rect erase = new Rect(10, 10, 30, 10);
Rect quit = new Rect(10 + 30, 10, 30, 10);
Library.drawButtons(d, erase, quit);
while (true) {
Pt m = d.awaitMouseClick();
if (quit.contains(m)) {
System.out.println("Good-bye!");
System.exit(0);
}
if (erase.contains(m)) {
d.clear(d.bounds());
Library.drawGrid(d, xL, yL, cols, lines, width, height);
Library.drawButtons(d, erase, quit);
// Should look like it did in the beginning...
} else {
System.out.println(" Drawing red squares... ");
}
}
}
}
The only change occurs in the main class. Now we move the drawing of red squares inside the library of methods.
import element.*;
import java.awt.Color;
public class dgerman7 {
public static void main(String[] args) {
Library.printCustomGreeting("Welcome to Homework Seven!");
DrawingWindow d = new DrawingWindow();
int xL = 20, yL = 30, cols = 11, lines = 7, width = 12, height = 12;
Library.drawGrid(d, xL, yL, cols, lines, width, height);
Rect erase = new Rect(10, 10, 30, 10);
Rect quit = new Rect(10 + 30, 10, 30, 10);
Library.drawButtons(d, erase, quit);
while (true) {
Pt m = d.awaitMouseClick();
if (quit.contains(m)) {
System.out.println("Good-bye!");
System.exit(0);
}
if (erase.contains(m)) {
d.clear(d.bounds());
Library.drawGrid(d, xL, yL, cols, lines, width, height);
Library.drawButtons(d, erase, quit);
// Should look like it did in the beginning...
} else {
Library.drawRedSquares();
}
}
}
}
class Library {
public static void printGreeting() {
System.out.println("Hello");
}
public static void printCustomGreeting(String greeting) {
System.out.println(greeting);
}
public static void drawGrid(DrawingWindow dW, // The Window
int x, // xL
int y, // yL
int c, // cols
int l, // lines
int w, // cell width
int h) { // cell height
System.out.println(" Drawing of grid starts... ");
for (int i = 0; i < l; i++) {
for (int j = 0; j < c; j++) {
Rect r = new Rect(x + j * w, y + i * h, w, h);
dW.draw(r);
// Library.wait1second();
}
System.out.println(" Done with line: " + i);
}
}
public static void wait1second() {
long now, then;
now = System.currentTimeMillis();
then = now + 1000;
while (System.currentTimeMillis() < then) {
// do nothing (keep checking))
}
}
public static void drawButtons(DrawingWindow d, Rect e, Rect q) {
d.draw(e);
d.setForeground(Color.blue);
d.fill(q);
d.setForeground(Color.black);
d.draw(q);
}
public static void drawRedSquares() {
System.out.println(" Drawing red squares... ");
}
}
Let's develop the drawRedSquares method, see what information
it needs to complete job. It needs: xL, yL)
lines and cols)
width and height)
drawRedSquares as follows:
public static void drawRedSquares(Pt m, DrawingWindow d,
int xL, int yL, int cols, int lines, int w, int h) {
if (m.x() >= xL && m.x() < xL + cols * w && // within western and eastern border
m.y() >= yL && m.y() < yL + lines * h) { // within northerm and southern border
int i = (m.y() - yL) / w; // line in grid of cell where mouse clicked
int j = (m.x() - xL) / h; // col. in grid of cell where mouse clicked
int xij = xL + w * j; // top left corner x coord. for cell where mouse clicked
int yij = yL + h * i; // y coord. for same cell, i and j just computed are used
Rect redSquare = new Rect(xij, yij, w, h);
d.setForeground(Color.red);
d.fill(redSquare);
d.setForeground(Color.black);
d.draw(redSquare);
} else {
System.out.println("Outside of grid");
}
}
and change the way we invoke it
and we are done.Library.drawRedSquares(m, d, xL, yL, cols, lines, width, height);
Note that this way the structure of main is clearer, and the
modules are separate and we only need think what kind of info we need to
send to them, and how we call it. You can't submit this as your assignment
7, the assignment you turn in should have a single class and one method
main. But you can use this to write your assignment, by
understanding the various smaller components in detail.