Solutions Manual For Java 2E, Ralph Morelli
Solutions Manual For Java 2E, Ralph Morelli
Solutions Manual For Java 2E, Ralph Morelli
Ralph Morelli
with Jamie Mazur, Meisha Morelli, and Alicia Morelli
April 12, 2002
c 2002
Prentice
Hall
Preface
This Solutions Manual contains solutions for all the exercises in Java, Java, Java, 2E,
including the complete source code for all the programming exercises.
Each of the solutions has been checked for accuracy. The source code has been
thoroughly documented and tested. Most of the programming solutions contain a brief
explanation of the main design issues considered in developing the solution, and many
of the solutions include figures showing their graphical interface or the sample output
they produce. For the second edition, (Unified Modeling Language) UML diagrams
are provided for each of the programming exercises. These are generally located at the
end of the chapter.
The Instructors Resource CD (IRCD) contains the source code and Java byte code
for all the programming solutions. The programs are organized into directories that
correspond to the books chapters. There is also an HTML-based index that allows
you to browse through the solutions and run the Java applet solutions using a Web
browser. The IRCD also contains separate GIF files for each of the UML diagrams.
Thus, instructors who so desire can provide students with the design for a solution (in
UML) and have the students code the solution in Java. Finally, the IRCD also contains
solutions and additional documentation for the laboratory exercises described in the
text.
I would greatly appreciate any comments, suggestions, or corrections you may have
on any of the ancillary materials that are available with Java, Java, Java, 2E. The best
way to reach me is by e-mail at: [email protected] I will try to get back to
you as quickly as possible.
Writing and producing a textbook together with its supporting materials is an enormous team effort, and I would like to thank the entire team of professionals at PrenticeHall. In terms of this solutions manual, I especially want to commend the work done
by my student assistants: Jamie Mazur, Trinity College, 2000, Meisha Morelli (my
daughter), Amherst College, 2002, and Alicia Morelli (my daughter), Union College,
2004. Jamie and Meisha wrote the first draft of many of the solutions, and Alicia did
extensive work on the UML diagrams.
R. Morelli
ii
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
22
41
71
101
6 Control Structures
135
166
217
263
300
354
370
392
444
468
513
Chapter 0
principle.
(b) Designing a class so that it shields certain parts of an object from other
principle. Answer: information hiding
objects is an example of the
(c) The fact that Java programs can run without change on a wide variety of
. Answer: platform
different kinds of computers is an example of
independence
(d) The fact that social security numbers are divided into three parts is an exprinciple. Answer: abstraction
ample of the
(e) To say that a program is robust means that
. Answer: errors in
the program dont usually cause system crashes
is a separate module that encapsulates a Java programs attributes
(f) An
and actions. Answer: object
2. Explain the difference between each of the following pairs of concepts.
(a) hardware and software
Answer: A computers hardware consists of its physical components,
such as its processor and memory. Its software includes the programs that
control the hardware.
(b) systems and application software
Answer: Systems software, such as the operating system, is the software
that gives the computer its general usability. Application software consists
of programs that perform specific tasks, such as word processing.
(c) compiler and interpreter
Answer: A compiler translates an entire source code program into object
code, which can then be executed. An interpreter translates and executes
one line of a program at a time.
2
protocol. Answer:
(j) A
is a networked computer that is used to store data for other computers on the network. Answer: file server
4. Identify the component of computer hardware that is responsible for the following functions.
(a) fetch-execute cycle Answer: The CPU, central processing unit
(b) arithmetic operations Answer: the ALU, arithmetic-logic unit
(c) executing instructions Answer: the CPU, central processing unit
(d) storing programs while they are executing Answer: primary memory
(e) storing programs and data when the computer is off Answer: secondary
memory
5. Explain why a typical piece of software, such as a word processor, cannot run on
both a Macintosh and a Windows machine.
Answer: Macintosh and Windows computers constitute different hardware and
software platforms. A typical piece of software uses features of a particular operating system (such as Windows) and a particular hardware environment (such
as Intel). This is known as platform dependence.
6. What advantages do you see in platform independence? What disadvantages?
Answer: Platform independence means that a single program can run without
further translation on a wide variety of computers. One advantage is that this
would greatly simplify software development. One disadvantage is that it is very
difficult to optimize a platform independent program for a particular hardware or
software platform. Therefore, such programs may not be as efficient as platformdependent programs.
form of information hiding makes our lives much simpler. If we had to know how
our radiator works in order to drive a car, wed all have to get physics degrees!
UML Exercises
11. Draw a UML object diagram to depict a relationship between two objects, a
telephone and a user.
Miscellaneous Classes
User
Dog
+says()
Savings Account
Telephone
+deposit()
Person
+says()
Customer
Exercise 0.11
: User
Exercise 0.12
Uses
: Telephone
Owns
: Person
: Dog
Exercise 0.14
Exercise 0.13
Owns
Owns
bill : Person
lily : Dog
bill
lily
says(Speak)
says(Arf!)
Exercise 0.15
deposit($50)
William Smith
Account #00550090
12. Draw a UML object diagram to depict a relationship between two objects, a dog
and its owner.
13. Modify the diagram in the previous exercise to show that the pet owner is named
Bill and the pet is named Lily.
14. Modify the diagram in the previous exercise to represent the following exchange
between Bill and Lily: Bill says Speak and Lily says Arf.
15. Draw a UML diagram to represent a relationship between a customer and the
customers savings account. Have the customer deposits $50 into the account.
Chapter 1
and
but an empty
.
.
Print N.
If N equals 1, stop.
If N is even, divide it by 2.
If N is odd, triple it and add 1.
Go to step 0.
Answer: This was supposed to be the 3N+1 algorithm. But given the way this
algorithm is stated, it will result in an infinite sequence being printed out in each
case. For N=15, the sequence will be 15, 46, 70, 106, 160, 80, 40, 20, 10, 16, 8,
4, 2, 4, 2, ... For N=6, the sequence will be 6, 10, 16, 8, 4, 2, 4, 2, ... Perhaps a
better algorithm for this exercise would be modify steps 2 and 3 as follows:
2: If N is even, divide it by 2 and go to step 0.
3. If N is odd, triple it and add 1 and go to step 0.
Stated this way, the algorithms would print out the sequences 15, 46, 23, 70, 35,
106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1 for N=15 and 6, 3, 10, 5, 16, 8, 4, 2,
1 for N=6.
6. Suppose N is 5 and M is 3. What value would be reported by the following
pseudocode algorithm? In general, what quantity does this algorithm calculate?
0.
1.
2.
3.
4.
Answer: This algorithm will report 15. In general this algorithm calculates the
quantity M N .
10
11
7. Puzzle Problem: You are given two different length strings that have the characteristic that they both take exactly one hour to burn. However, neither string
burns at a constant rate. Some sections of the strings burn very fast, other sections burn very slow. All you have to work with is a box of matches and the two
strings. Describe an algorithm that uses the strings and the matches to calculate
when exactly 45 minutes has elapsed.
Answer:
0. Light both ends of the first string and
one end of the second string at the same time.
1. When the first string is finished burning,
light the unlit end of the second string.
2. When the second string is finished burning
exactly 45 minutes will have passed.
8. Puzzle Problem: A polar bear that lives right at the North Pole can walk due
south for one hour, due east for one hour, and due north for one hour, and end
up right back where it started. Is it possible to do this anywhere else on earth?
Explain.
Answer: Yes. There are an infinite number of other locations on earth where
this is possible. For example, pick a latitude near the South Pole where the
circumference of the earth takes exactly 1/2 hour to traverse. Start at a point that
is 1 hour north of this latitude. From this point (and there are an infinite number
of such points) you can walk one hour due south, then one hour due east (making
2 revolutions of the earth and arriving back where you turned east), and then one
hour due north. You will arrive back at the same spot where you started.
9. Puzzle Problem: Lewis Carroll, the author of Alice in Wonderland, used the following puzzle to entertain his guests: A captive Queen weighing 195 pounds, her
son weighing 90 pounds, and her daughter weighing 165 pounds, were trapped in
a very high tower. Outside their window was a pulley and rope with a basket fastened on each end. They managed to escape by using the baskets and a 75-pound
weight they found in the tower. How did they do it? The problem is anytime the
difference in weight between the two baskets is more than 15 pounds, someone
might get killed. Describe an algorithm that gets them down safely.
Answer:
\begin{verbatim}
0. QDSW are in the tower.
1. Lower the 75 lb. wgt, empty basket comes up. (75/0)
2. Lower the 90 lb. prince as 75 lb. wgt. goes up. (90/75)
TOWER, GROUND
QDSW, QDS , W
QD W, S
3. Lower
4. Lower
5. Lower
6. Lower
7. Lower
8. Lower
9. Lower
10. Lower
11. Lower
12. Lower
, QDSW
12
QD ,
Q SW,
Q S ,
Q W,
DS ,
D W,
D ,
SW,
S ,
-
SW
D
DW
DS
QW
QS
QSW
QD
QDW
Note that this solution allows the occupants to pull on the ropes when
the weights are equal (165/165).
10. Puzzle Problem: Heres another Carroll favorite: A farmer needs to cross a
river with his fox, goose, and a bag of corn. Theres a rowboat that will hold the
farmer and one other passenger. The problem is that the fox will eat the goose, if
they are left alone, and the goose will eat the corn, if they are left alone. Write an
algorithm that describes how he got across without losing any of his possessions.
Answer:
1.
2.
3.
4.
5.
6.
7.
Farmer
Farmer
Farmer
Farmer
Farmer
Farmer
Farmer
Other bank
----------Goose
Fox
Fox and Corn
Fox, Corn, Goose, Farmer
11. Puzzle Problem: Have you heard this one? A farmer lent the mechanic next
door a 40-pound weight. Unfortunately the mechanic dropped the weight and it
broke into four pieces. The good news is that according to the mechanic, it is
still possible to use the four pieces to weigh any quantity between one and 40
pounds on a balance scale. How much did each of the four pieces weigh? (Hint:
You can weigh a 4-pound object on a balance by putting a 5-pound weight on
one side and a 1-pound weight on the other.)
Answer: The weights were 1 + 3 + 9 + 27 = 40 and heres some of the formulas
for weighing various weights. The equation relates the two sides of a balance
scale. The unknown is the first value in the equation:
X
--
40
39
38 +
37
36
35 +
...
6 +
5 +
4
3
2 +
1
=
=
=
=
=
=
3
3 + 1 =
=
=
1
=
=
27
27
27
27
27
27
+
+
+
+
+
+
9
9
9
9
9
9
+
+
+
+
3 + 1
3
3
1
9
3 + 1
3
3
1
12. Suppose your little sister asks you to help her calculate her homework average
in her science course by showing how to use a pocket calculator. Describe an
algorithm that she can use to find the average of 10 homework grades.
Answer:
0.
1.
2.
3.
4.
5.
6.
13. A Caesar cipher is a secret code in which each letter of the alphabet is shifted by
N letters to the right, with the letters at the end of the alphabet wrapping around
to the beginning. For example, if N is 1, daze would be written as ebaf.
Describe an algorithm that can be used to create a Caesar encoded message with
a shift of 5.
Answer:
Repeat 5 times
Shift each letter of the message by 1
14. Suppose you received the message, sxccohv duh ixq, which you know to be a
Caesar cipher. Figure out what it says and then describe an algorithm that will
always find what the message said regardless of the size of the shift that was
used.
Answer:
Repeat until the message is readable
Shift each letter of the encrypted message by 1
13
sxccohv
tyddpiw
uzeeqjx
vaffrky
wbggslz
xchhtma
ydiiunb
zejjvoc
afkkwpd
bgllxqe
chmmyrf
dinnzsg
ejooath
fkppbui
glqqcvj
hmrrdwk
inssexl
jottfym
kpuugzn
lqvvhzo
mrwwiap
nsxxjbq
otyykcr
puzzles
duh
evi
fwj
gxk
hyl
izm
jan
kbo
lcp
mdq
ner
ofs
pgt
qhu
riv
sjw
tkx
uly
vmz
wna
xob
ypc
zqd
are
ixq
jyr
kzs
lat
mbu
ncv
odw
pex
qfy
rgz
sha
tib
ujc
vkd
wle
xmf
yng
zoh
api
bqj
crk
dsl
etm
fun
15. Suppose youre talking to your little brother on the phone and he wants you
to calculate his homework average. All you have to work with is a piece of
chalk and a very small chalkboard big enough to write one four-digit number.
Whats more, although your little brother knows how to read numbers, he doesnt
know how to count very well so he cant tell you how many grades there are. All
he can do is read the numbers to you. Describe an algorithm that will calculate
the correct average under these conditions.
Answer:
0.
1.
2.
3.
4.
5.
6.
14
15
20. Complete the definition of the Square class using the definition of Rectangle, defined in this chapter, as a model.
/*
* File: Square.java
* Author: Java, Java, Java
* Description: This class implements a geometric square.
*/
public class Square
{
private double side;
// Instance variable
/**
* Square() constructor creates a square with side l
22. Define a Java class, called Patterns, modeled after OldMacDonald, that
16
will print the following patterns of asterisks, one after the other heading down
the page:
*****
****
***
**
*
*****
*
*
*
*
*
*
*****
*****
* * *
* *
* * *
*****
/*
* File: Patterns.java
* Author: Java, Java, Java
* Description: This class prints a patter of asterisks.
*/
public class Patterns
{
public static void main(String argv[]) // Main method
{
System.out.println("*****");
System.out.println(" ****");
System.out.println(" ***");
System.out.println("
**");
System.out.println("
*");
System.out.println();
System.out.println("*****");
System.out.println("*
*");
System.out.println("*
*");
System.out.println("*
*");
System.out.println("*****");
System.out.println();
System.out.println("*****");
System.out.println("* * *");
System.out.println(" * *");
System.out.println("* * *");
System.out.println("*****");
} // main()
} // Patterns
23. Write a Java class that prints your initials as block letters, for example,
******
*
*
*
*
******
**
* *
* *
*
*
*
*
**
**
* *
* *
* * * *
*
*
*
*
*
*
*
*
*
17
/*
* File: Initials.java
* Author: Java, Java, Java
* Description: This class prints the block initials RM.
*/
public class Initials
{
public static void main(String argv[]) // Main method
{
System.out.println("******* *
*");
System.out.println("*
* **
**");
System.out.println("*
* * *
* *");
System.out.println("******* * * * *");
System.out.println("**
*
*
*");
System.out.println("* *
*
*");
System.out.println("* *
*
*");
System.out.println("*
*
*
*");
} // main()
} // Initials
18
*/
public double getTemp()
{
return currentTemp;
}
} // Temperature
25. Challenge: Define a class named TaxWhiz that computes the sales tax for
a purchase. It should store the current tax rate as an instance variable. Following the model of the Rectangle class, you can initialize the rate using a
TaxWhiz() method. This class should have one public method, calcTax(double
purchase), which returns a double, whose value is purchases times
the tax rate. For example, if the tax rate is 4 percent, 0.04, and the purchase is
$100, the calcTax() should return 4.0.
/*
* File: TaxWhiz.java
* Author: Java, Java, Java
* Description: This class stores a tax rate and
* computes the tax for a given purchase price.
*/
public class TaxWhiz
{
private double taxRate;
/**
* TaxWhiz() constructor creates an object with
* a given tax rate
* @param t -- the given tax rate
*/
public TaxWhiz(double t)
{
taxRate = t;
}
/**
* calcTax() returns the tax for a given purchase
* @param purchase -- the given purchase price
*/
public double calcTax(double purchase)
{
return taxRate * purchase;
}
} // TaxWhiz
19
UML Exercises
26. Modify the UML diagram of the Rectangle class to contain a method for
calculating a rectangles perimeter. Like the calculateArea() method, this
method should return a double.
27. Draw a UML class diagram representing the following class: The name of the
class is Circle. It has one attribute, a radius which is represented by a
double value. It has one operation, calculateArea(), which returns a
double. Its attributes should be designated as private and its method as public.
28. Draw a UML diagram of the FirstApplet class (Text Figure 1-18) showing
all of its attributes and operations.
29. To represent a triangle we need attributes for each of its three sides and operations
to create a triangle, calculate its area, and calculate its perimeter. Draw a UML
diagram to represent this triangle.
30. Try to give the Java class definition for the class described in the UML diagram
shown in Figure 1.1.
/*
* File: Person.java
* Author: Java, Java, Java
* Description: This class represents a person.
*/
public class Person
{
private String name;
private String phone;
/**
* printName() prints the persons name.
*/
public void printName()
{
System.out.println(name);
}
/**
* printPhone() prints the persons name.
*/
public void printPhone()
{
System.out.println(phone);
}
} // Person
20
21
Exercise 1.18
Misc. Classes
Button
+Square(in l : double)
+calculateArea() : double
+calculatePerimeter() : double
Exercise 1.24
Initials
+main()
Exercise 1.25
Temperature
+main()
Exercise 1.22
MaryHadALittleLamb
Patterns
-length : double
ActionEvent
Exercise 1.23
Exercise 1.21
Square
Exercise 1.26
TaxWhiz
-currentTemp : double
-taxRate : double
+setTemp(in t : double)
+getTemp() : double
+TaxWhiz(in t : double)
+calcTax(in purchase : double) : double
Exercise 1.27
+main()
Exercise 1.28
Circle
FirstApplet
-radius : double
-clickMe : Button
+calculateArea() : double
+init()
+actionPerformed(in e : ActionEvent)
Exercise 1.29
Triangle
-length1 : double
-length2 : double
-length3 : double
+Triangle(in side1 : double, in side2 : double, in side3 : double)
+calculateArea() : double
+calculatePerim() : double
Rectangle
-length : double
-width : double
+Rectangle(in len : double, in wid : double)
+calculateArea() : double
+calculatePerim() : double
Chapter 2
22
23
24
, or a
74ElmStreet
public
Big_N
Private
L$&%#
Joe
boolean
j1
Boolean
2*K
_number
big numb
(a)
(b)
(c)
colon
(d)
(e)
(f)
(g)
(h)
(i)
(j)
25
//
//
//
//
//
//
//
//
//
//
//
// Answer
// Answer
// Answer
15. For each of the following data types, identify what default value Java will give
a instance variable of that type if no initializer expression is used when it is
declared: boolean, int, String, double, CyberPet.
Answer: boolean: false, int:
CyberPet: null
0, String:
null, double:0.0,
16. Identify the syntax error (if any) in each method header:
(a)
(b)
//
//
//
//
//
(c)
private void myMethod
theses after myMethod
(d)
private myMethod()
// The ResultType is not defined
(e)
public static void Main (String argv[]) // This is OK but its a different
// method than main() with lowercase m.
26
17. Identify the syntax error (if any) in each assignment statement. Assume that the
following variables have been declared:
public
public
public
public
int m;
double d;
boolean b;
String s;
(a)
m = 86.5 ;
teger variable.
(b)
d = 86 ;
(c)
d = true ;
ble variable.
(d)
s = 1295 ;
(e)
s = "1295.98" ;
(f)
b = "true" ;
tion marks around it.
(g)
b = false
18. Given the definition of the NumberAdder class, add statements to its main()
method to create two instances of this class, named adder1 and adder2. Then
add statements to set adder1s numbers to 10 and 15, and adder2s numbers
to 100 and 200. Then add statements to print their respective sums.
/*
* File: NumberAdder.java
* Author: Java, Java, Java
* Description: This class adds its two instance variables
* when its getSum() method is called.
*/
public class NumberAdder
{
private double num1;
private double num2;
/**
* setNums() sets the two instance variables from the given parameters
* @param n1 -- one of the given numbers
* @param n2 -- the second given number
*/
public void setNums(double n1, double n2)
{
num1 = n1;
num2 = n2;
} // setNums()
/**
* getSum() returns the sum of the two instance variables
27
*/
public double getSum()
{
return num1 + num2 ;
} // getSum()
/**
* main() creates two instances of this class and tests its
* setNums() and getSum() methods
*/
public static void main(String args[])
{
NumberAdder adder1 = new NumberAdder(); // Create two instances
NumberAdder adder2 = new NumberAdder();
adder1.setNums(10,15);
// Set the instances values
adder2.setNums(100,200);
System.out.println("Sum of adder1 " + adder1.getSum()); // Print the values
System.out.println("Sum of adder2 " + adder2.getSum());
} // main()
} // NumberAdder
19. For the NumberAdder class in the previous exercise, what are the names of its
instance variables and instance methods? Identify three expressions that occur in
the program and explain what they do. Identify two assignment statements and
explain what they do.
Instance variables = num1, num2
Instance methods = setNums(), getSums()
private double num1; is an expression defining the variable num1 as
double and private
System.out.println("Sum of adder1 " + adder1.getSum()); is an
expression that reports the sum of adder1 by printing what is
in the quotation marks
num1 + num2 is an expression that evaluates to the sum of num1
and num2
num1 = n1; is an assignment statement that sets the value of num1
to n1
num2 = n2; is an assignment statement that sets the value of num1
to n1
20. Explain the difference between each of the following pairs of concepts.
(a) A method definition and a method invocation.
Answer: Method definition is the part of the code that contains the executable statements that the method performs. Method invocation is the act
of calling the method to perform the task it is meant to perform.
(b) Declaring a reference variable and creating an instance.
Answer: A reference variable (such as pet1) refers to an object. An
object is an instance of a class and must be created (instantiated) with the
new operator.
(c) Defining a variable and instantiating an object.
Answer: Defining a variable is creating a new variable where data can be
placed. Instantiating an object is creating a specific instance of an object
with the new keyword.
21. Look at the following Java program, which uses the CyberPet class defined in
Text Figure 2-8. What would the program output be?
public class TestCyberPet
{
public static void main(String argv[])
{
CyberPet pet1;
pet1 = new CyberPet();
pet1.eat();
pet1.sleep();
CyberPet pet2;
pet2 = new CyberPet();
pet2.sleep();
pet2.eat();
pet1.eat();
} // main()
} // TestCyberPet
*********** The output would be:
Pet is eating
Pet is sleeping
Pet is sleeping
Pet is eating
Pet is eating
22. Write a main method that creates two CyberPets named lilly and billy
and then asks each of them to sleep and then eat.
public static void main(String argv[])
{
CyberPet lilly;
lilly = new CyberPet();
lilly.sleep();
lilly.eat();
28
CyberPet billy;
billy = new CyberPet();
billy.sleep();
billy.eat();
}
23. Modify CyberPet to have a String instance variable, name. Give name
an initial value and add a public method tellMeYourName() that prints the
pets name. Test your method by invoking it from main().
/*
* File: CyberPet.java
* Author: Java, Java, Java
* Description: This class defines an object that simulates a simple
* pet that can eat, sleep and state its name upon command.
*/
public class CyberPet
{
private boolean isEating = true;
private boolean isSleeping = false;
private String name = "Lilly";
/**
* tellMeYourName() prints the pets name
*/
public void tellMeYourName()
{
System.out.println("Pets name is " + name );
}
/**
* eat() puts the pet in the eating state
*/
public void eat()
{
isEating = true;
isSleeping = false;
System.out.println("Pet is eating");
return;
}
/**
* sleep() puts the pet in the sleeping state
*/
public void sleep()
{
isSleeping = true;
isEating = false;
29
System.out.println("Pet is sleeping");
return;
}
/**
* main() creates a CyberPet instance and asks it its name
*/
public static void main(String argv[])
{
CyberPet pet = new CyberPet();
pet.tellMeYourName();
}
} // CyberPet
24. Define a Java class named NumberCruncher which has a single double
value as its only instance variable. Then define methods that perform the following operations on its number: get, double, triple, square, and cube. Set the initial
value of the number by following the way the length and width variables are
set in the Rectangle class.
Answer: See the answer to the next problem.
25. Write a main() method and add it to the NumberCruncher class defined in
the previous problem. Use it to create a NumberCruncher instance, with a
certain initial value, and then get it to report its double, triple, square, and cube.
/*
* File: NumberCruncher.java
* Author: Java, Java, Java
* Description: This class stores a number and contains
* methods to calculate the numbers double, triple, and so on.
*/
public class NumberCruncher
{
private double num;
// The instance variable
/**
* NumberCruncher() constructor creates an instance that
* stores the number given as its parameter
* @param number -- the number that will be stored
*/
public NumberCruncher(double number)
{
num = number;
}
/**
* getNum() returns the objects number
*/
30
31
} // NumberCruncher
26. Challenge: Modify your solution to the previous exercise so that it lets the user
input the number to be crunches. Follow the example shown in the section that
describes how to input numeric values.
Answer: The only change needed to solve this problem is to add statements to
main() to perform keyboard input. A BufferedReader instance is used to
input a string, which is then converted to an int.
/**
* main() creates an instance of this class and tests its
*
various methods. This version uses a BufferedReader
*
object to let the user input the objects number.
*/
public static void main( String args[] ) throws IOException
{
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
String inputString;
double num;
System.out.println("Input a number: ");
inputString = input.readLine();
num = Integer.parseInt(inputString);
NumberCruncher cruncher1 = new NumberCruncher(num);
System.out.println("Value of num is " + cruncher1.getNum());
System.out.println("num doubled is " + cruncher1.doubleNum());
System.out.println("num tripled is " + cruncher1.tripleNum());
System.out.println("num squared is " + cruncher1.squareNum());
System.out.println("num cubed is " + cruncher1.cubeNum());
} // main()
27. Write a Java class definition for a Cube object. The object should be capable of
reporting its surface area and volume. The surface area of a cube is six times the
area of any side. The volume is calculated by cubing the side.
/*
* File: Cube.java
* Author: Java, Java, Java
* Description: This class represents a geometric cube.
*/
public class Cube
{
private double length;
/**
* Cube() constructor creates an instance with length l
* @param l -- the length of the cubes side
32
*/
public Cube(double l)
{
length = l;
}
/**
* getLength() returns this cubes length
*/
public double getLength()
{
return length;
}
/**
* calculateSurfaceArea() returns this cubes surface area
*/
public double calculateSurfaceArea()
{
return 6 * length;
}
/**
* calculateVolume() returns this cubes volume
*/
public double calculateVolume()
{
return length * length * length;
}
} // Cube
28. Write a java class definition for a CubeUser object that will use the Cube
object defined in the previous exercise. This class should create three Cube
instances, each with a different side, and then report their respective surface
areas and volumes.
/*
* File: CubeUser.java
* Author: Java, Java, Java
* Description: This class creates 3 instances of the Cube
* class and prints their areas and volumes.
*/
public class CubeUser
{
/**
* main() -- creates instance of Cube and tests them
*/
public static void main(String argv[])
{
33
34
Cube cube1;
cube1 = new Cube(5);
Cube cube2;
cube2 = new Cube(10);
Cube cube3;
cube3 = new Cube(15);
System.out.println("Side length of cube1 is " + cube1.getLength());
System.out.println("Surface Area of cube1 is " + cube1.calculateSurfaceArea ());
System.out.println("Volume of cube1 is " + cube1.calculateVolume());
System.out.println("Side length of cube2 is " + cube2.getLength());
System.out.println("Surface Area of cube2 is " + cube2.calculateSurfaceArea ());
System.out.println("Volume of cube2 is " + cube2.calculateVolume());
System.out.println("Side length of cube3 is " + cube3.getLength());
System.out.println("Surface Area of cube3 is " + cube3.calculateSurfaceArea ());
System.out.println("Volume of cube3 is " + cube3.calculateVolume());
} // main()
} // CubeUser
29. Challenge: Modify your solution to the previous exercise so that it lets the user
input the side of the cube. Follow the example shown in section that shows how
to perform numeric input.
/*
* File: CubeUser2.java
* Author: Java, Java, Java
* Description: This class creates 3 instances of the Cube
* class and prints their areas and volumes. This version
* lets the user input the cubes sizes.
*/
import java.io.*;
public class CubeUser2
{
/**
* main() -- creates instance of Cube and tests them. This
* version uses a BufferedReader object to read the users
* keyboard input.
*/
public static void main(String args[]) throws IOException
{
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
String inputString;
int length;
System.out.println("Input the side length of cube1: ");
inputString = input.readLine();
length = Integer.parseInt(inputString);
Cube cube1 = new Cube(length);
35
30. Challenge: Define a Java class that represents an address book entry, Entry, which consists of a name, address, and phone number, all represented as
Strings. For the classs interface, define methods to set and get the values
of each of its instance variables. Thus, for the name variable, it should have a
setName() and a getName() method.
/*
* File: Entry.java
* Author: Java, Java, Java
* Description: This class represents an address book entry, with
* name, address and phone number.
*/
public class Entry
{
private String name;
// The entrys data
private String address;
private String phoneNumber;
/**
* setName() sets the name from the given String
* @param nameIn -- the string giving the name
*/
public void setName(String nameIn)
{
name = nameIn;
}
/**
* getName() returns the entrys name
*/
public String getName()
{
return name;
}
/**
* setAddress() sets the address from the given String
* @param nameIn -- the string giving the address
*/
public void setAddress(String addressIn)
{
address = addressIn;
}
/**
* getAddress() returns the entrys address
*/
public String getAddress()
{
return address;
}
/**
* setPhoneNumber() sets the phone number from the given String
* @param nameIn -- the string giving the phone number
*/
public void setPhoneNumber(String phoneIn)
{
phoneNumber = phoneIn;
}
/**
* getPhoneNumber() returns the entrys phone number
*/
public String getPhoneNumber()
{
return phoneNumber;
}
/**
* main() creates an Entry
*/
public static void main(String args[])
{
Entry entry = new Entry();
entry.setName("Lilly");
entry.setAddress("Dog House Lane");
36
37
entry.setPhoneNumber("123-456-7890");
System.out.println("Entry is " + entry.getName() + " "
+ entry.getAddress() + " "
+ entry.getPhoneNumber());
} // main()
} // Entry
31. Challenge: Write a Java class definition for a Temperature object that is
capable of reporting its temperature in either Fahrenheit or Celsius. This class
should have one instance variable called temperature and two public methods, one called getFahrenheit, which returns the temperature in Fahrenheit,
and one called getCelsius(), which returns the temperature in Celsius. This
method has to convert the stored temperature to Celsius before returning it. An
expression for converting Fahrenheit to Celsius is (5 (F 32)=9), where F is
the temperature in Fahrenheit.
/*
* File: Temperature.java
* Author: Java, Java, Java
* Description: This class converts temperatures from
* Fahrenheit to Celsius and vice versa. It stores the
* temperature in Fahrenheit.
*/
public class Temperature
{
private double temperature;
/**
* setTemperature() sets the temperature from the given temperature
* @param t -- the given temperature in Fahrenheit
*/
public void setTemperature(double t)
{
temperature = t;
}
/**
* getFahrenheit() returns the temperature as degrees
*/
public double getFahrenheit()
{
return temperature;
}
/**
* getCelsius() returns the temperature as degrees C
*/
public double getCelsius()
{
return 5*(temperature-32)/9;
}
/**
* main() creates a Temperature object and tests it
*/
public static void main(String args[])
{
Temperature t = new Temperature();
t.setTemperature(212);
// Set temp in Fahrenheit
System.out.println("Fahrenheit = " + t.getFahrenheit());
System.out.println("Celsius = " + t.getCelsius());
} // main()
} // Temperature
UML Exercises
32. Draw a UML class diagram to represent the following class hierarchy: There
are two types of languages, natural languages and programming languages. The
natural languages include Chinese, English, French, and German. The programming languages include Java, Smalltalk and C++, which are object-oriented languages, Fortran, Cobol, Pascal, and C, which are imperative languages, Lisp and
ML, which are functional languages, and Prolog, which is a logic language.
33. Draw a UML class diagram to represent different kinds of automobiles, including trucks, sedans, wagons, SUVs, and the names and manufacturers of some
popular models in each category.
34. Draw a UML object diagram of a triangle with attributes for three sides, containing the values 3, 4, and 5.
35. Suppose you are writing a Java program to implement an electronic address
book. Your design is to have two classes, one to represent the user interface
and one to represent the address book. Draw a UML diagram to depict this relationship. See Text Figure 2-3.
36. Draw an UML object diagram to depict the relationship between an applet, that
serves as a user interface, and three Triangles, named t1, t2 and t3.
37. Suppose we add as isThinking attribute to the CyberPet class with a corresponding new think() behavior. Draw a UML class diagram to represent
this version of CyberPet.
38
Exercise 2.18
39
Exercise 2.23
NumberAdder
-num1 : double
-num2 : double
+setNums(in n1 : double, in n2 : double)
+getSum() : double
+main()
CyberPet
-num : double
+tellMeYourName()
+eat()
+sleep()
+main()
Exercise 2.27
Exercises 2.28, 2.29
Cube
-length : double
Exercise 2.30
CubeUser
+Cube(in l : double)
+getLength() : double
+calculateSurfaceArea() : double
+calculateVolume() : double
Entry
Uses
-name : String
-address : String
-phoneNumber : String
+main()
Cube
-length : double
Exercise 2.31
+Cube(in l : double)
+getLength() : double
+calculateSurfaceArea() : double
+calculateVolume() : double
Temperature
-temperature : double
+setTemperature(in t : double)
+getFahrenheit() : double
+getCelsius() : double
+main()
Exercise 2.34
Exercise 2.35
: Triangle
BookInterface
side1 : double = 3
side2 : double = 4
side3 : double = 5
AddressBook
+main()
Triangle
Exercise 2.37
Exercise 2.36
CyberPet
Uses
t1 : Triangle
Uses
Applet
t2 : Triangle
Uses
t3 : Triangle
Uses
Exercise 2.32
Language
NaturalLanguage
ProgrammingLanguage
English
Chinese
40
German
ObjectOrientedLanguage
ImperativeLanguage
FunctionalLanguage
LogicLanguage
French
Java
C++
SmallTalk
Exercise 2.33
FORTRAN
C
Pascal
Automobile
Truck
Sedan
ToyotaCamry
COBOL
NissanAltima
VWPassat
NissanMaxima
Stationwagon
SUV
Volvo740
ToyotaRav4
Volvo240
VWPassat
Volvo850
ML
Lisp
Prolog
Chapter 3
. Answer:
access. Answer:
access.
. Answer: void
control
42
43
(b)
if (isWalking)
System.out.println("Walking")
// Syntax Error: Semicolon missing here
else
System.out.println("Not walking");
(c)
if (isWalking)
System.out.println("Walking");
else
System.out.println("Not walking") // Syntax Error: Semicolon missing here
(d)
if (isWalking = false)
// Syntax Error: = is not equality operator
System.out.println("Walking");
else
System.out.println("Not walking");
5. For each of the following, suppose that isWalking is true and isTalking
is false. First draw a flowchart for each statement and then determine what
would be printed by each statement.
(a)
if (isWalking == false)
System.out.println("One");
System.out.println("Two");
Output: Two
(b)
if (isWalking == true)
System.out.println("One");
44
45
System.out.println("Two");
Output: One
Two
(c)
if (isWalking == false)
{
System.out.println("One");
System.out.println("Two");
}
Output: No output
(d)
if (isWalking == false)
if (isTalking == true)
System.out.println("One");
else
System.out.println("Two");
else
System.out.println("Three");
Output: Three
6. Show what would be output if the following version of main() method were
executed.
public static void main(String
{
System.out.println("main()
CyberPet pet1;
pet1 = new CyberPet();
CyberPet pet2;
pet2 = new CyberPet();
pet1.setName("Mary");
pet2.setName("Peter");
pet1.eat();
pet1.sleep();
pet2.sleep();
pet2.eat();
System.out.println("main()
return;
}
Output: main() is starting
Mary is eating
Mary is sleeping
Peter is sleeping
argv[])
//
is starting");
//
//
//
//
//
//
is
//
Peter is eating
main() is finished
7. Dangling else. For each of these unindented statements, first draw a flowchart of
the statement and then determine its output assuming that isWalking is true
and isTalking is false. Then rewrite the statements using proper indentation
techniques. Recall that according to the syntax of the if-else statement an else
matches the closest previous unmatched if.
(a)
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else
System.out.println("Two");
System.out.println("Three");
Properly indented:
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else
System.out.println("Two");
System.out.println("Three");
Output: Two
Three
(b)
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else {
System.out.println("Two");
System.out.println("Three");
}
Properly indented:
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else {
System.out.println("Two");
System.out.println("Three");
}
Output: Two
Three
(c)
if (isWalking == true) {
46
47
if (isTalking == true)
System.out.println("One");
}
else {
System.out.println("Two");
System.out.println("Three");
}
Properly indented:
if (isWalking == true) {
if (isTalking == true)
System.out.println("One");
}
else {
System.out.println("Two");
System.out.println("Three");
}
Output: No output
(d)
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else
System.out.println("Two");
else
System.out.println("Three");
Properly indented:
if (isWalking == true)
if (isTalking == true)
System.out.println("One");
else
System.out.println("Two");
else
System.out.println("Three");
Output: Two
48
What output would be produced by the following statements? Recall the distinction between pass by value and pass by reference.
CyberPet pet1 = new CyberPet("Socrates");
boolean isSocrates = true;
System.out.println(pet1.getState());
myMethod(pet1, isSocrates);
if (isSocrates == true)
System.out.println(" Socrates");
else
System.out.println(" NOT Socrates");
System.out.println(socrates.getState());
Output: Eating
Socrates
Sleeping
49
10. Write a boolean method a method that returns a boolean that takes
an int parameter and converts the integers 0 and 1 into false and true,
respectively.
/**
* myMethod() converts its int parameter to a boolean
* @param n -- an int, usually either 0 or 1
* @return -- a boolean giving true when n is 1 and false otherwise
*/
public boolean myMethod(int n)
{
if (n == 1)
return true;
else
return false;
}
11. Define an int method that takes a boolean parameter. If the parameters value
is false, the method should return 0; otherwise it should return 1.
/**
* myMethod() converts its boolean parameter to an int
* @param b -- a boolean
* @return -- a int giving 0 if b is false and 1 otherwise
*/
public int myMethod(boolean b)
{
if (b == false)
return 0;
else
return 1;
}
12. Define a void method named hello that takes a single boolean parameter.
The method should print Hello if its parameter is true; otherwise it should print
Goodbye.
/**
* hello() prints hello when its parameter is true or else goodbye
* @param b -- a boolean
*/
public void hello(boolean b)
{
if (b == true)
System.out.println("Hello");
else
System.out.println("Goodbye");
}
50
13. Define a method named hello that takes a single boolean parameter. The
method should return Hello if its parameter is true; otherwise it should return
Goodbye. Note the difference between this method and the one in the previous
exercise. This one returns a String. That one was a void method.
/**
* hello() returns hello when its parameter is true or else goodbye
* @param b -- a boolean
* @return -- a String giving either hello or goodbye
*/
public String hello(boolean b)
{
if (b == true)
return "Hello";
else
return "Goodbye";
}
14. Write a method named hello that takes a single String parameter. The
method should return a String that consists of the word Hello concatenated
with the value of its parameter. For example, if you call this method with the
expression hello(" dolly"), it should return hello dolly. If you call it
with hello(" young lovers wherever you are"), it should return
hello young lovers wherever you are.
/**
* hello() returns hello plus its parameter
* @param s -- a String, usually giving a name
* @return -- a String giving hello x where x is the value of s
*/
public String hello(String s)
{
return "Hello" + s;
}
15. Define a void method named day1 that prints a partridge in a pear tree.
/**
* day1() prints a string
*/
public void day1()
{
System.out.println(" a partridge in a pear tree");
}
16. Write a Java application program called TwelveDays that prints the Christmas
carol Twelve Days of Christmas. For this version, write a void method name
51
52
intro() that takes a single String parameter that gives the day of the verse
and prints the intro to the song. For example, intro("first"), should print,
On the first day of Christmas my true love gave to me. Then write methods
day1(), day2(), and so on, each of which prints its version of the verse. Then
write a main() method that calls the other methods to print the whole song.
/*
* File: TwelveDays.java
* Author: Java, Java, Java
* Description: This class sings the Twelve Days of
* Christmas carol. Its methods are named dayX(),
* where X is one of the 12 days. Each such method
* prints the verse for that day and then calls the
* previous day. So day2() will call day1().
*/
public class TwelveDays
{
public void intro(String d)
{
System.out.println();
System.out.println("On the " + d + " day of Christmas my true love gave to me,");
}
public void day1()
{
System.out.println("a partridge in a pear tree.");
}
public void day2()
{
System.out.println("two turtle doves, and ");
day1();
}
public void day3()
{
System.out.println("three french hens,");
day2();
}
public void day4()
{
System.out.println("four calling birds,");
day3();
}
public void day5()
{
System.out.println("five gold rings,");
day4();
}
public void day6()
{
System.out.println("six geese a laying,");
day5();
}
public void day7()
{
System.out.println("seven swans a swimming,");
day6();
}
public void day8()
{
System.out.println("eight maids a milking,");
day7();
}
public void day9()
{
System.out.println("nine ladies dancing,");
day8();
}
public void day10()
{
System.out.println("ten pipers piping,");
day9();
}
public void day11()
{
System.out.println("eleven lords a leaping,");
day10();
}
public void day12()
{
System.out.println("twelve pizzas baking,");
day11();
}
public static void main(String argv[])
{
TwelveDays song = new TwelveDays();
song.intro("first");
song.day1();
53
54
song.intro("second");
song.day2();
song.intro("third");
song.day3();
song.intro("fourth");
song.day4();
song.intro("fifth");
song.day5();
song.intro("sixth");
song.day6();
song.intro("seventh");
song.day7();
song.intro("eighth");
song.day8();
song.intro("ninth");
song.day9();
song.intro("tenth");
song.day10();
song.intro("eleventh");
song.day11();
song.intro("twelfth");
song.day12();
} // main()
}// TwelveDays
17. Define a void method named verse that takes two String parameters and
returns a verse of the Christmas carol, Twelve Days of Christmas. For example, if you call this method with verse("first", "a partridge in a
pear tree"), it should return, On the first day of Christmas my true love
gave to me, a partridge in a pear tree.
/*
* File: TwelveDaysLine
* Author: Java, Java, Java
* Description: This class tests the verse() method.
*/
public class TwelveDaysLine
{
/**
* verse() returns a verse of the Twelve Days carol
* @return -- a String giving the verse
*/
public String verse(String day, String gift)
{
return "On the " + day + " day of christmas my true love gave to me " + gift;
}
/**
55
18. Define a void method named permute, which takes three String parameters and prints out all possible arrangements of the three strings. For example, if
you called permute("a","b","c"), it would produce the following output:
abc, acb, bac, bca, cab, cba, with each permutation on a separate line.
/*
* File: Permute.java
* Author: Java, Java, Java
* Description: This class contains a permute() method
* which prints all possible permutations of its three
* parameters.
*/
public class Permute
{
/**
* permute() prints the permutations of a, b, and c,
* its three String parameters
*/
public void permute(String a, String b, String c)
{
System.out.println(a + b + c);
System.out.println(a + c + b);
System.out.println(b + a + c);
System.out.println(b + c + a);
System.out.println(c + a + b);
System.out.println(c + b + a);
} //permute
/**
* main() creates an instance and tests the permute() method
*/
public static void main(String strv[])
{
Permute abc = new Permute();
abc.permute("a","b","c");
} // main()
} // Permute
19. Design a method that can produce limericks given a bunch of rhyming words.
For example, if you call
56
limerick("Jones","stones","rained","pained","bones");
/*
* File: Limerick.java
* Author: Java, Java, Java
* Description: This class "sings" a limerick. The
* limericks content can be varied by providing
* different keywords to the limerick() method.
*/
public class Limerick
{
/**
* sing() prints the limerick, substituting its parameters
* as the key rhyming words
* @param name -- a String giving a persons name
* @param noun -- a String giving an object that the person likes
* @param verb -- a String giving a name for a weather condition
* @param adjective -- a String giving a name for the persons mood
* @param noun2 -- a String giving a name for the persons body part
*/
public void sing(String name, String noun, String verb, String adjective, String noun2)
{
System.out.println("There once was a person named " + name + ",");
System.out.println("Who had a great liking for " + noun + ",");
System.out.println("But whenever it " + verb + ",");
System.out.println(name + " expression was " + adjective + ",");
System.out.println("Because " + noun + " werent good for the " + noun2 + ",");
} // limerick()
/**
* main() creates a Limerick instance and tests it on a
* couple of examples.
*/
public static void main(String argv[])
{
20. Write a constructor method that can be used to set both the name and initial state
of a CyberPet.
/**
* CyberPet() constructor sets the pets name from its parameter
* @param petName -- a String giving the pets name
*/
public CyberPet(String petName)
{
name = petName;
isEating = true;
isSleeping = false;
}
21. Write a constructor method that can be used to set a pets initial state to something besides its default state. (Hint: Use boolean variables.)
/**
* CyberPet() constructor sets the pets name and state
* from its parameters
* @param petName -- a String giving the pets name
* @param eating -- a boolean set to true if the pet is eating
*/
public CyberPet(String petName, boolean eating)
{
name = petName;
isEating = eating;
// This sets isEating to True or False
if (isEating)
// This sets isSleeping to the
isSleeping = false; // opposite of isEating
else
isSleeping = true;
}
22. Extend the definition of CyberPet so that a pets state can have three possible
values: eating, sleeping, and thinking. Modify any existing methods that need to
be changed, and add the appropriate access methods for the new state.
/*
* File: CyberPet.java
* Author: Java, Java, Java
* Description: This class simulates a pet that can
57
58
*/
public void sleep()
{
isSleeping = true;
isEating = false;
isThinking = false;
return;
} // sleep()
// Start Sleeping
// Change the state
/**
* think() puts the pet in the thinking state
*/
public void think()
// Start Thinking
{
isSleeping =false;
// Change the state
isEating = false;
isThinking = true;
return;
} // think()
/**
* getState() returns a representation of the pets state
* @return -- a String giving the pets state
*/
public String getState ()
{
if (isEating)
return "Eating"; // Exit the method
if (isSleeping)
return "Sleeping"; // Exit the method
if (isThinking)
return "Thinking";
return "Error in State"; // Exit the method
} // getState()
} // CyberPet
/*
* File: TestCyberPet.java
* Author: Java, Java, Java
* Description: This class serves as an interface to
* the CyberPet class. It creates two CyberPet instances
* and invokes methods to set and report their states.
*/
public class TestCyberPet
{
public static void main (String argv[])
{
CyberPet pet1;
// Declare CyberPet variables
CyberPet pet2;
59
60
23. Challenge. Add a size instance variable to CyberPet, making certain it can
be set to either big or small through a constructor or an access method.
Then write an encounter(CyberPet) method that allows one CyberPet
to encounter another. Note that the method should take a CyberPet parameter.
Depending on the size of the pet, the small pet should be chased by the larger pet
or the two should befriend each other. This encounter should be described with
a returned String. For example, if you create two pets such that pet1 is big
and pet2 is small, and then you invoke pet1.encounter(pet2), it should
return something like Im going to eat you.
/*
* File: CyberPet.java
* Author: Java, Java, Java
* Description: This class simulates a pet that can
* eat, sleep, and tell its name upon command. This
* version also has a size variable, and an encounter()
* method that simulates an encounter with another CyberPet.
*/
public class CyberPet
{
private boolean isEating = true; // CyberPets state
private boolean isSleeping = false;
private String name = "no name"; // CyberPets name
private boolean bigSize; // CyberPets size
/**
* CyberPet() constructor sets the pets name its parameter
/**
* getName() returns a string giving the pets name
* @return a String giving the pets name
*/
public String getName()
{
return name;
// Return CyberPets name
} // getName()
/**
* getSize() returns a string giving the pets size
* @return a String giving the pets size
*/
public String getSize() // Access method
{
if (bigSize)
return "Big";
if (bigSize == false)
return "Small";
return "Error in Size";
} // getSize()
/**
* isBig() returns true iff the pet is big
*/
public boolean isBig()
{
if (bigSize)
return true;
else
return false;
} // isBig()
61
/**
* setSizeToBig() sets the pets size from its parameter
* @param big -- true means big size, false means small
*/
public void setSizeToBig(boolean big)
// Set Size
{
bigSize = big;
} // setSize()
/**
* eat() puts the pet in the eating state
*/
public void eat()
// Start Eating
{
isEating = true;
// Change the state
isSleeping = false;
return;
} // eat()
/**
* sleep() puts the pet in the sleeping state
*/
public void sleep()
// Start Sleeping
{
isSleeping = true;
// Change the state
isEating = false;
return;
} // sleep()
/**
* getState() returns a representation of the pets state
* @return -- a String giving the pets state
*/
public String getState ()
{
if (isEating)
return "Eating"; // Exit the method
if (isSleeping)
return "Sleeping"; // Exit the method
return "Error in State"; // Exit the method
} // getState()
public String encounter(CyberPet pet)
{
System.out.println(name + " encounters " + pet.getName());
if (pet.isBig() == false)
{
if (isBig())
// if encountered pet is smaller, attack
return "I am going to eat you.";
if (isBig() == false)
62
63
return "Lets be friends."; // if pets are the same size, befriend the pet
}
if (pet.isBig() == true)
{
if (isBig())
return "Lets be friends."; // if pets are the same size, befriend the pet
if (isBig() == false)
return "Please dont eat me."; // if encountered pet is larger, beg
}
return "I dont know what to do.";
} // encounter()
} // CyberPet
/*
* File: TestCyberPet.java
* Author: Java, Java, Java
* Description: This class serves as a user interface to
* the CyberPet class. It creates two CyberPet instances
* and sets their sizes to big or small. Then it simulates
* various encounters between the two. Big pets tend to
* terrorize small pets. Same size pets tend to befriend
* each other.
*/
public class TestCyberPet
{
public static void main (String argv[])
{
CyberPet pet1;
// Declare CyberPet variables
CyberPet pet2;
pet1 = new CyberPet("Socrates");
// Create pet1 named "Socrates"
pet2 = new CyberPet("Plato");
// Create pet2 named "Plato"
// Print the pets names and states
System.out.println(pet1.getName() + " is "
System.out.println(pet2.getName() + " is "
pet1.eat();
// Tell pet1 to
pet2.sleep();
// Tell pet2 to
+ pet1.getState());
+ pet2.getState());
eat
sleep
64
For each of the following exercises, write a complete Java application program.
24. Define a class named Donor that takes has two instance variables, the donors
name and rating, both Strings. The name can be any string, but the rating
should be one of the following values: high, medium, or none. Write the
following methods for this class: a constructor, Donor(String,String),
that allows you to set both the donors and rating; and access methods to set and
get both the name and rating of a donor.
/*
* File: Donor.java
* Author: Java, Java, Java
* Description: This class represents a donor to an
* organization. It stores the donors name and rating.
* The main() method tests the classs methods.
*/
public class Donor
{
private String name = "no name";
private String rating = "none";
65
/**
* Donor() constructor sets the objects name and rating
* @param str -- a String giving the donors name
* @param str2 -- a String giving the donors rating
*/
public Donor(String str, String str2)
{
name = str;
rating = str2;
}
/**
* getName() returns the donors name
* @return a String giving the persons name
*/
public String getName()
{
return name;
}
/**
* getRating() returns the donors rating
* @return a String giving the persons rating
*/
public String getRating()
{
if (rating.equals ("high"))
return "high";
if (rating.equals ("medium"))
return "medium";
else
return "none";
}
/**
* main() creates three Donor instances and tests this
* classes methods.
*/
public static void main (String argv[])
{
Donor donor1 = new Donor("NewDonor", "high");
System.out.println("Donors name is " + donor1.getName());
System.out.println(donor1.getName() + "s rating is " + donor1.getRating());
Donor donor2 = new Donor("NewDonor2", "medium");
System.out.println("Donors name is " + donor2.getName());
System.out.println(donor2.getName() + "s rating is " + donor2.getRating());
Donor donor3 = new Donor("NewDonor3", "unknown");
System.out.println("Donors name is " + donor3.getName());
66
25. Challenge. Define a CopyMonitor class that solves the following problem.
A company needs a monitor program to keep track of when a particular copy
machine needs service. The device has two important (boolean) variables: its
toner level (too low or not) and whether it has printed more than 100,000 pages
since its last servicing (it either has or has not). The servicing rule that the
company uses is that service is needed when either 100,000 pages have been
printed or the toner is too low. Your program should contain a method that
reports either service needed or service not needed based on the machines
state. (Pretend that the machine has other methods that keep track of toner level
and page count.)
/*
* File: CopyMoniter.java
* Author: Java, Java, Java
* Description: This class simulates a copy machine monitor.
* It has boolean variables to keep track of whether its
* toner is too low or whether it has exceeded its page
* limit. Its serviceNeeded() method reports whether or
* not service is needed.
*/
public class CopyMoniter
{
private boolean tonerTooLow = false;
private boolean printed100000Pages = false;
/**
* setVariables() sets the monitors boolean instance variables
* @param tonerLow -- true if the toner is too low
* @param pageCountHigh -- true if the page count is too high
*/
public void setVariables(boolean tonerLow, boolean pageCountHigh)
{
tonerTooLow = tonerLow;
printed100000Pages = pageCountHigh;
}
/**
* serviceNeeded() reports whether the machine requires
* servicing based on a check of its toner and page count
* @return a String reporting the service status
*/
public String serviceNeeded()
{
if (tonerTooLow)
26. Challenge. Design and write an OldMacdonald class that sings several verses
of Old MacDonald Had a Farm. Use methods to generalize the verses. For
example, write a method named eieio() to sing the E I E I O part of
the verse. Write another method with the signature hadAnX(String s),
which sings the had a duck part of the verse, and a method withA(String
sound) to sing the with a quack quack here part of the verse. Test your class
by writing a main() method.
/*
* File: OldMacdonald.java
* Author: Java, Java, Java
* Description: This version of OldMacdonald uses parameters
* in the singVerse() method to generalize the song. By
* substituting arguments for the parameters when singVerse()
* is called, singVerse() can be used to sing an unlimited
* number of different verses.
*/
public class OldMacdonald
{
/**
* singVerse() sings a verse of Old Macdonald
* @param animal -- a String giving the name of an animal
* @param sound -- a String giving a sound made by the animal
*/
public void singVerse(String animal, String sound)
{
System.out.println("Old Macdonald had a farm");
67
System.out.println("E I E I O");
System.out.println("And on his farm he had a " + animal);
System.out.println("E I E I O");
System.out.println("With a " + sound + " " + sound + " here," );
System.out.println("And a " + sound + " " + sound + " there," );
System.out.println("Here a " + sound + ", there a " + sound
+ ", everywhere a " + sound + " " + sound);
System.out.println("Old Macdonald had a farm");
System.out.println("E I E I O");
}
/**
* main() creates an instance of this class and calls the
* singVerse() method with different arguments to produce
* two verses of Old MacDonald
*/
public static void main(String argv[])
{
OldMacdonald mac = new OldMacdonald();
mac.singVerse("duck", "quack");
mac.singVerse("cow", "moo");
} // main()
} // OldMacdonald
Additional Exercises
27. Modify the design of the Rectangle class to contain public methods to set and
get a rectangles length and width. Draw a UML class diagram to depict this new
design.
28. Draw a UML object diagram to depict an interaction between a user interface object and two rectangles, in which the interface sets the length setLength()
of each rectangle to a different value.
29. Suppose you have an Object A, with public methods a(), b(), and private
method c(). And suppose you have a subclass of A named B with methods
named b(), c() and d(). Draw a UML diagram showing the relationship
between these two classes. Explain the inheritance relationships between them
and identify those methods which would be considered polymorphic.
Answer: The method b() is polymorphic. It will have different behavior for
an object of class A and an object of class B. Class B inherits methods a() and
b() because they are public. The private method A.c() is not inherited by B.
30. Consider the definition of the class C. Define a subclass of C named B that overrides method m1() so that it returns the difference between m and n instead of
their sum.
public class C {
68
private int m;
private int n;
public C(int mIn, int nIn) {
m = mIn;
n = nIn;
}
public int m1() {
return m+n;
}
}
69
70
Exercise 3.16
Exercise 3.22
TwelveDays
Exercise 3.23
CyberPet
CyberPet
+intro(in d : String)
+day1()
+day2()
+day3()
+day4()
+day5()
+day6()
+day7()
+day8()
+day9()
+day10()
+day11()
+day12()
+main()
Exercise 3.25
CopyMonitor
-tonerTooLow : boolean = false
-printed100000pages : boolean = false
Exercise 3.24
Donor
Exercise 3.26
OldMacDonald
Exercise 3.27
Rectangle
-length : double
-width : double
Exercise 3.28
userInterface
setLength(10)
setLength(15)
Exercise 3.29
Exercise 3.30
A
+a()
+b()
-c()
C
-m : int
-n : int
+C(in mIn : int, in nIn : int)
+m1() : int
B
+b()
+c()
+d()
rect1
B
+m1() : int
rect2
Chapter 4
method. abstract
a class and
from the Java
or
(h) The Button, TextField and Component classes are defined in the
package. Answer: java.awt
(i) Java applets utilize a form of control known as
swer: event driven
(j) When the user clicks on an applets Button, an
be generated. Answer: ActionEvent
and
. An-
. Answer: Panel
71
72
4. Arrange the Java AWT library classes listed in the Chapter Summary into their
proper hierarchy, using the Object class as the root of the hierarchy.
5. Look up the documentation for the Button class on Suns Web site, and list the
names of all the methods that are inherited by its ToggleButton subclass.
addNotify()
getLabel()
setLabel()
setActionCommand()
getActionCommand()
addActionListener()
removeActionListener()
processEvent()
processActionEvent()
paramString()
6. Suppose we want to set the text in our applets TextField. What method
should we use and where is this method defined? (Hint: Look up the documentation for TextField. If no appropriate method is defined there, see if it is
inherited from a superclass.)
Answer: The setText() method should be used. It is defined in the TextComponent class and overridden in the TextField class.
7. Does an Applet have an init() method? Explain.
Answer: Yes. The init() method is defined as a stub method in the Applet
class.
73
Figure 4.2: Exercise 4: Part of the AWT hierarchy, plus the Applet class.
74
75
13. Javas Object class contains a public method, toString(), which returns a
string that represents this object. Because every class is a subclass of Object,
the toString() method can be used by any object. Show how you would
invoke this method for a Button object named button.
button.toString()
14. The following applet contains a semantic error in its init() method. The error
will cause the actionPerformed() method never to display Clicked even
though the user clicks on the button in the applet. Why? (Hint: Think scope!)
public class SomeApplet extends Applet
{
// Declare instance variables
private Button button;
public void init()
{
// Instantiate the instance variable
Button button = new Button("Click me");
add(button);
button.addActionListener(this);
} // init()
// Error
Answer: The Button declared in the init() and assigned an ActionListener there, has local scope. So it cannot be referred to in the actionPerformed() method.
15. What would be output by the following applet?
public class SomeApplet extends Applet
{
// Declare instance variables
private Button button;
private TextField field;
public void init()
{
// Instantiate instance variables
button = new Button("Click me");
add(button);
field = new TextField("Field me");
add(field);
System.out.println(field.getText() + button.getText());
} // init()
} // SomeApplet
Answer: A new button would be created with the text Click me, and a new
field would be created with the text Field me. A line of output saying Field
me Click me would also be created.
16. Modify the ToggleTest applet so that it displays an image of a light bulb in
the on or off state on alternate clicks of its lightSwitch.
Figure 4.3: This version of ToggleTest displays an on/off lightbulb image each time
its button is clicked.
/*
* File: ToggleTest.java
* Author: Java, Java, Java
* Description: This class provides an applet interface
* to test the ToggleButton. When clicked the toggle
* button displays one of two images and changes its
* label from "off" to "on" and vice versa.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ToggleTest extends Applet implements ActionListener
{
private ToggleButton lightSwitch;
private Image lightOn, lightOff; //Declare two image variables
/**
76
77
*
*
*
*
*
*/
import java.awt.*;
import java.awt.event.*;
public class ToggleButton extends Button implements ActionListener
{
private String label1;
// Two Labels to toggle between
private String label2;
/**
* ToggleButton() constructor stores its parameters as the
* buttons alternative labels. It uses the first label, l1,
* as its default label. Note that it starts by calling the
* superclass constructor, which creates a Button with label
* l1. The call to the superclass must be the first statement
* in the method.
* @param l1 -- a String giving the buttons primary label
* @param l2 -- a String giving the buttons secondary label
*/
public ToggleButton(String l1, String l2) // Constructor method
{
super(l1);
// Use l1 as the default label
label1 = l1;
label2 = l2;
addActionListener(this);
}
/**
* actionPerformed() swaps this buttons labels. Note
* that it must use a temporary variable to perform the swap.
*/
public void actionPerformed(ActionEvent e)
{
String tempS = label1; // Swap the labels
label1 = label2;
label2 = tempS;
ToggleButton.this.setLabel(label1);
} // actionPerformed()
} // ToggleButton
17. Write a simple Java applet that creates a Button, a TextField, and a Label.
Add statements to the init() method that use the toString() method to
display each objects string representation.
78
Figure 4.4: This applet displays the default toString() representations of its various components.
/*
* File: ToStringApplet.java
* Author: Java, Java, Java
* Description: This applet illustrates the Object.toString()
* method. Since every class is a subclass of Object, every
* class inherits the Object.toString(). However, the default
* version of this method is not necessarily appropriate for
* the subclass. In that case, the method can be overridden
* in the subclass. In this case we display the default
* behavior for a Button, TextField and Label object.
*/
import java.applet.Applet;
import java.awt.*;
public class ToStringApplet extends Applet
{
private Button button;
private TextField field;
private Label label;
/**
* init() creates the objects and prints their toString()
* results
*/
public void init()
{
button = new Button("Click Me");
field = new TextField("Field Me");
label = new Label("Label Me");
add(button);
add(field);
79
add(label);
System.out.println(button.toString());
System.out.println(field.toString());
System.out.println(label.toString());
} // init()
} // ToStringApplet
18. Modify the SimpleApplet program so that it contains a second button labeled
initially The Doctor is in. Modify the actionPerformed() method so that
every time the user clicks on a button, its label is toggled. The label on the second
button should toggle to The Doctor is out.
Figure 4.5: This version of SimpleApplet contains two buttons that toggle between
their pairs of labels.
/*
* File: SimpleApplet.java
* Author: Java, Java, Java
* Description: This applet contains two buttons that
* toggle between their two sets of labels.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleApplet extends Applet implements ActionListener
{
private Button toggle;
// From java.awt.*
private Button toggle2;
/**
* init() sets up the applets interface. It creates
* the buttons and assigns them an action listener.
*/
80
81
19. Modify the SimpleApplet program so that it contains two Buttons, initially labeled Me first! and Me next! Modify the actionPerformed()
method so that every time the user clicks on either one of the buttons, the labels
on both buttons are exchanged. (Hint: You dont need an if-else statement for
this problem.)
/*
* File: SimpleApplet.java
* Author: Java, Java, Java
* Description: This applet creates two buttons labeled
* "me first" and "me next". Whenever one of the other
* button is clicked, it exchanges the labels on both
* buttons.
Figure 4.6: This version of SimpleApplet modifies the labels on two different buttons each time either button is clicked.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleApplet extends Applet implements ActionListener
{
private Button button1;
// From java.awt.*
private Button button2;
/**
* init() initializes the applets interface by creating
* the two buttons and assigning them action listeners.
*/
public void init()
{
button1 = new Button ("Me first");
button1.addActionListener(this);
add(button1);
button2 = new Button ("Me next");
button2.addActionListener(this);
add(button2);
} // init()
/**
* actionPerformed() handles button clicks on either button.
* Button.getLabel() and setLabel() are used to retrieve
* their respective labels and exchange them.
* @param e -- the ActionEvent that triggered this method call
*/
public void actionPerformed(ActionEvent e)
{
82
20. Modify the SimpleApplet program so that it contains three Buttons, initially labeled First, Second, and Third. Modify the actionPerformed()
method so that every time the user clicks on one of the buttons, the labels on the
buttons are rotated. Second should get firsts label, third should get seconds, and
first should get thirds label.
Figure 4.7: This version of SimpleApplet switches the labels on three different
buttons each time either button is clicked.
/*
* File: SimpleApplet.java
* Author: Java, Java, Java
* Description: This applet creates three buttons labeled
* "first", "second", and "third". Whenever one of the other
* button is clicked, it exchanges the labels on all three
* buttons.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class SimpleApplet extends Applet implements ActionListener
{
private Button button1;
// From java.awt.*
private Button button2;
private Button button3;
private String label1;
83
84
Figure 4.8: This version of SimpleApplet displays the buttons label in a textfield
each time it is clicked.
* File: SimpleApplet.java
* Author: Java, Java, Java
* Description: This applet creates two buttons labeled
* "first" and "second". Whenever one of the
* buttons is clicked, its label is displayed in the text field.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class SimpleApplet extends Applet implements ActionListener
{
private Button button1;
// From java.awt.*
private Button button2;
private String label1;
private String label2;
private TextField field;
/**
* init() initializes the applets interface by creating
* the two buttons and assigning them action listeners
* and labels. It also creates a text field.
*/
public void init()
{
label1 = "Left";
label2 = "Right";
button1 = new Button(label1);
button2 = new Button(label2);
field = new TextField(12);
85
add(field);
add(button1);
add(button2);
button1.addActionListener(this);
button2.addActionListener(this);
} // init()
/**
* actionPerformed() handles button clicks on both buttons.
* field.setText() is used to set the text in the text field
* to the label of the button that was clicked.
* @param e -- the ActionEvent that triggered this method call
*/
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
field.setText(label1);
else if (e.getSource() == button2)
field.setText(label2);
} // actionPerformed()
} // SimpleApplet
22. You can change the size of an applet by using the setSize(int h, int v)
method, where h and v give the horizontal and vertical dimensions of the applets
window in pixels. Write an applet that contains two Buttons, labeled Big and
Small. Whenever the user clicks on small, set the applets dimensions to 200 x
100, and whenever the user clicks on big, set the dimensions to 300 x 200.
/*
* File: BigSmall.java
* Author: Java, Java, Java
* Description: This applet presents two buttons
86
*
*
*
*
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class BigSmall extends Applet implements ActionListener
{
private Button button1;
private Button button2;
/**
* init() instantiates the buttons, adds them to the applets
* window, and registers them with an ActionListener
*/
public void init()
{
button1 = new Button("Small");
button2 = new Button("Big");
add(button1);
add(button2);
button1.addActionListener(this);
button2.addActionListener(this);
}
/**
* actionPerformed() handles action events on the two
* buttons.
* @param e -- a representation of the ActionEvent
*/
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
setSize(200,100);
else if (e.getSource() == button2)
setSize(300,200);
} // actionPerformed()
} // BigSmall
23. Rewrite the size-adjusting applet in the previous exercise so that it uses a single
button, whose label is toggled appropriately each time it is clicked. Obviously,
when the Button is labeled Big, clicking it should give the applet its big
dimensions.
87
Figure 4.10: In this case a single button is used to change the applets size.
/*
* File: BigSmall.java
* Author: Java, Java, Java
* Description: This applet presents a single button
* that when clicked changes the applets size. Each
* time the button is clicked, its label is changed
* from "big" to "small" and vice versa depending on
* the applets current size. It may be necessary
* to run this with the appletviewer rather than
* with a browser to change the applets size.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class BigSmall extends Applet implements ActionListener
{
private Button button;
private String label1;
private String label2;
private boolean buttonIsBig = true; // Keeps track of button label
/**
* init() instantiates the button, adds it to the applets
* window, and registers it with an ActionListener
*/
public void init()
{
label1 = "Big";
label2 = "Small";
88
24. Challenge: Design and write an applet that allows the user to change the applets
background color to one of three choices, indicated by buttons. Like all other
Java Components, applets have an associated background color, which can be
set by the following commands:
setBackground( Color.red );
setBackground( Color.yellow );
89
Figure 4.11: In this applet buttons are used to change the applets background color.
/*
* File: ColorChanger.java
* Author: Java, Java, Java
* Description: This applet presents three buttons
* labeled red, blue and yellow. When one of the
* buttons is clicked, it changes the applets
* background color.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class ColorChanger extends Applet implements ActionListener
{
private Button button1; // Three buttons
private Button button2;
private Button button3;
/**
* init() creates the three buttons, adds them to the
* applet and registers them with an ActionListener
*/
public void init()
{
button1 = new Button("Red");
button2 = new Button("Yellow");
button3 = new Button("Blue");
add(button1);
add(button2);
add(button3);
button1.addActionListener(this);
button2.addActionListener(this);
90
button3.addActionListener(this);
} // init()
/**
* actionPerformed() handles clicks on the three buttons.
* The buttons are associated with the applets background color.
*/
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
setBackground( Color.red);
else if (e.getSource() == button2)
setBackground( Color.yellow);
else if (e.getSource() == button3)
setBackground( Color.blue);
} // actionPerformed()
} // ColorChanger
25. Challenge:
Modify CyberPet and CyberPetApplet so that CyberPet can eat two different things for example, a fly or a beetle. Your
interface design should allow the user to set the CyberPets food type. Whenever the CyberPet is eating, its state should be reported as Socrates is eating
a fly.
Figure 4.12: This version of the CyberPet applet is capable of eating two different
kinds of food.
/*
* File: CyberPet.java
91
/**
* CyberPet() constructor sets the pets name its parameter
* @param str -- a String giving the pets name
*/
public CyberPet (String str)
// Constructor method
{
name = str;
}
/**
* setName() sets the pets name from its parameter
* @param str -- a String giving the pets name
*/
public void setName (String str)
// Access method
{
name = str;
} // setName()
/**
* getName() returns the pets name
* @return a String giving the pets name
*/
public String getName()
{
return name;
// Return CyberPets name
} // getName()
/**
* eat() puts the pet in the eating state
*/
public void eat()
// Start eating
{
isEating = true;
// Change the state
isSleeping = false;
return;
92
} // eat()
/**
* sleep() puts the pet in the sleeping state
*/
public void sleep()
// Start sleeping
{
isSleeping = true;
// Change the state
isEating = false;
return;
} // sleep()
/**
* setFood() sets the pets food from its parameter
* @param foodString -- a String giving the name of food
*/
public void setFood (String foodString)
// Access method
{
food = foodString;
} // setFood()
/**
* getFood() returns the name of the pets food
* @return a String representing the food
*/
public String getFood()
{
return food;
// Return food
} // getFood()
/**
* getState() returns a representation of the pets state
* @return -- a String giving the pets state
*/
public String getState ()
{
if (isEating)
return "Eating " + food;
// Exit the method
if (isSleeping)
return "Sleeping";
// Exit the method
return "Error in State"; // Exit the method
} // getState()
/**
* toString() returns a String representation of the pets state
*/
public String toString()
{
return name + " is " + getState();
}
93
94
} // CyberPet
/*
* File: CyberPetApplet.java
* Author: Java, Java, Java
* Description: This applet creates a user interface to
* the CyberPet. The interface contains buttons, which
* can be used to order the pet to eat or sleep, and
* text fields that report the pets state and that
* can input the pets food.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class CyberPetApplet extends Applet implements ActionListener
{
// Declare instance variables
private CyberPet pet1;
// The CyberPet
private Label nameLabel;
// A Label
private TextField stateField;
// A TextField
private Button eatButton, sleepButton;
// Two Buttons
private TextField foodField;
// A TextField
private Label foodPrompt;
// A Label
/**
* init() sets up the applets interface. It instantiates the instance
* variables. This creates both the CyberPet, pet1, and the GUI
* elements that are displayed on the applet.
*/
public void init()
{
pet1 = new CyberPet("Socrates");
// CyberPet
// Create the GUI components
nameLabel = new Label("Hi! My name is " + pet1.getName() +
" and currently I am : ");
foodPrompt = new Label("Enter a food: ");
stateField = new TextField(20);
foodField = new TextField(12);
eatButton = new Button("Eat!");
// Buttons
eatButton.addActionListener(this);
// Assign the listeners.
sleepButton = new Button("Sleep!");
sleepButton.addActionListener(this);
// Initialize the TextFields
stateField.setText(pet1.getState());
95
stateField.setEditable(false);
foodField.setEditable(true);
// Add the components to the applet.
add(nameLabel);
add(stateField);
add(eatButton);
add(sleepButton);
add(foodPrompt);
add(foodField);
setSize(300,150);
} // init()
/*
* actionPerformed() gets called when one of the buttons is pressed
* @param e -- the ActionEvent that generated this method call
*/
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == eatButton)
{
pet1.eat();
pet1.setFood(foodField.getText());
}
else if (e.getSource() == sleepButton)
pet1.sleep();
stateField.setText(pet1.getState());
}//actionPerformed()
} // CyberPetApplet
Additional Exercises
26. Given the classes with the following headers
public
public
public
public
public
public
public
class
class
class
class
class
class
class
Animal ...
DomesticAnimal extends Animal ...
FarmAnimal extends DomesticAnimal...
HousePet extends DomesticAnimal...
Cow extends FarmAnimal ...
Goat extends FarmAnimal ...
DairyCow extends Cow ...
draw a UML class diagram representing the hierarchy created by these declarations.
Answer: See the UML diagrams at the end of this chapter.
27. Given the above hierarchy of classes, which of the following are legal assignment
statements?
DairyCow dc = new FarmAnimal();
FarmAnimal fa = new Goat();
Cow c1 = new DomesticAnimal();
Cow c2 = new DairyCow();
DomesticAnimal dom = new HousePet();
//
//
//
//
//
Error
Ok
Error
Ok
Ok
28. Following the rectangle-square example, design an Employee class with subclasses HourlyEmployee and Manager, such that each employee has inheritable attributes name of type String and id of type int, and an inherits method getName():String and setName(String). The subclasses
should also have the appropriate constructors that allow the employees id to be
set when an instance is created. Draw a UML diagram showing the details and
the relationships among these classes.
Answer: See the UML diagrams at the end of this chapter.
29. Extend the design in the previous exercise so that the Employee class contains an attribute for payrate and a polymorphic method calcPay(). This
method must be polymorphic because the way an employees pay is calculated
depends on whether the employee is a manager or an hourly employee.
Answer: See the UML diagrams at the end of this chapter.
30. Suppose you have a Java interface named Drawable that contains the polymorphic method draw(). This interface is meant to be used for drawing geometric
objects. Design a subclass of Rectangle named DrawableRectangle that
implements the Drawable interface and represent your design in a UML diagram.
Answer: See the UML diagrams at the end of this chapter.
31. Suppose you have a Java interface named Scalable that contains the polymorphic methods enlarge(double) and reduce(double). These methods
are meant to enlarge or reduce the size of a geometric object by some factor.
Modify you design of DrawableRectangle so that it also implements the
Scalable interface.
Answer: See the UML diagrams at the end of this chapter.
32. Write an implementation of the enlarge(double) method for the DrawableRectangle class in the previous exercise.
/**
* enlarge() enlarges the size of its object. This implementation assumes
* the object has a size variable.
96
* @param scale -- the factor by which to enlarge the object (e.g., 0.5 = 50 percent)
*/
public void enlarge(double scale) {
size = size + size * scale;
}
33. Write an implementation of the reduce(double) method for the DrawableRectangle class in the previous exercise.
/**
* reduce() reduces the size of its object. This implementation assumes
* the object has a size variable.
* @param scale -- the factor by which to reduce the object (e.g., 0.5 = 50 percent)
*/
public void enlarge(double scale) {
size = size - size * scale;
}
34. Suppose you have a Java applet that contains a Button and a TextField.
Each time the Button is clicked, it displays the time using the showTime()
method in the TextField. Draw a UML sequence diagram that depicts this
sequence of events.
Answer: See the UML diagrams at the end of this chapter.
97
Miscellaneous Classes
URL
AudioClip
Button
ActionEvent
Label
TextField
Image
Graphics
Exercise 4.3
Language
NaturalLanguage
English
FormalLanguage
Chinese
French
Java
Korean
Object
RomanceLanguage
C++
ClassicalLanguage
Italian
French
Latin
Greek
interface
ActionListener
Exercise 4.16
Exercise 4.4
98
+actionPerformed(in e : ActionEvent)
EventObject
Applet
Button
AWTEvent
Component
+init()
+toggleButton()
Label
Button
ToggleTest
ToggleButton
TextComponent
TextField
-label1 : String
-label2 : String
+toggleButton(in l1 : String, in l2 : String)
+actionPerformed(in e : ActionEvent)
-lightSwitch : ToggleButton
-lightOn : Image
-lightOff : Image
+init()
+paint(in g : Graphics)
+actionPerformed(in e : ActionEvent)
Uses
Exercise 4.20
Exercises 4.18, 4.19
Exercise 4.17
Applet
interface
ActionListener
+actionPerformed(in e : ActionEvent)
interface
ActionListener
+actionPerformed(in e : ActionEvent)
Applet
+init()
Applet
+init()
+init()
ToStringApplet
-button : ActionListener
-field : TextField
-label : Label
+init()
SimpleApplet
SimpleApplet
-toggle : Button
-toggle2 : Button
+init()
+actionPerformed(in e : ActionEvent)
-button1 : Button
-button2 : Button
-button3 : Button
-label1 : String
-label2 : String
-label3 : String
+init()
+actionPerformed(in e : ActionEvent)
Exercise 4.21
interface
ActionListener
Exercise 4.22
99
Exercise 4.23
interface
ActionListener
interface
ActionListener
+actionPerformed(in e : ActionEvent)
+actionPerformed(in e : ActionEvent)
+actionPerformed(in e : ActionEvent)
Applet
Applet
Applet
+init()
+init()
+init()
SimpleApplet
-button1 : Button
-button2 : Button
-label1 : String
-label2 : String
-field : TextField
BigSmall
BigSmall
-button1 : Button
-button2 : Button
+init()
+actionPerformed(in e : ActionEvent)
+init()
+actionPerformed(in e : ActionEvent)
-button : Button
-label1 : String
-label2 : String
-buttonIsBig : boolean = true
+init()
+actionPerformed(in e : ActionEvent)
Exercise 4.24
Exercise 4.26
Miscellaneous Classes
interface
ActionListener
Animal
URL
AudioClip
Button
ActionEvent
Label
TextField
+actionPerformed(in e)
DomesticAnimal
FarmAnimal
HousePet
Applet
+init()
Graphics
Image
Cow
ColorChanger
Goat
DairyCow
Exercise 4.25
+init()
+actionPerformed(in e : ActionEvent)
interface
ActionListener
+actionPerformed(in e : ActionEvent)
CyberPet
-isEating : boolean = true
-isSleeping : boolean = false
-name : String = "no name"
-food : String = "no food"
Applet
+init()
CyberPetApplet
-pet1 : CyberPet
-nameLabel : Label
-stateField : TextField
-eatButton : Button
-sleepButton : Button
-foodField : TextField
-foodPrompt : Label
-button1 : Button
-button2 : Button
-button3 : Button
+init()
+actionPerformed(in e : ActionEvent)
Uses
Exercise 4.30-4.31
Exercise 4.28-4.29
interface
Drawable
Employee
#name : String
#id : int
#payrate : double
+draw()
Rectangle
interface
Scalable
+enlarge(in scal : double)
+reduce(in scal : double)
DrawableRectangle
+draw()
+enlarge(in scale : double)
+reduce(in scale : double)
HourlyEmployee
Manager
Exercise 4.34
MyApplet
JavaVirtualMachine
100
MyTextField
MyButton
User Clicks
MyButton Clicked
actionPerformed()
showTime
Chapter 5
101
102
Exception
|
-- IOException
3. For each of the following data types, list how many bits are used in its representation and how many values can be represented:
(a)
int
(b) char
(c) byte
(d) long
(e) double
Answer: (a) 32, 232 (b) 16, 216 (c) 8, 28 (d) 64, 264 (e) 64, 264
4. Fill in the blank.
(a) Methods and variables that are associated with a class rather than with its
. Answer: static
instances must be declared
(b) When an expression involves values of two different types, one value must
be
before the expression can be evaluated. Answer: promoted
(c) Constants should be declared
. Answer: final
(d) Variables that take true and false as their possible values are known as
. Answer: boolean
5. Arrange the following data types into a promotion hierarchy: double, float,
int, short, long.
Answer: verbshort int long float double
103
6. Assuming that o1 is true, o2 is false, and o3 is false, evaluate each of the following expressions:
(a) o1 || o2 && o3
(b) o1 o2
(b) 11 / 2 % 2 > 0
(e) 15 / 3 == true
((11 / 3) % 2) == 1
==>
((11 / 2) % 2) > 0
==>
(15 % 3) >= (21 % 3)
==>
(12.0 / 4.0) >= (12 / 3) ==>
(15 / 3) == true
==>
(c) 15 % 3 >= 21 % 3
true
true
true
false
invalid
10. What value would m have after each of the following statements is executed?
Assume that m, k, j are reinitialized before each statement.
int m = 5, k = 0, j = 1;
(a) m = ++k + j;
(b) m += ++k * j;
(d) m = m - k - j;
(e) m = ++m;
104
11. What value would b have after each of the following statements is executed?
Assume that m, k, j are reinitialized before each statement. It may help to
parenthesize the right-hand side of the statements before evaluating them.
boolean b;
int m = 5, k = 0, j = 1;
(a) b = m > k + j;
(b) b = m * m != m * j;
(d) b = m < k || k < j;
(e) b = --m == 2 * ++j;
Answer: (a) true (b) true (c) true (d) true (e) true
12. For each of the following expressions, if it is valid, determine the value of the
variable on the left-hand side. If not, change it to a valid expression.
char c = a ;
int m = 95;
(a) c = c + 5;
(d) c = (char) m + 1;
Answer:
(a) c = (char)(c + 5)
(d) c = (char)(m + 1)
(b) c = A + B;
(e) m = a - 32;
(b) c = (char)(A + B)
(e) m = 65
(c) m = c + 5;
(c) m == 102
int m = 0, n = 0, j = 0, k = 0;
m = 2 * n++;
System.out.println("m= " + m + " n= " + n);
j += ( --k * 2 );
System.out.println("j= " + j + " k= " + k);
Output:
m= 0 n= 1
j= -2 k= -1
Each of the following problems asks you to write a method. Of course, as you
are developing the method in a stepwise fashion, you should test it. Heres a
simple application program that you can use for this purpose. Just replace the
square() method with your method. Note that you must declare your method
static if you want to call it directly from main() as we do here.
/*
* File: MethodTester.java
* Author: Java, Java, Java
* Description: This class tests the square() method.
*/
public class MethodTester {
/**
* This method squares its parameter
* @param n -- the number to be
public static int square(int n) {
return n * n;
}
public static void main(String args[]) {
System.out.println("5 squared = " + square(5));
}
}
15. Write a method to calculate the sales tax for a sale item. The method should take
two double parameters, one for the sales price and the other for the tax rate.
It should return a double. For example, calcTax(20.0, 0.05) should
return 1.0.
public static double calcTax(double price, double rate) {
return price * rate;
}
16. Challenge: Suppose youre writing a program that tells what day of the week
someones birthday falls on this year. Write a method that takes an int parameter, representing what day of the year it is, and returns a String like
Monday. For example, for 1999, the first day of the year was on Friday. The
105
thirty-second day of the year (February 1, 1999) was a Monday, so getDayOfWeek(1) should return Friday and getDayOfWeek(32) should return
Monday. (Hint: If you divide the day of the year by 7, the remainder will always be a number between 0 and 6, which can be made to correspond to days of
the week.)
public static String getDayOfWeek(int dayOfYear) {
int num = dayOfYear % 7;
if (num == 3)
return "Sunday";
else if (num == 4)
return "Monday";
else if (num == 5)
return "Tuesday";
else if (num == 6)
return "Wednesday";
else if (num == 0)
return "Thursday";
else if (num == 1)
return "Friday";
else if (num == 2)
return "Saturday";
else
return "Error";
} // getDayOfWeek()
17. Challenge: As part of the same program youll want a method that takes the
month and the day as parameters, and returns what day of the year it is. For
example, getDay(1,1) should return 1; getDay(2,1) should return 32;
and getDay(12,31) should return 365. (Hint: If the month is 3, and the day
is 5, you have to add the number of days in January plus the number of days in
February to 5 to get the result: 31 + 28 + 5 = 64.)
public static int getDay(int month, int day) {
if (month == 1)
return day;
else if (month == 2)
return 31 + day;
else if (month == 3)
return 31 + 28 + day;
else if (month == 4)
return 31 + 28 + 31 + day;
else if (month == 5)
return 31 + 28 + 31 + 30 + day;
else if (month == 6)
return 31 + 28 + 31 + 30 + 31 + day;
else if (month == 7)
return 31 + 28 + 31 + 30 + 31 + 30 + day;
106
else if (month == 8)
return 31 + 28 + 31
else if (month == 9)
return 31 + 28 + 31
else if (month == 10)
return 31 + 28 + 31
else if (month == 11)
return 31 + 28 + 31
else if (month == 12)
return 31 + 28 + 31
else
return 0;
} // getDay()
107
+ 30 + 31 + 30 + 31 + day;
+ 30 + 31 + 30 + 31 + 31 + day;
+ 30 + 31 + 30 + 31 + 31+ 30 + day;
+ 30 + 31 + 30 + 31 + 31+ 30 + 31 + day;
+ 30 + 31 + 30 + 31 + 31+ 30 + 31 + 30 + day;
18. Write a Java method that converts a char to lowercase. For example, toLowerCase(A) should return a. Make sure you guard against method calls
like toLowerCase(a).
public static char toLowerCase(char ch) {
if (ch >= A && ch <= Z)
return (char)(ch + 32);
return ch;
}
19. Challenge: Write a Java method that shifts a char by n places in the alphabet, wrapping around to the start of the alphabet, if necessary. For example,
shift(a,2) should return c; shift(y,2) should return a. This
method can be used to create a Caesar cipher, in which every letter in a message
is shifted by n places hfu ju?
public static char shift(char ch, int num) {
if (ch >= a && ch <= z)
{
if (((char)(ch + num) >= a) && ((char)(ch + num) <= z))
return (char)(ch + num);
else if ((char)(ch + num) >= z)
return (char)((ch + num) - 26);
}
else if (ch >= A && ch <= Z)
{
if (((char)(ch + num) >= A) && ((char)(ch + num) <= Z))
return (char)(ch + num);
else if ((char)(ch + num) >= Z)
return (char)((ch + num) - 26);
}
return ch;
} // shift()
108
20. Write a method that converts its boolean parameter to a String. For example, boolToString( true ) should return true.
public static String boolToString(boolean bool) {
if (bool)
return "true";
else
return "false";
}
21. Write a Java application that prompts the user for three numbers, which represent
the sides of a rectangular cube, and then computes and outputs the volume and
the surface area of the cube.
/*
* File: Cube.java
* Author: Java, Java, Java
* Description: This class represents a geometric cube
* in terms of the lengths of its 3 sides. It contains
* methods to calculate the cubes volume and surface area.
* The main() method creates an instance of the class and
* lets the user input the lengths of the sides.
*/
import java.io.*;
public class Cube
{
private int side1, side2, side3;
/**
* Cube() constructor creates an instance given the lengths
* of its 3 sides.
* @param s1, s2 and s3 are ints representing the lengths of the sides
*/
public Cube(int s1, int s2, int s3)
{
side1 = s1;
side2 = s2;
side3 = s3;
}
/**
* calcVolume() returns the volume of this cube using the formula
* V = s3
*/
public int calcVolume() {
return side1 * side2 * side3;
}
109
/**
* calcSurfaceArea() returns the cubes surface area using the
* formula A = 2ab + 2bc + 2ac, where a, b, c are the sides.
*/
public int calcSurfaceArea() {
return 2 * (side1 * side2) + 2 * (side2 * side3) + 2 * (side1 * side3);
}
/**
* main() creates an instance of this class using values input
*
by the user. It then tests the methods.
*/
public static void main(String args[]) throws IOException{
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
String inputString;
System.out.println("Enter Length of First Side:");
inputString = input.readLine();
int side1 = Integer.parseInt(inputString);
System.out.println("Enter Length of Second Side:");
inputString = input.readLine();
int side2 = Integer.parseInt(inputString);
System.out.println("Enter Length of Third Side:");
inputString = input.readLine();
int side3 = Integer.parseInt(inputString);
Cube cube = new Cube(side1, side2, side3);
System.out.println("The Volume is " + cube.calcVolume());
System.out.println("The Surface Area is " + cube.calcSurfaceArea());
} // main()
}
22. Write a Java application that prompts the user for three numbers, and then outputs the three numbers in increasing order.
/*
*
*
*
*
*
*
*
*
*
File: IncreasingOrder.java
Author: Java, Java, Java
Description: This application prompts the user for
three integers and the outputs the integers in
increasing order. Its main() method creates an instance
of the class in order to test that its methods work
correctly.
A java.io.BufferedReader object is used to input the data.
*/
import java.io.*;
public class IncreasingOrder
{
/**
* smallest() returns the smallest of its three parameters.
* Boolean operators are used to perform the comparisons.
* @param num1, num2, num3 are three integers
* @return a int representing the smallest value is returned
*/
public int smallest(int num1, int num2, int num3) {
if (num1 <= num2 && num1 <= num3)
return num1;
else if (num2 <= num1 && num2 <= num3)
return num2;
else if (num3 <= num1 && num3 <= num2)
return num3;
return 0;
} // smallest()
/**
* middle() returns the middle value of its three parameters.
* Boolean operators are used to perform the comparisons.
* @param num1, num2, num3 are three integers
* @return a int representing the middle value is returned
*/
public int middle(int num1, int num2, int num3) {
if (num1 <= num3 && num1 >= num2)
return num1;
else if (num1 >= num3 && num1 <= num2)
return num1;
else if (num2 <= num1 && num2 >= num3)
return num2;
else if (num2 >= num1 && num2 <= num3)
return num2;
else if (num3 <= num1 && num3 >= num2)
return num3;
else if (num3 >= num1 && num3 <= num2)
return num3;
return 0;
} // middle()
/**
* largest() returns the largest of its three parameters.
* Boolean operators are used to perform the comparisons.
* @param num1, num2, num3 are three integers
* @return a int representing the largest value is returned
*/
110
111
/**
* main() creates an instance of this class and uses it
* to test the ordering methods. Note the use of a BufferedReader
* to perform keyboard input.
*/
public static void main(String args[]) throws IOException{
IncreasingOrder orderer = new IncreasingOrder();
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
String inputString;
System.out.println("Enter First Number:"); // Prompt
inputString = input.readLine();
// Read
int num1 = Integer.parseInt(inputString); // Convert
System.out.println("Enter Second Number:");
inputString = input.readLine();
int num2 = Integer.parseInt(inputString);
System.out.println("Enter Third Number:");
inputString = input.readLine();
int num3 = Integer.parseInt(inputString);
// Print results
System.out.println("Numbers in increasing order are: ");
System.out.println( orderer.smallest(num1,num2,num3) + ","
+ orderer.middle(num1,num2,num3) + ","
+ orderer.largest(num1,num2,num3));
} // main()
} // IncreasingOrder
23. Write a Java application that inputs two integers and then determines whether
the first is divisible by the second. (Hint: Use the modulus operator.)
/*
* File: Divisible.java
* Author: Java, Java, Java
* Description: This program inputs two integers from the
* user and determines whether the first is divisible by
* the second.
112
*/
import java.io.*;
public class Divisible
{
/**
* divisible() returns true iff its first parameter
* is divisible by its second
* @param num1 -- an integer representing the numerator
* @param num2 -- an integer representing the denominator
*/
public boolean divisible(int num1, int num2) {
if (num1 % num2 == 0)
return true;
else
return false;
} // divisible()
/**
* main() inputs two integers from the user. It then
* creates an instance of Divisible and tests whether
* the first integer is divisible by the second.
*/
public static void main(String args[]) throws IOException{
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
String inputString;
System.out.print("Enter First Number:");
inputString = input.readLine();
int num1 = Integer.parseInt(inputString);
System.out.print("Enter Second Number:");
inputString = input.readLine();
int num2 = Integer.parseInt(inputString);
Divisible div = new Divisible(); // Create an instance
if (div.divisible(num1,num2))
System.out.println(num1 + " is evenly divisible by " + num2);
else
System.out.println(num1 + " is NOT evenly divisible by " + num2);
} // main()
} // Divisible
N
1
2
3
4
5
SQUARE
1
4
9
16
25
113
CUBE
1
8
27
64
125
/*
* File: Table.java
* Author: Java, Java, Java
* Description: This application prints a table of the
* squares and cubes of the numbers from 1 to 5.
*/
import java.lang.*;
public class Table
{
/**
* square() returns the square of its parameter
* @param num -- an integer to be squared
* @return the integer square
*/
public int square(int num) {
return (int)Math.pow(num,2);
}
/**
* cube() returns the cube of its parameter
* @param num -- an integer to be cubed
* @return the integer cube
*/
public int cube(int num) {
return (int)Math.pow(num,3);
}
/**
* main() creates an instance of this class and
* invokes its square() and cube() methods to print
* a table of squares and cubes.
*/
public static void main(String args[]) {
Table table = new Table();
System.out.println("N SQUARE CUBE");
System.out.println(1 + "
" + table.square(1) +
System.out.println(2 + "
" + table.square(2) +
System.out.println(3 + "
" + table.square(3) +
System.out.println(4 + "
" + table.square(4) +
System.out.println(5 + "
" + table.square(5) +
} // main()
"
"
"
"
"
" + table.cube(1));
" + table.cube(2));
" + table.cube(3));
" + table.cube(4));
" + table.cube(5));
114
} // Table
25. Design and write a Java applet that converts kilometers to miles and vice versa.
Use a TextField for I/O and Buttons for the various conversion actions.
Figure 5.1: This applet converts from kilometers to miles and vice versa.
/*
* File: ConvertDistanceApplet.java
* Author: Java, Java, Java
* Description: This applet provides the user interface to a
* ConvertDistance, an object that converts kilometers to miles
* and vice versa. It provides the user with a TextField and
* two labeled buttons. The user inputs a number in the text fields
* and clicks on one or the other button to convert from kilometers
* to miles or vice versa.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ConvertDistanceApplet extends Applet implements ActionListener
{
private Label prompt;
// References for GUI components
private TextField inputField;
private Button button1;
private Button button2;
private
private
private
private
double distanceInMiles;
double distanceInKm;
String inputString;
boolean distEnteredInKm;
//
//
//
//
115
/**
* convertStringToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
private double convertStringToDouble(String s)
{
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
} // convertStringToDouble()
/**
* init() creates the applets interface and assigns
* the applet itself as the ActionListener for the conversion buttons
*/
public void init()
{
prompt = new Label("Input a Distance:");
inputField = new TextField(10);
inputField.setEditable(true);
button1 = new Button("Convert To Miles");
button1.addActionListener(this);
button2 = new Button("Convert To Kilometers");
button2.addActionListener(this);
add(prompt);
add(inputField);
add(button1);
add(button2);
setSize(500,200);
} //init()
/**
* paint() displays the result of the conversion. It uses a class
* variable, distEnteredInKm, to determine the proper units for the display
*/
public void paint (Graphics g)
{
if (distEnteredInKm)
g.drawString(distanceInKm + "Km = " + distanceInMiles + "Mi", 10, 50);
else
g.drawString (distanceInMiles + "Mi = " + distanceInKm + "Km", 10, 50);
} // paint()
/**
116
26. Design and write an (applet) GUI that allows a user to calculate the maturity
value of a CD. The user should enter the principal, interest rate, and period, and
the applet should then display the maturity value. Make use of the CDInterest
program covered in this chapter. Use separate TextFields for the users inputs
and a separate TextField for the result.
Figure 5.2: This applet calculates the maturity value of a Certificate of Deposit.
/*
117
* File: MaturityApplet.java
* Author: Java, Java, Java
* Description: This applet provides a user interface to
* the CDInterest class, a class which calculates the maturity
* value of a CD given its principal, interest rate, and time
* period.
*
* In this solution we have broken the problem into two parts.
* This class handles the interface and the CDInterest class
* handles the maturity calculation.
*/
import
import
import
import
java.applet.*;
java.awt.*;
java.awt.event.*;
java.text.NumberFormat;
118
119
add(prompt1);
add(inputField1);
add(prompt2);
add(inputField2);
add(prompt3);
add(inputField3);
add(button);
add(resultLabel);
add(resultField);
setSize(400,300);
} // init()
/**
* convertStringToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
public double convertStringToDouble(String s)
{
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
} // convertStringToDouble()
/**
* actionPerformed() handles clicks on the calculate button.
* It inputs the data from the TextFields, converts them to
* numeric values and calls on the CDInterest object to perform
* the calculation. It translates the result into a currency format
* and displays it in a TextField.
*/
public void actionPerformed(ActionEvent e)
{
String inputString = inputField1.getText();
double principal = convertStringToDouble(inputString);
inputString = inputField2.getText();
double rate = convertStringToDouble(inputString);
inputString = inputField3.getText();
double years = convertStringToDouble(inputString);
double maturityValue = CDInterest.calcValue(principal, rate, years);
NumberFormat dollars = NumberFormat.getCurrencyInstance();
String resultStr = dollars.format(maturityValue);
resultField.setText(resultStr);
} //actionPerformed()
} // MaturityApplet
/*
* File: CDInterest.java
27. Design and write an (applet) GUI that lets the user input a birth date (month and
day), and reports what day of the week it falls on. Use the getDayOfWeek()
and getDay() methods that you developed in previous exercises.
/*
* File: DayOfWeekApplet.java
* Author: Java, Java, Java
* Description: This applet provides the user interface to
* an instance of the GetDayOfWeek class, a class that
* calculates what day of the week a given date (mon/day/2002)
* falls on. The interface contains of three TextFields -- two
* for inputting the month and day, and one for outputting the
* result -- and a button, which directs the program to perform
* its calculations.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class DayOfWeekApplet extends Applet implements ActionListener
{
private Label prompt1;
// GUI components
private Label prompt2;
120
Figure 5.3: This applet will tell you what day of the week your birthday falls on in the
year 2002.
121
private
private
private
private
private
TextField inputField1;
TextField inputField2;
Label resultLabel;
TextField resultField;
Button button;
122
/**
* init() initializes the applets interface. The applet itself
* is designated as the ActionListener for the button.
*/
public void init()
{
prompt1 = new Label("Enter the Month (1 - 12):");
prompt2 = new Label("Enter the Day:");
resultLabel = new Label("In 2002, Date Falls on a:");
inputField1 = new TextField(10);
inputField2 = new TextField(10);
resultField = new TextField(10);
resultField.setEditable(false);
// Suppress input in the result field
button = new Button("Calculate the Day of The Week");
button.addActionListener(this);
add(prompt1);
add(inputField1);
add(prompt2);
add(inputField2);
add(button);
add(resultLabel);
add(resultField);
setSize(300,200);
} // init()
/**
* actionPerformed() handles clicks on the calculate button.
* It inputs the data in the month and day TextFields,
* converting them to integers. It then gets the GetDayOfWeek
* class to perform the day of week calculation and displays
* the result in a TextField.
* @param e -- the ActionEvent that generated this method call
*/
public void actionPerformed(ActionEvent e)
{
int month = Integer.parseInt(inputField1.getText());
int day = Integer.parseInt(inputField2.getText());
String dayOfTheWeek = DayOfWeek.getDayOfWeek(month, day);
resultField.setText(dayOfTheWeek);
} //actionPerformed()
} // DayOfWeekApplet
123
/*
* File: DayOfWeek.java
* Author: Java, Java, Java
* Description: This class calculates the day of the week
* (Monday, Tuesday, etc.) given the month and day for
* 2002. It is modeled after the java.lang.Math class in
* that its conversion methods are declared static. Thus
* to convert a
*/
public class DayOfWeek
{
/**
* getDay() converts the month and day for the current
* year (2002) into the ordinal day of the year, where Jan. 1
* is day 1 and Dec. 31 is day 365.
* @param month -- an int representing the month, 1..12
* @param day -- an int representing the day, 1..31
* @return -- an int giving the day of the year
* Algorithm: Treat each of the 12 months as a separate case,
* adding the appropriate number of days through the last day
* of the previous month. Then add in the day.
*/
public static int getDayOfYear(int month, int day) {
if (month == 1)
return day;
else if (month == 2)
return 31 + day;
else if (month == 3)
return 31 + 28 + day;
else if (month == 4)
return 31 + 28 + 31 + day;
else if (month == 5)
return 31 + 28 + 31 + 30 + day;
else if (month == 6)
return 31 + 28 + 31 + 30 + 31 + day;
else if (month == 7)
return 31 + 28 + 31 + 30 + 31 + 30 + day;
else if (month == 8)
return 31 + 28 + 31 + 30 + 31 + 30 + 31 + day;
else if (month == 9)
return 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + day;
else if (month == 10)
return 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31+ 30 + day;
else if (month == 11)
return 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31+ 30 + 31 + day;
else if (month == 12)
return 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31+ 30 + 31 + 30 + day;
else
return 0;
} //getDayOfYear()
/**
* getDayOfWeek() converts the month and day for the current
* year (2002) into a string giving the day of the week
* @param month -- an int representing the month, 1..12
* @param day -- an int representing the day, 1..31
* @return -- an String giving the day of the week (e.g., "Sunday")
* Algorithm: For 2002, 1/1/2002 was a Tuesday. So compute
* the day of the year. Then divide the day of the year by 7,
* take the remainder, and determine the day of the week by
* looking at each of the 7 possible cases.
*/
public static String getDayOfWeek(int month, int day) {
int dayOfYear = getDayOfYear(month, day);
int num = dayOfYear % 7;
if (num == 6)
return "Sunday";
else if (num == 7)
return "Monday";
else if (num == 1)
return "Tuesday";
else if (num == 2)
return "Wednesday";
else if (num == 3)
return "Thursday";
else if (num == 4)
return "Friday";
else if (num == 5)
return "Saturday";
else
return "Error";
} // getDayOfWeek()
} // DayOfWeek
28. Design and write an (applet) GUI that allows the users access input their exam
grades for a course and computes their average and probable letter grade. The
applet should contain a single TextField for inputting a grade and a single
TextField for displaying the average and letter grade. The program should
keep track internally of how many grades the student has entered. Each time a
new grade is entered, it should display the current average and probable letter
grade.
/*
* File: GradeCalcApplet.java
* Author: Java, Java, Java
* Description: This applet provides a user interface to
124
Figure 5.4: This applet computes a course average and letter grade.
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class GradeCalcApplet extends Applet implements ActionListener
{
private Label prompt;
// GUI components
private TextField inputField;
private Label resultLabel;
private TextField resultField;
private Button button;
private GradeCalculator calculator; // The Calculator object
125
126
/**
* convertStringToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
public double convertStringToDouble(String s)
{
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
} //convertStringToDouble()
/**
* init() sets up the user interface. It instantiates each
* of the GUI components and adds them to the applet. It
* assigns the applet itself as the ActionListener for the
* calculate button. Note that it also creates an instance of
* the GradeCalculator class.
*/
public void init()
{
calculator = new GradeCalculator(); // Create a calculator instance
prompt = new Label("Enter a grade:");
resultLabel = new Label("Your average is:");
inputField = new TextField(10);
resultField = new TextField(20);
resultField.setEditable(false);
button = new Button("Calculate Your Average and Letter Grade");
button.addActionListener(this);
add(prompt);
add(inputField);
add(button);
add(resultLabel);
add(resultField);
setSize(300,200);
} // init()
/**
* actionPerformed() handles the clicks on the calculate button.
* For each grade input, it gets the grade from the TextField, converts
* it to a double and increments the number grades input. It then gets
* the GradeCalculater class to calculate a running average and computes
* the letter grade, which are displayed in TextFields.
* @param e -- the ActionEvent the generated this system call
*/
public void actionPerformed(ActionEvent e)
{
String inputString = inputField.getText();
double grade = convertStringToDouble(inputString);
String average = "" + calculator.calcAvg(grade);
String letterGrade = calculator.calcLetterGrade();
resultField.setText(average + " " + letterGrade);
} //actionPerformed()
} // GradeCalcApplet
/*
* File: GradeCalculator.java
* Author: Java, Java, Java
* Description: Instances of this class are used to calculate
* a course average and a letter grade. In order to calculate
* the average and the letter grade, a GradeCalculator must store
* two essential pieces of data: the number of grades and the sum
* of the grades. Therefore these are declared as instance variable.
* Each time calcAverage(grade) is called, a new grade is added to
* the running total, and the number of grades is incremented.
*/
public class GradeCalculator
{
private int gradeCount = 0;
// GradeCalculators internal state
private double gradeTotal = 0.0;
/**
* calcAverage() is given a grade, which is added to
* the running total. It then increments the grade count
* and returns the running average.
*/
public double calcAvg(double grade)
{
gradeTotal += grade;
++gradeCount;
return gradeTotal/gradeCount;
} // calcAvg
/**
* calcLetterGrade() returns the letter grade for this object.
* Algorithm: The course average is first computed from the stored
* gradeTotal and gradeCount and then converted into a
* letter grade.
* @return a String representing "A" through "F"
*/
public String calcLetterGrade ()
{
127
Additional Exercises
29. One of the reviewers of this text has suggested an alternative design for the Temperature class (Text Figure 5-5). According to this design, the class would
contain an instance variable, say temperature, and access methods that operate on it. The access methods would be: setFahrenheit(double), getFahrenheit():double, setCelsius(double), and getCelsius():double.
One way to implement this design is to store the temperature in the Kelvin scale
and then convert from and to Kelvin in the access methods. The formula for
converting Kelvin to Celsius is:
K = C + 273.15
Draw a UML class diagram representing this design of the Temperature
class. Which design is more object oriented, this one or the one used in Text
Figure 5-5?
Answer: See the UML diagrams at the end of this chapter.
30. Write an implementation of the Temperature class using the design described
in the previous exercise.
/*
* File: Temperature.java
* Author: Java, Java, Java
* Description: This version of the Temperature class stores
*
the temperature in Kelvin. It has methods to set and get
*
the temperature in either Fahrenheit or celsius.
*
* One way in which this version is more object-oriented than
* the version given is that it has a state, thus more closely
* resembling what we commonly think of as an object.
*/
128
129
// Temperature in Kelvin
public Temperature() {}
/**
* setCelsius() sets the temperature given a F value
* @param cels -- gives the temperature in Celsius
*/
public void setCelsius(double cels)
{
kelvin = cels + 273.15;
}
/**
* getCelsius() returns the temperature in Celsius
* @return -- a double giving the temperature in Celsius
*/
public double getCelsius()
{
return kelvin - 273.15;
}
/**
* setFahrenheit() sets the temperature given a F value
* @param fahr -- gives the temperature in Fahrenheit
*/
public void setFahrenheit(double fahr)
{
double celsius = 5.0 * (fahr - 32.0) / 9.0;
kelvin = celsius + 273.15;
}
/**
* getFahrenheit() returns the temperature in Fahrenheit
* @return -- a double giving the temperature in Fahrenheit
*/
public double getFahrenheit()
{
double celsius = kelvin -273.5;
return 9.0 * celsius / 5.0 + 32.0;
}
} // Temperature
31. Another way to represent a CyberPet would be to use strings to represent the state
for example, sleeping and eating. Draw a UML class diagram representing
this design.
130
// Initially Eating
// CyberPets name
/**
* CyberPet() constructor sets the pets name its parameter
* @param str -- a String giving the pets name
*/
public CyberPet (String str)
// Constructor method
{
name = str;
}
/**
* setName() sets the pets name from its parameter
* @param str -- a String giving the pets name
*/
public void setName (String str)
// Access method
{
name = str;
} // setName()
/**
* getName() returns the pets name
* @return a String giving the pets name
*/
public String getName()
{
return name;
// Return CyberPets name
} // getName()
/**
* setName() sets the pets food from its parameter
* @param str -- a String giving the pets food
*/
public void setFood (String str)
// Access method
{
food = str;
} // setFood()
/**
* getFood() returns the pets food
* @return a String giving the pets food
*/
public String getFood()
{
return food;
// Return CyberPets food
} // getName()
/**
* eat() puts the pet in the eating state
*/
public void eat()
// Start eating
{
state = EATING;
} // eat()
/**
* sleep() puts the pet in the sleeping state
*/
public void sleep()
// Start sleeping
{
state = SLEEPING;
} // sleep()
/**
* getState() returns a representation of the pets state
* @return -- a String giving the pets state
*/
public String getState ()
{
if (state.equals(EATING))
return state + " " + food;
else
return state;
} // getState()
/**
* toString() returns a String representation of the pets state
131
*/
public String toString()
{
return name + " is " + getState();
}
} // CyberPet
33. Challenge: One possible objection to the integer-based CyberPet is that it does
not allow for a pet to be doing more than one thing (eating and thinking) at the
same time. Devise a system of integer values that can be used to represent a pets
state that would allow the pet to do more than one thing at a time. Modify the
CyberPet class to use your scheme and to show that the pet can do more than
one thing at a time. Hint: Any nonnegative integer value can be computed as
sum of unique powers of 2. For example 13 = 2 3 + 22 + 20 = 8 + 4 + 1.
Answer: Following the hint, let the CyberPets states be distinct powers of 2.
For example, given the following values,
public static final int SLEEPING = 1;
public static final int EATING = 2;
public static final int THINKING = 4;
a pet with a state fo 3 is both sleeping and eating. A pet with a state of 6 is eating
and thinking.
132
133
Exercise 5.21
Label
ActionEvent
Button
datatype
boolean
TextField
Exercise 5.22
Cube
Miscellaneous Types
-side1 : int
-side2 : int
-side3 : int
IncreasingOrder
Exercise 5.24
Exercise 5.23
Divisible
Table
Exercise 5.25
Applet
+init()
Exercise 5.26
interface
ActionListener
+actionPerformed()
Applet
MaturityApplet
-prompt1 : Label
-prompt2 : Label
-prompt3 : Label
-inputField1 : TextField
-inputField2 : TextField
-inputField3 : TextField
-resultLabel : Label
-resultField : TextField
-button : Button
-prompt : Label
-inputField : TextField
-button1 : Button
-button2 : Button
-distanceInMiles : double
-distanceInKm : double
-inputString : String
-distanceEnteredInKm : boolean
Uses
+init()
+convertStringToDouble(in s : String) : double
+actionPerformed(in e : ActionEvent)
ConvertDistance
+actionPerformed()
+init()
ConvertDistanceApplet
interface
ActionListener
CDInterest
Uses
134
Miscellaneous Classes
Label
TextField
Button
ActionEvent
Exercise 5.28
Exercises 5.27
Applet
Applet
interface
ActionListener
+actionPerformed()
+init()
+actionPerformed()
+init()
GradeCalcApplet
DayOfWeekApplet
-prompt1 : Label
-prompt2 : Label
-inputField1 : TextField
-inputField2 : TextField
-resultLabel : Label
-resultField : TextField
-button : Button
interface
ActionListener
Uses
+init()
+actionPerformed(in e : ActionEvent)
-prompt : Label
-inputField : TextField
-resultLabel : Label
-resultField : TextField
-button : Button
-calculator : GradeCalculator
+init()
+convertStringToDouble(in s : String) : double
+actionPerformed(in e : ActionEvent)
GradeCalculator
DayOfWeek
-gradeCount : int = 0
-gradeTotal : double = 0.0
Exercise 5.29
Exercise 5.31
CyberPet
Temperature
-temperature : float
+setFahrenheit(in temp : double)
+getFahrenheit() : double
+setCelsius(in temp : double)
+getCelsius() : double
Uses
Chapter 6
Control Structures
1. Explain the difference between the following pairs of terms.
(a) Counting loop and conditional loop.
Answer: A counting loop is used to perform repetitive tasks when the
number of iterations required is known beforehand. A conditional loop is
used to perform repetitive tasks when the number of iterations depends on
a non-counting bound.
(b) For statement and while statement.
Answer: A for statement is a counting loop that is usually used when the
number of iterations is known beforehand. A while statement is a conditional loop that is used when the number of iterations depends on a noncounting bound.
(c) While statement and do-while statement. Answer: A do-while statement
checks the loop bound after the loop is executed whereas the while statement checks it before. This makes it useful to use the while statement for
loops that may not be executed at all and to use do-while statements for
loops to be executed at least one time.
(d) Zero indexing and unit indexing.
Answer: In zero indexing a counter starts at zero. In unit indexing a counter
starts at one.
(e) Sentinel bound and limit bound.
Answer: A limit bound terminates a loop when a certain limit is reached. A
sentinel bound terminates a loop when a certain special value (the sentinel)
is reached.
(f) Counting bound and flag bound.
Answer: A counting bound terminates a loop when a certain count is
reached. A flag bound terminates a loop when a certain boolean variable is
set to true.
135
136
. Answer:
statement. Answer:
0)
would be
(e) A loop that should iterate until the user types in a special value should use
a
bound. Answer: sentinel
(f) A loop that should iterate until its variable goes from 5 to 100 should use a
bound. Answer: counting
(g) A loop that should iterate until the difference between two values is less
bound. Answer: limit
than 0.005 is an example of a
3. Identify the syntax errors in each of the following:
(a) for (int k = 0; k < 100; k++)
System.out.println( k )
colon here
(b) for (int k = 0; k < 100; k++);
System.out.println( k );
(c) int k = 0
colon here
while k < 100
theses around k < 100
{
System.out.println(k); k++;
}
(d) int k = 0;
do
{
System.out.println(k);
}
while k < 100 ;
theses around k < 100
137
k++;
// Missing paren-
4. Determine the output and/or identify the error in each of the following code
segments:
(a) for (int k = 1; k == 100; k += 2)
System.out.println(k);
// Error: The entry condition will never be met.
(b) int k = 0;
while ( k < 100 )
System.out.println(k);
k++;
// Error: There are braces missing around the loop body, so k will
// never be updated and an infinite loop will result.
(c) for (int k = 0; k < 100; k++) ;
System.out.println(k);
// The output will be all integers from 0 to 99
5. Write pseudocode algorithms for the following activities, paying particular attention to the initializer, updater, and boundary condition in each case.
(a) a softball game
for (inning = 1, inning <= 9, inning ++)
let the home team bat,
let the away team field,
let the home team field,
let the away team bat
(b) a five-question quiz
for (question = 1, question <= 5, question ++)
read the question,
answer the question,
(c) looking up a name in the phone book
8. Write three different loops a for loop, a while loop, and a do-while loop to
print the following sequence of numbers: 45, 36, 27, 18, 9, 0, -9, -18, -27, -36,
-45.
138
139
int j = 5;
// while loop
while (j >= -5)
{
int k = j * 9;
outputArea.appendText(k + ", ");
j--;
}
int j = 5;
// do-while loop
do
{
int k = j * 9;
outputArea.appendText(k + ", ");
j--;
} while (j >= -5);
9. Write three different loops a for loop, a while loop, and a do-while loop to
print the following ski-jump design:
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
# #
# # #
# # # #
// for loop
// while loop
140
row++;
}
int row = 1;
do {
int col = 1;
do {
System.out.print(#);
col++;
} while (col <= row);
System.out.println();
row++;
} while (row <= 7);
// do-while loop
10. The Straight Downhill Ski Lodge in Gravel Crest, Vermont, gets lots of college
students on breaks. The lodge likes to keep track of repeat visitors. Straight
Downhills database includes an integer variable, visit, which gives the number
of times a guest has stayed at the lodge (1 or more). Write the pseudocode to
catch those visitors who have stayed at the lodge at least twice and to send them
a special promotional package (pseudocode = send promo). (Note: The largest
number of stays recorded is eight. The number nine is used as an end-of-data
flag.)
Read a visitor record
while (visit != 9)
if (visit >= 2)
Send visitor a pamphlet
Read the next visitor record
11. Modify your pseudocode in the previous exercise. In addition to every guest who
has stayed at least twice at the lodge receiving a promotional package, any guest
with three or more stays should also get a $40 coupon good for lodging, lifts, or
food.
Read a visitor record
while (visit != 9)
if (visit >= 2)
Send visitor a pamphlet
if (visit >= 3)
Send visitor a coupon for lodging, lift, or food
Read the next visitor record
12. Write a method that is passed a single parameter, N, and displays all the even
numbers between 1 and N.
141
/**
* evens() displays all the even numbers between 1 and its parameter
* @param n -- the upper bound for the number sequence
*/
private void evens (int n) {
for (int j = 1; j <= n; j++)
if (j % 2 == 0)
outputArea.appendText(j + ", ");
} // evens()
13. Write a method that is passed a single parameter, N, that prints all the odd numbers between 1 and N.
/**
* odds() displays all the odd numbers between 1 and its parameter
* @param n -- the upper bound for the number sequence
*/
private void odds (int n) {
for (int j = 1; j <= n; j++)
if (j % 2 != 0)
outputArea.appendText(j + ", ");
} // odds()
14. Write a method that is passed a single parameter, N, that prints all the numbers
divisible by 10 from N down to 1.
/**
* divby10() displays all numbers divisible by 10 between 1 and its parameter
* @param n -- the upper bound for the number sequence
*/
private void divby10 (int n) {
for (int j = 1; j <= n; j++)
if (j % 10 == 0)
outputArea.appendText(j + ", ");
} // divby10()
15. Write a method that is passed two parameters a char Ch and an int N,
and prints a string of N Chs.
/**
* chars() prints a sequence of n characters
* @param n -- the number characters in the sequence
* @param ch -- the characters that are printed
*/
private void chars (char ch, int n) {
for (int j = 1; j <= n; j++)
outputArea.appendText(ch + ", ");
} // chars()
142
16. Write a method that uses a nested for loop to print the following multiplication
table:
1
2
3
4
5
6
7
8
9
1
1
2
3
4
5
6
7
8
9
4
6
8
10
12
14
16
18
9
12
15
18
21
24
27
16
20
24
28
32
36
25
30
35
40
45
36
42 48
48 56 64
54 63 72 81
/**
* multTable() prints a triangular multiplication table
* with row and column headings
*/
private static void multTable () {
for (int col = 1; col <= 9; col++) // Column headings
System.out.print(col + " ");
System.out.println();
for (int row = 1; row <= 9; row++) {
System.out.print(row + " ");
// Row heading
for (int col = 1; col <= row; col++)
System.out.print(col * row + " ");
System.out.println();
}
} // multTable()
17. Write methods that use nested for loops to print the following patterns. Your
method should use the following statement to print the patterns: System.out.print(#).
# # # #
# # #
# #
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
143
#
#
#
#
#
# # # #
# # #
# #
#
# # # #
#
#
#
#
#
#
# # # #
# # # #
#
#
#
#
#
#
# # # #
# # # # # # # #
#
#
#
#
#
#
# # # # # # # #
/*
* File: Patterns.java
* Author: Java, Java, Java
* Description: This program uses nested loops to
* draw four two-dimensional patterns.
*/
public class Patterns {
private static void pattern1 () {
for (int row = 1; row <= 8; row++) {
for (int k = 2; k <= row; k++)
// Skip some blanks
System.out.print(" ");
for (int n = 9 - row; n >= 1; n--)
System.out.print("# ");
System.out.println();
}
} // pattern1()
private static void pattern2 ()
for (int row = 1; row <= 8;
for (int n = 9 - row; n
System.out.print("#
System.out.println();
}
} // pattern2()
{
row++) {
>= 1; n--)
");
} // pattern3()
private static void pattern4 () {
for (int row = 1; row <= 8; row++) {
for (int col = 1; col <= 8; col++)
if (row == 1 || row == 8)
System.out.print("# ");
else if (row == 9 - col)
System.out.print("# ");
else
System.out.print(" ");
System.out.println();
}
} // pattern4()
public static void main(String args[]) {
pattern1();
pattern2();
pattern3();
pattern4();
} // main
} // Patterns
18. Write a program which asks the user for the number of rows and the number of
columns in a box of asterisks. Then use nested loops to generate the box.
/*
* File: Box.java
* Author: Java, Java, Java
* Description: This program draws a rectangular box of
* asterisks given the number of rows and columns from
* the user.
*/
import java.io.*;
public class Box {
/**
* drawBox() draws a row x col box of asterisks
* @param row -- an int giving the number of rows
* @param col -- an int giving the number of columns
*/
public static void drawBox (int row, int col) {
for (int k = row; k > 0; k--) {
for (int j = col;j > 0; j--)
System.out.print(*);
System.out.println();
}
144
145
} // drawBox()
/**
* main() inputs the number of rows and columns from the
* user and invokes the Box.drawBox() method to draw a box.
*/
public static void main(String args[]) throws IOException{
String inputString;
int nRows = 0;
int nColumns = 0;
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
System.out.print("Enter the number of rows you want in your box: ");
inputString = input.readLine();
nRows = Integer.parseInt(inputString);
System.out.print("Enter the number of colums you want in your box: ");
inputString = input.readLine();
nColumns = Integer.parseInt(inputString);
System.out.println("This is what your box looks like\n");
Box.drawBox(nRows, nColumns);
} // main()
} // Box
19. Write a Java application that lets the user input a sequence of consecutive numbers. In other words, the program should let the user keep entering numbers as
long as the current number is one greater than the previous number.
/*
* File: ConsecutiveSequence.java
* Author: Java, Java, Java
* Description: This program lets the user input a
* sequence of consecutive integers. The sequence
* ends when an input value is "out of sequence."
*/
import java.io.*;
public class ConsecutiveSequence {
/**
* main() does all the work
* sequence of consecutive
of-sequence
* value.
*
* The loop uses a sentinel
* because there has to be
*/
146
throws IOException{
20. Write a Java application that lets the user input a sequence of integers terminated
by any negative value. The program should then report the largest and smallest
values that were entered.
/*
* File: SequenceTester.java
* Author: Java, Java, Java
* Description: This program lets the user input
* sequence of positive integers. It terminates
* soon as the user inputs a negative value. It
* reports the largest and smallest values that
*/
any
as
then
were entered.
import java.io.*;
public class SequenceTester {
/**
* main() does all the work in this program. It inputs a
* sequence of integers terminated by a negative value.
* For each integer it compares it to the largest and smallest
* so far, updating these variables if necessary. When the
147
// Sentinel bound
21. How many guesses does it take to guess a secret number between 1 and N? For
example, Im thinking of a number between 1 and 100. Ill tell you whether your
guess is too high or too low. Obviously, an intelligent first guess would be 50.
If thats too low, an intelligent second guess would be 75. And so on. If we
continue to divide the range in half, well eventually get down to one number.
Because you can divide 100 seven times (50,25,12,6,3,1,0), it will take at most
seven guesses to guess a number between 1 and 100. Write a Java applet that lets
the user input a positive integer, N, and then reports how many guesses it would
148
149
} // main()
} // GuessingGame
22. Suppose you determine that the fire extinguisher in your kitchen loses X percent
of its foam every day. How long before it drops below a certain threshold (Y
percent), at which point it is no longer serviceable? Write a Java applet that
lets the user input the values X and Y, and then reports how many weeks the fire
extinguisher will last?
/*
* File: FireExtinguisher.java
* Author: Java, Java, Java
* Description: This program tests the life of a
* fire extinguisher using data input by the user.
* The user will input two numbers, X and Y, which
* represent the percentage of foam lost each day (X)
* and the threshold (Y) beyond which the extinguisher
* is no longer useful. It then reports how many days
* the extinguisher will last.
*/
import java.io.*;
public class FireExtinguisher {
/**
* convertToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
private static double convertToDouble(String s) {
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
}
/**
* calculateLifeTime() counts the number of weeks a extinguisher
* should last given its daily loss rate and its usefulness threshold
* @param lossRate -- a double giving the percentage loss each day
* @param threshold -- a double giving the percentage of foam needed
* @return an double giving the extinguishers expected life in weeks
* Algorithm: This loop uses a limit bound, which requires a noncounting
* loop. The extinguisher starts at 100% full and loses lossRate percent
* per day. Note that lossRate must be divided by 100.
*/
public static double calculateLifeTime(double lossRate, double threshold) {
150
23. Leibnitzs method for computing is based on the following convergent series:
=1
4
1 + 1
3
5
1 +
7
How many iterations does it take to compute using this series? Write a Java
program to find out.
/*
* File: PiTester.java
* Author: Java, Java, Java
* Description: This program tests Leibnizs method for
151
} // main()
} // PiTester
24. Newtons method for calculating the square root of N starts by making a (non
zero) guess at the square root. It then uses the original guess to calculate a new
guess, according to the following formula:
guess = (( N / guess) + guess) / 2;
No matter how wild the original guess is, if we repeat this calculation, the algorithm will eventually find the square root. Write a square root method based
on this algorithm. Then write a program to determine how many guesses are
required to find the square roots of different numbers. Uses Math.sqrt() to
determine when to terminate the guessing.
/*
* File: NewtonTester.java
* Author: Java, Java, Java
* Description: The program uses Newtons method to calculate
* square roots. Newtons method is based on the formula:
*
guess = (( N / guess) + guess) / 2;
* To compute a square root, start with any nonzero guess,
* then use the formula to update the guess until it converges
* on the square root. The program tests how many guesses are
* needed by comparing Newtons value with Math.sqrt().
*/
import java.io.*;
public class NewtonTester {
/**
* convertToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
private static double convertToDouble(String s) {
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
}
/**
* countGuesses() counts the number of guesses needed to
* compute the square root of num using Newtons method
* @param num -- the number whose square root is computed
* @param guess -- the initial guess (should be nonzero)
* @return an int giving the number of guesses required
* Algorithm: The loop in this method uses a limit bound.
152
153
25. Your employer is developing encryption software and wants you to develop a
Java applet that will display all of the factorials less than N, where N is a number
to be entered by the user. In addition to displaying the factorials themselves,
provide a count of how many there are. Use the method that was developed in
section on pre- and postconditions.
/*
* File: PrimesTester.java
* Author: Java, Java, Java
* Description: This program lets the user input an integer,
* and then displays all the prime numbers between 1 and that
* integer. It also provides a count of the number of such
* primes.
*/
import java.io.*;
public class PrimesTester {
/**
* countPrimesLessThanN() prints the primes between 1 and n
* and returns their count
* @param n -- the upper bound on the sequence of primes
* @return -- an int giving the number of primes between 1 and n
* Algorithm: To test every value between 1 and n we can use a
* counting loop. A more efficient algorithm would print 1, 2, 3
* and then check every other value between 3 and n.
*/
public int countPrimesLessThanN(int n) {
int counter = 0;
for (int num = 1; num < n; num++) {
if (isPrime(num)) {
System.out.print((num) + " ");
counter++;
} // if
} // for
return counter;
} // countPrimesLessThanN()
/**
* isPrime() returns true iff its parameter is a prime
* @param n -- the value to be tested for primality
* @return -- a boolean set to true iff n is prime
* Algorithm: The primality test attempts to divide n by
* every value between 2 and n. The loop exits when n is
* divisible by n or if it passes each test.
*/
public boolean isPrime(int n) {
boolean notDivisibleYet = true;
int k = 2;
while (notDivisibleYet && k < n) {
if (n % k == 0) {
notDivisibleYet = false;
}
k++;
} // while
return notDivisibleYet;
154
155
} // isPrime()
/**
* main() prompts the user for a number and creates
* and instance of the PrimesTester class to print
* all the primes between 1 and the users bound.
*/
public static void main(String args[]) throws IOException {
String inputString;
int bound;
// The users bound
int count;
// The number of primes found
PrimesTester tester = new PrimesTester(); // The tester object
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
System.out.print("Enter a number: ");
inputString = input.readLine();
bound = Integer.parseInt(inputString);
System.out.println("The primes less than " + bound + " are:");
count = tester.countPrimesLessThanN(bound);
System.out.println("\nThere are " + count + " primes less then " + bound);
}// main()
} // PrimesTester
26. Your little sister asks you to help her with her multiplication and you decide
to write a Java application that tests her skills. The program will let her input a
starting number, such as 5. It will generate multiplication problems ranging from
from 5 1 to 5 12. For each problem she will be prompted to enter the correct
answer. The program should check her answer and should not let her advance to
the next question until the correct answer is given to the current question.
/*
* File: MultTester.java
* Author: Java, Java, Java
* Description: This program conducts a drill and
* practice tutorial for a student learning the
* multiplication tables. The user inputs a starting
* value, say 5. Then the program presents multiplication
* problems starting at 5 x 1, up through 5 x 12. The
* user must provide the correct answer before being
* able to advance.
*/
import java.io.*;
public class MultTester {
/**
156
ter 0 to quit.");
System.out.print("Enter a number: ");
inputString = input.readLine();
startNumber = Integer.parseInt(inputString);
if (startNumber > 0)
multDrill(startNumber);
} while (startNumber != 0);
} // main()
} // MultTester
27. Write an application that prompts the user for four values and draws corresponding bar graphs using an ASCII character. For example, if the user entered 15, 12,
9, and 4, the program would draw
******************
************
*********
****
/*
* File: Grapher.java
* Author: Java, Java, Java
* Description: This program draws a horizontal bar
* graph from input received from the user.
*/
import java.io.*;
public class Grapher {
/**
* drawBar() draws a horizontal bar of length n
* @param n -- the number of asterisks in the bar
* Algorithm: Because we know how many asterisks to
* to draw, we use a counting (for) loop
*/
public void drawBar(int n) {
for (int k = 0; k < n; k++) {
System.out.print(*);
}
System.out.println();
} // drawBar()
/**
* main() gets the input from the user and uses an
* instance of this class to draw the bar graph.
*/
public static void main(String args[]) throws IOException {
157
158
");
");
");
");
28. Revise the application in the previous problem so that the bar charts are displayed
vertically. For example, if the user inputs 5, 2, 3, and 4, the program should
display
**
**
**
**
** **
** ** ** **
** ** ** **
------------/*
* File: BarGraph.java
* Author: Java, Java, Java
* Description: This program prints a vertical bar graph
* with the four values input by the user. The trick to
* solving this problem is knowing the size of the largest
* bar in the graph. The getLargest() method determines
* that value.
159
*/
import java.io.*;
public class BarGraph {
/**
* getLargest() returns the value of the largest of its
* four int parameters.
* @param -- four integer values
* @return -- the value of the largest parameter
* Algorithm: For each of the 4 parameters, assume that
* it is the largest and compare it with all the others.
* If it is greater than or equal to the others, set
* the boolean flag (foundLargest) to true. This will
* cause the loop to exit. Note that we have used a
* for loop with a compound entry condition. The can
* terminate because all four cases have been tried or
* because the first value (a) is the largest.
*/
public static int getLargest(int a, int b, int c, int d) {
int largest = 0;
boolean foundLargest = false;
for (int k = 0; k < 4 && !foundLargest; k++) { // For each of the 4 params
if (k == 0)
// Assume it is the largest
largest = a;
else if (k == 1)
largest = b;
else if (k == 2)
largest = c;
else
largest = d;
if (largest >= a && largest >= b && largest >= c && largest >= d)
foundLargest = true;
} // for
return largest;
} // getLargest()
/**
* printGraph() prints a vertical bar graph of its four
* parameter values. To determine the height of the graph
* it first begins by finding the largest of the four
* parameters. That determines the bound on the outer four loop,
* which determines the height of the graph. The inner for loop
* prints each row. So it goes through each of the four variables
* and either prints asterisks or spaces for that variable,
* depending on whether that variable is greater than the
* current height or not.
160
*/
public static void printGraph(int a, int b, int c, int d) {
int number = 0;
for (int hgt = getLargest(a,b,c,d); hgt > 0; hgt--) { // For each row
for (int var = 0; var < 4; var++) {
// For each variable
if (var == 0)
number = a;
// Assign its value to number
else if (var == 1)
number = b;
else if (var == 2)
number = c;
else
number = d;
if (number >= hgt)
// If the vars value is high enough
System.out.print("** "); // print asterisks
else
System.out.print("
"); // Otherwise print blanks
} // inner for
System.out.println(); // Start a new line
} // outer for
} // printGraph()
/**
* main() inputs four integers and prints a horizontal
* bar graph showing their relative values.
*/
public static void main(String args[]) throws IOException{
String inputString;
int A, B, C, D;
// The four input values
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
System.out.println("Enter the first value:");
inputString = input.readLine();
A = Integer.parseInt(inputString);
System.out.println("Enter the second value:");
inputString = input.readLine();
B = Integer.parseInt(inputString);
System.out.println("Enter the third value:");
inputString = input.readLine();
C = Integer.parseInt(inputString);
System.out.println("Enter the fourth value:");
inputString = input.readLine();
D = Integer.parseInt(inputString);
System.out.println("This is what your graph looks like");
printGraph(A,B,C,D);
} // main()
} // BarGraph
29. The Fibonacci sequence (named after the Italian mathematician Leonardo of
Pisa, ca.1200) consists of the numbers 0; 1; 1; 2; 3; 5; 8; 13; : : : in which each
number (except for the first two) is the sum of the two preceding numbers. Write
a method fibonacci(N) that prints the first N Fibonacci numbers.
/*
* File: Fibonacci.java
* Author: Java, Java, Java
* Description: This program prints the first N values
* of the Fibonacci sequence. The sequence starts with
* 0, 1, 1, 2, 3, 5, 8, 13, ... Each term in the sequence
* (except the first two) is the sum of the two previous
* terms.
*/
import java.io.*;
public class Fibonacci {
/**
* doFibonacci() prints the first n values of the
* fibonacci sequence.
* @param n -- an int giving the number of values to print
* Algorithm: The bound in this case is a counting bound
* and therefore we can use a counting (for) loop.
*/
public static void doFibonacci(int n) {
int a = 0;
int b = 1;
int c = 0;
for (int counter = 1; counter <= n; counter++) {
if (counter == 1)
System.out.print(a + ", ");
if (counter == 2)
System.out.print(b + ", ");
if (counter >= 3) {
c = a + b;
a = b;
b = c;
System.out.print(c + ", ");
}
} // for
System.out.println();
} // doFibonacci
/**
* main() inputs a number, N, from the user and then prints
* the first N values of the fibonacci sequence.
*/
public static void main(String args[]) throws IOException{
161
30. The Nuclear Regulatory Agency wants you to write a program that will help
them determine how long certain radioactive substances will take to decay. The
program should let the user input two values: a string giving the substances
name, and its half-life in years. (A substances half-life is the number of years
required for the disintegration of half of its atoms.) The program should report
how many years it will take before there is less than 2 percent of the original
number of atoms remaining.
/*
* File: HalfLife.java
* Author: Java, Java, Java
* Description: This program calculates how many years will
* transpire before a substance X with a half life of Y will
* have less than 2 percent of its radioactivity left.
*/
import java.io.*;
public class HalfLife {
/**
* calcYears() computes the number of years a substance with
* a half life of n years will last before 2 percent of its
* radioactive atoms are left
* @param n -- an int giving the stuffs half life
* @return -- an int giving the number of years of life
* Algorithm: The loop in this case uses a limit bound.
* It will iterate as long as the amount is greater than
* 2 percent of the original amount.
*/
public static int calcYears(int n) {
double amt = 100;
// Start with 100 percent of the stuff
int years = 0;
while (amt > 2) {
// While more than 2 percent
amt -= amt * 0.5; // Divide the substance in half
162
years += n;
}
return years;
} // calcYears()
163
/**
* main() inputs the name and half life of a radioactive substance
* and then calls a method to calculate the number of years it will last.
*/
public static void main(String args[]) throws IOException{
BufferedReader input = new BufferedReader
(new InputStreamReader(System.in));
System.out.println("This program computes the lifetime of a radioactive substance. ");
System.out.print("Enter the name of the substance: ");
String name = input.readLine();
System.out.print("Enter the half life of the substance (in years): ");
String inputString = input.readLine();
int halfLife = Integer.parseInt(inputString);
System.out.println("The " + name + " will last for " + calcYears(halfLife)
+ " years before less then 2% is left");
} // main()
} // HalfLife
31. Modify the CarLoan program so that it calculates a users car payments for
loans of different interest rates and different loan periods. Let the user input
the amount of the loan. Have the program output a table of monthly payment
schedules.
/*
* File: CarLoan.java
* Author: Java, Java, Java
* Description: This program prints a table showing the
* total cash outlay for a car purchase. The table gives
* a breakdown for different interest rates and for 2
* through 8 years.
*/
import java.io.*;
import java.text.NumberFormat;
public class CarLoan {
/**
* convertStringToDouble() converts its string parameter to a double
* @param s -- a String to be converted
* @return a double representing the number stored in s
*/
private static double convertToDouble(String s) {
164
Exercise 6.18
165
Exercise 6.19
Box
ConsecutiveSequence
+main()
Exercise 6.21
Exercise 6.20
GuessingGame
SequenceTester
+main()
Exercise 6.22
FireExtinguisher
Exercise 6.24
PiTester
NewtonTester
+countIterations() : long
+main()
-convertToDouble() : String
+countGuesses(in num : double, in guess : double) : int
+main()
Exercise 6.26
Exercise 6.25
PrimesTester
MultTester
+multDrill(in n : int)
+main()
Exercise 6.28
Grapher
+drawBar(in n : int)
+main()
Exercise 6.29
Fibonacci
+doFibonacci(in n : int)
+main()
datatype
boolean
BarGraph
Exercise 6.31
HalfLife
CarLoan
Chapter 7
167
(a) The fact that the first character in a string has index 0 is known as
Answer: zero indexing
. An-
cipher. Answer:substitution
3. Given the String str with the value to be or not to be that is the question,
write Java expressions to extract each of the following substrings. Provide two
sets of answers. One that uses the actual index numbers of the substrings for
example, the first to goes from 0 to 2 and the second that will retrieve the
same substring from the following string it is easy to become what you want
to become. (Hint: In the second case, use length() and indexOf() along
with substring() in your expressions. If necessary, you may use local variables to store intermediate results. The answer to (a) is provided as an example.)
(a) the first to in the string
str.substring(0,2);
str.substring(str.indexOf(t), str.indexOf(o) + 1;
(f) the last four characters in the string (e) the first four characters in the string
str.substring(0,4);
str.substring(str.length() - 5, str.length() - 1);
4. Identify the syntax errors in each of the following: Assume that the String s
equals exercise.
(a) s.charAt("hello")
(b) s.indexOf(10)
acters long
(c) s.substring("er")
(d) s.lastIndexOf(er)
(e) s.length
ter length
5. Evaluate each of the following expressions assuming that the String s equals
exercise.
(a)
(b)
(c)
(d)
(e)
s.charAt(5)
s.indexOf("er")
s.substring(5)
s.lastIndexOf(e)
s.length()
==
==
==
==
==
i
2
"ise"
7
8
168
*/
public boolean equals(String str1, String str2) {
if (str1.length() != str2.length())
return false;
else for (int k = 0; k < str1.length(); k++)
if (str1.charAt(k) != str2.charAt(k))
return false;
return true;
} // equals()
8. Write a method for the StringTricks class that takes a String argument
and returns a String result which is the lowercase version of the original string.
/**
* lowercase() converts its String parameter to lowercase
* @param str -- a String to be converted
* @return a String containing only lowercase letters
* Algorithm: Go through each letter in the string and if
* a letter is an uppercase, convert it to lowercase.
*/
public String lowercase(String str){
StringBuffer result = new StringBuffer();
for (int k = 0; k < str.length(); k++) {
if ((str.charAt(k) > A) && (str.charAt(k) < Z))
result.append((char)(str.charAt(k) + 32));
else
result.append((char)str.charAt(k));
}
return result.toString();
} // lowercase()
9. Implement a method that uses the following variation of the Caesar cipher. The
method should take two parameters, a String and an int N. The result should
be a String in which the first letter is shifted by N, the second by N + 1, the
third by N + 2, and so on. For example, given the string Hello, and an initial
shift of 1, your method should return Igopt.
/**
* specialCaesar() performs a variation of a Caesar shift
* on its string parameter. The shift increases by 1 for
* each character.
* @param s -- a String to be shifted
* @param shift -- an integer giving the initial shift
* @return a String containing the shifted string
* Algorithm: Increment the shift by 1 on each iteration,
* taking care to wrap around (with modular arithmetic)
* if necessary.
*/
public String specialCaesar(String s, int shift) {
169
170
10. Challenge: Imagine a Caesar cipher that uses the letters of a keyword to determine the shift of each letter in the plaintext. For example, suppose we choose the
word ace as the keyword. You could also think of ace in terms of how many
places each of its letters is shifted from the letter a. Thus a is shifted by 0, c
is shifted by 2, and e is shifted by 4. So given this keyword, the first letter of
the plaintext would be shifted by 0, the second by 2, the third by 4, the fourth by
0, and so on. For example,
key:
plaintext:
shift:
ciphertext:
acea
this
0240
tjms
ce
is
24
jw
a
a
0
a
ceacea
secret
240240
uictit
ceaceac
message
2402402
oisuegg
Write a method to implement this cipher. The method should take two String
arguments: the string to be encrypted and the keyword.
/**
* caesarChallenge() performs a variation of a Caesar shift
* on its string parameter. It uses the keyword to determine
* the shift for each letter. To simplify this, we change
* everything to lowercase.
* @param s -- a String to be shifted
* @param keyword -- a String whose letters are treated as shifts
* @return a String containing the shifted string
* Algorithm: Let m point be an index to the chars in keyword.
* Then on each iteration, increment m, wrapping around to 0
* when the end of the keyword is reached. Take the mth char
* of the keyword and subtract a from it to get a value between
* 0 and 25 that is used as the shift.
*/
public String caesarChallenge(String s, String keyWord) {
StringBuffer result = new StringBuffer();
s = lowercase(s);
// Lowercase the
keyWord = lowercase(keyWord);
// Lowercase the keyword
171
int m = 0;
// m points to keyword chars
int shiftValue = keyWord.charAt(m) - a; // Get initial shift value
for (int k = 0; k < s.length(); k++) {
char ch = s.charAt(k);
if (ch >= a && ch <= z) {
ch = (char)(a + (ch - a + shiftValue) % 26);
m = (m +1) % keyWord.length();
// Move m along with wraparound
shiftValue = keyWord.charAt(m) - a; // Get new shift
}
result.append(ch);
}
return result.toString();
} // caesarChallenge()
11. One way to make it more difficult to decipher a secret message is to destroy the
word boundaries. For example, consider the following two versions of the same
sentence:
Plaintext:
This is how we would ordinarily write a sentence.
Blocked text: Thisi showw ewoul dordi naril ywrit easen tence.
Write a method that converts its String parameter so that letters are written in
blocks five characters long.
/**
* convertToFive() removes the natural word boundaries in s
* and creates a new string with blocks of 5 characters
* @param s -- a String to be processed
* @return a String with 5-character blocks
*/
private String convertToFive(String s){
StringBuffer result = new StringBuffer();
for (int k = 0; k < s.length(); k++) {
if ((k+1) % 5 != 0){
result.append(s.charAt(k));
}
else if ((k + 1) % 5 == 0)
result.append(s.charAt(k) + " ");
}
return result.toString();
} // convertToFive()
12. Design and implement an applet that lets the user type a document into a TextArea,
and then provides the following analysis of the document: The number of words
in the document, the number of characters in the document, and the percentage
of words that had more than six letters.
172
173
/*
* File: AnalyzeDocApplet.java
* Author: Java, Java, Java
* Description: This applet provides a user interface
* for the DocumentAnalyzer object. The user can enter
* text into a TextArea and click a button. The DocumentAnalyzer
* will then report a count of the characters and words, and the
* percentage of words with more than LONG characters,
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class AnalyzeDocApplet extends Applet implements ActionListener {
private static final int LONG = 6;
private
private
private
private
// GUI components
Label prompt;
TextArea inputArea;
Button button;
TextArea outputArea;
/**
* init() sets up the GUI for the applet.
*/
public void init() {
prompt = new Label("Enter a document to analyze:");
inputArea = new TextArea(5,50);
inputArea.setEditable(true);
outputArea = new TextArea(5,50);
button = new Button("Analyze");
button.addActionListener(this);
add(prompt);
add(inputArea);
add(button);
add(outputArea);
setSize(300,300);
} // init()
/**
* actionPerformed() creates a DocumentAnalyzer and
* gets it to perform the analysis of the text in the TextArea
*/
public void actionPerformed(ActionEvent e) {
DocumentAnalyzer analyzer = new DocumentAnalyzer(inputArea.getText());
outputArea.setText("");
int nWords = analyzer.countWords();
174
} // numberOfWords()
/**
* countChars() counts the characters, including whitespace, in the
* document
* @return an int giving the number of characters
*/
public int countChars() {
return document.length();
}
/**
* countLongWords() counts the number of words having more
* than n characters. Note that it is necessary to use a
* a local StringTokenizer here because each time nextToken()
* is called it removes a token from the StringTokenizer.
* @param n -- the length of a long word
* @return an int giving the number of long words
*/
public int countLongWords(int n) {
StringTokenizer tokenizer = new StringTokenizer(document);
int counter = 0;
while (tokenizer.hasMoreTokens()) {
String s = tokenizer.nextToken();
if (s.length() > n)
counter++;
}
return counter;
} // countLongWords()
} // DocumentAnalyzer
13. Design and write an applet that searches for single-digit numbers in a text and
changes them to their corresponding words. For example, the string 4 score and
7 years ago would be converted into four score and seven years ago.
/*
* File: DigitConverterApplet.java
* Author: Java, Java, Java
* Description: This applet lets the user type in
* text and then converts each digit in the text
* to its corresponding number name -- e.g., 7 to
* "seven."
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
175
Figure 7.2: The DigitConverterApplet converts the digits in a text into words
e.g., 7 into seven.
176
177
* @param ch -- a char
* @return a boolean true iff ch is a digit
*/
public boolean isDigit (char ch) {
if (ch >= 0 && ch <= 9)
return true;
else
return false;
} // isDigit()
/**
* convert() converts is digit parameter to a word
* for example 9 to "nine"
* @digit a char giving a 0 to 9
* @return a String representing the digit
*/
public String convert (char ch) {
if (ch == 0)
return "zero";
else if (ch == 1)
return "one";
else if (ch == 2)
return "two";
else if (ch == 3)
return "three";
else if (ch == 4)
return "four";
else if (ch == 5)
return "five";
else if (ch == 6)
return "six";
else if (ch == 7)
return "seven";
else if (ch == 8)
return "eight";
else if (ch == 9)
return "nine";
else
return "error";
} // convert()
/**
* findAndChange() changes each digit in s to
* its corresponding number name: 7 to "seven"
* @param s -- a String of text to be converted
* @return a String giving the processed text
*/
public String findAndChange(String s) {
StringBuffer result = new StringBuffer();
char ch;
178
14. A palindrome is a string that is spelled the same way backwards and forwards.
For example, mom, dad, radar, 727 and able was i ere i saw elba are all examples
of palindromes. Write a Java applet that lets the user type in a word or phrase,
and then determines whether the string is a palindrome.
/*
* File: PalindromeApplet.java
* Author: Java, Java, Java
* Description: This applet provides a user interface
* for the Palindrome object, which determines whether
* strings input into a TextArea are palindromes.
* The interface contains two TextAreas, one for input
* and one for output, and a button to start the test.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class PalindromeApplet extends Applet implements ActionListener {
private
private
private
private
Label prompt;
TextArea inputArea;
Button button;
TextArea outputArea;
/**
* init() sets up the user interface
*/
public void init(){
prompt = new Label("Enter a sentence to test:");
inputArea = new TextArea(5,40);
inputArea.setEditable(true);
outputArea = new TextArea(5,40);
button = new Button("Test Palindrome");
button.addActionListener(this);
add(prompt);
179
Figure 7.3: The PalindromeApplet tests whether input strings are palindromes.
180
add(inputArea);
add(button);
add(outputArea);
setSize(400,400);
} // init()
/**
* actionPerformed() tests the string in the input TextArea
* to see if it is a palindrome and reports the result.
*/
public void actionPerformed(ActionEvent e){
Palindrome pal = new Palindrome();
String document = new String(inputArea.getText());
if (pal.isPalindrome(document))
outputArea.setText(document + " is a palindrome");
else
outputArea.setText(document + " is NOT a palindrome");
} // actionPerformed()
} // PalindromeApplet.java
/*
* File: Palindrome.java
* Author: Java, Java, Java
* Description: This class contains methods to determine
* whether a string is a palindrome or not. A palindrome
* is a string that is equal to its reverse.
*/
import java.util.*;
public class Palindrome
/**
* reverse() reverses the characters in its parameter
* @param s -- a String to be reversed
* @return a String giving the reverse of s
*/
private String reverse(String s) {
StringBuffer result = new StringBuffer();
for (int k = s.length() - 1; k >= 0; k--)
result.append(s.charAt(k));
return result.toString();
}
/**
* isPalindrome() tests whether its string is a palindrome
* @param s -- a String to be tested
* @return a boolean set to true iff s is a palindrome
*/
public boolean isPalindrome(String s) {
181
182
return s.equals(reverse(s));
} // isPalindrome()
} // Palindrome
15. Suppose youre writing a maze program and are using a string to store a representation of the maze. For example, consider the following string and the
corresponding maze:
String: XX_XXXXXXXX__XXX_XXXX_XX____XXX_XX_XX_XXX____XXXXXXXXX_X___X
Maze:
XX XXXXXXX
X XXX XXX
X XX
XX
X XX XX XX
X
XXXXX
XXXX X
X
Write a method that accepts such a string as a parameter and prints a twodimensional representation of the maze.
/*
* File: Maze.java
* Author: Java, Java, Java
* Description: This class contains a method to
* convert a String such into a two-dimensional maze
* of asterisks.
*/
public class Maze {
/**
* convertToMaze() prints specially encoded string
* into a two-dimensional maze.
* @param s -- a specially encoded string, such as
*
XX_XXXXXXXX__XXX_XXXX_XX____
*/
public void convertToMaze(String s){
StringBuffer result = new StringBuffer("");
for (int k = 0; k < s.length(); k++) {
if (s.charAt(k) == X)
result.append(X);
else
result.append(" ");
if ( (k+1) % 10 == 0)
result.append("\n");
// Start new line
} // for
System.out.println(result.toString());
183
} // convertToMaze()
public static void main(String argv[]) {
Maze maze = new Maze();
String s = "XX_XXXXXXXX__XXX_XXXX_XX____XXX_XX_XX_XXX____XXXXXXXXX_X___X";
System.out.println("String " + s);
maze.convertToMaze(s);
} // main()
} // Maze
16. Write a method that takes a delimited string, which stores a name and address,
and prints a mailing label. For example, if the string contains Sam Penn:14
Bridge St.:Hoboken:NJ:01881, the method should print
Sam Penn
14 Bridge St.
Hoboken, NJ 01881
/**
* convertToAddress() converts a delimited string to
* a mailing label
* @param s -- a string of the form name:street:city:state:zip
*/
public void convertToAddress(String s){
StringTokenizer words = new StringTokenizer(s,":");
StringBuffer result = new StringBuffer();
int tokenNum = 0;
while (words.hasMoreTokens()) {
if (tokenNum < 2)
System.out.println(words.nextToken());
if (tokenNum == 2 || tokenNum == 4)
System.out.print(words.nextToken() + " ");
if (tokenNum == 3)
System.out.print(words.nextToken() + ", ");
tokenNum++;
} // while
} // convertToAddress()
17. Design and implement a Cipher subclass to implement the following substitution cipher: each letter in the alphabet is replaced with a letter from the opposite
end of the alphabet: a is replaced with z, b with y, and so forth.
/*
* File: SubstitutionCipherApplet.java
* Author: Java, Java, Java
* Description: This applet provides an interface that
* lets the user encrypt and decrypt messages. The user
* can click an encode or decode button to encrypt/decrypt
184
185
/*
* File: MyCipher.java
* Author: Java, Java, Java
* Description: This is a subclass of Cipher which
* implements the following substitution cipher: each letter
* in a word is replaced by a letter from the opposite end
* of the alphabet. a with z, b with y, and so on.
*/
public class MyCipher extends Cipher {
/**
* encode() replaces each letter in word with its counterpart
*
from the opposite end of the alphabet a with z, etc.
* @param word -- a word to be encoded
* @return -- a string giving the encoded word
*/
public String encode(String word) {
StringBuffer result = new StringBuffer();
for (int k = 0; k < word.length(); k++){
char ch = word.charAt(k);
int shiftValue = ch - a;
ch = (char)(z - shiftValue);
result.append(ch);
}
return result.toString();
} // encode()
/**
* decode() is the same as the encode() method
* @param word -- a word to be decoded
* @return -- a string giving the decoded word
*/
public String decode(String word) {
return encode(word);
} // decode()
} // MyCipher
18. One way to design a substitution alphabet for a cipher is to use keyword to construct the alphabet. For example, suppose the keyword is zebra. You place the
keyword at the beginning of the alphabet, and then fill out the other 21 slots with
remaining letters, giving the following alphabet:
Cipher alphabet:
Plain alphabet:
zebracdfghijklmnopqstuvwxy
abcdefghijklmnopqrstuvwxyz
Design and implement an Alphabet class for constructing these kinds of substitution alphabets. It should have a single public method that takes a keyword
String as an argument and returns an alphabet string. Note that an alphabet
186
19. Design and write a Cipher subclass for a substitution cipher that uses an alphabet from the Alphabet class created in the previous exercise.
/*
187
Figure 7.5: A substitution cipher that uses a keyword to construct a cipher alphabet.
188
* File: KeywordCipher.java
* Author: Java, Java, Java
* Description: This is a subclass of Cipher which
* implements a substitution cipher on a keyword. The keyword
* is used to create a cipher alphabet. Then each letter from the
* in the plaintext is replaced by the corresponding letter (by
* position) from the cipher alphabet. Decryption works just the
* opposite way: letters from the ciphertext are replaced by the
* corresponding letter from the plain alphabet.
*/
public class KeywordCipher extends Cipher {
private String plainAlphabet = "abcdefghijklmnopqrstuvwxyz";
private String cipherAlphabet;
private Alphabet alpha;
/**
* KeywordCipher() creates a cipher alphabet to be
* used in encoding and decoding.
*/
public KeywordCipher(String keyword) {
super();
alpha = new Alphabet();
cipherAlphabet = alpha.newAlphabet(keyword);
}
/**
* encode() replaces each letter in word with the corresponding
*
letter from the cipher alphabet
* @param word -- a word to be encoded
* @return -- a string giving the encoded word
*/
public String encode(String word) {
StringBuffer result = new StringBuffer();
for (int k = 0; k < word.length(); k++) {
int num = plainAlphabet.indexOf(word.charAt(k));
char ch = cipherAlphabet.charAt(num);
result.append(ch);
}
return result.toString();
} // encode()
/**
* decode() is the same as the encode() method
* @param word -- a word to be decoded
* @return -- a string giving the decoded word
*/
public String decode(String word) {
StringBuffer result = new StringBuffer();
189
190
add(outputArea);
setSize(500,500);
} // init()
/**
* actionPerformed() either encrypts or decrypts the
* TextField depending on which button the user clicked.
*/
public void actionPerformed(ActionEvent e){
String keyword = keyField.getText();
String inputString = inputField.getText();
KeywordCipher cipher = new KeywordCipher(keyword);
if (e.getSource() == encode)
outputArea.setText(cipher.encrypt(inputString));
else
outputArea.setText(cipher.decrypt(inputString));
} // actionPerformed()
} // SubstitutionCipherApplet
20. Design and implement an applet that plays Time Bomb with the user. Heres how
the game works. The computer picks a secret word and then prints one asterisk
for each letter in the word: * * * * *. The user guesses at the letters in the word.
For every correct guess, an asterisk is replaced by a letter: * e * * *. For every
incorrect guess, the time bombs fuse grows shorter. When the fuse disappears,
after say six incorrect guesses, the bomb explodes. Store the secret words in a
delimited string and invent your own representation for the time bomb.
/*
* File: TimeBombApplet.java
* Author: Java, Java, Java
* Description: This program plays the game of
* "time bomb." The user is given a secret word
* and tries to guess its letters. Each time a
* correct letter is guessed, its position in the
* word is displayed. The time bomb goes off after
* the user makes six wrong guesses.
* In this design, the applet (this class) handles the user
* interface and a separate object, a SecretWord, handles
* the processing of the users guesses.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class TimeBombApplet extends Applet implements ActionListener {
191
Figure 7.6: The TimeBombApplet plays a guessing game with the user.
192
193
// SecretWord object
/**
* init() sets up the applets interface which consists of a TextField
* in which the user inputs a guess, and a TextArea which displays
* the results of each guess. An ActionListener is assigned to the
* TextField.
*/
public void init() {
prompt1 = new Label("Enter a letter you think is in the secret word.");
prompt2 = new Label("You have six guesses to figure out the word.");
inputField = new TextField(30);
inputField.setEditable(true);
inputField.addActionListener(this);
outputArea = new TextArea(5,30);
add(prompt1);
add(prompt2);
add(inputField);
add(outputArea);
setSize(300,300);
secret.reset();
outputArea.append("The secret word: " + secret.checkProgress() +"\n");
} // init()
/**
* actionPerformed() handles action events in the TextField.
*/
public void actionPerformed(ActionEvent e) {
numberOfGuesses++;
int guessesLeft = 6 - numberOfGuesses;
inputString = inputField.getText();
inputField.setText("");
boolean guess = secret.makeGuess(inputString.charAt(0));
// Process the users guess
if (guess == true)
outputArea.append ("That Guess Was Right\n");
else
outputArea.append ("That Guess Was Wrong\n");
if (secret.isGuessed()) {
outputArea.append("Very good! You guessed the se-
194
/**
* reset() selects a new secretWord from wordList
*/
public void reset() {
secretWord = wordList.nextToken();
StringBuffer result = new StringBuffer("");
195
result.append(secretWord.charAt(k));
else if (secretWord.charAt(k) != ch)
result.append(guessedWord.charAt(k));
isRight = true;
}
// Otherwise, guessedWord is unchanged
else if (secretWord.indexOf(ch) == -1) {
result.append(guessedWord);
isRight = false;
}
guessedWord = result.toString();
// Update guessedWord
return isRight;
} // makeGuess()
} // SecretWord
21. Challenge: A common string processing algorithm is the global replace function found in every word processor. Write a method that takes three String
arguments: a document, a target string, and a replacement string. The method
should replace every occurrence of the target string in the document with the
replacement string. For example, if the document is To be or not to be, that is
the question and the target string is be and the replacement string is see, the
result should be To see or not to see, that is the question.
/*
* File: GlobalReplace.java
* Author: Java, Java, Java
* Description: This class tests the replace() method.
*/
public class GlobalReplace {
/**
* replace() replaces every occurrence of tar with rep
*
in the String doc
* @param doc -- a String to be processed
* @param targ -- a target String to be replaced
* @param repl -- a replacement String
* Algorithm: Use indexOf() to find the location of the
* target substring. Then replace the original string
* with the characters to the left of the target, the
* replacement string, and the characters to the right
* of the target. The loop exits when indexOf() returns 1,
* indicating that there are no further occurrences of the
* target in the string.
*/
public String replace(String doc, String targ, String repl){
int p = doc.indexOf(targ);
int targLen = targ.length();
196
while (p != -1) {
// While more occurrences
doc = doc.substring(0,p) + repl + doc.substring(p+targLen);
p = doc.indexOf(targ);
}
return doc;
} // replace()
public static void main(String argv[]) {
GlobalReplace replacer = new GlobalReplace();
String result = replacer.replace("Mississippi", "ss", "tt");
System.out.println(result);
} // main()
} // GlobalReplace
22. Challenge: Design and implement an applet that plays the following game with
the user. Let the user pick a letter between A and Z. Then let the computer
guess the secret letter. For every guess the player has to tell the computer whether
its too high or too low. The computer should be able to guess the letter within
five guesses. Do you see why?
/*
* File: GuessingGame.java
* Author: Java, Java, Java
* Description: This applet plays a simple guessing game
* with the user. It lets the user pick a letter between
* A and Z and then it guesses the secret within five
* guesses. The algorithm it uses splits the alphabet in
* half and guesses the middle letter each time. So the
* first guess will be M, and the user will answer "too
* high" or "too low" or "just right."
*/
import
import
import
import
java.util.*;
java.applet.*;
java.awt.*;
java.awt.event.*;
197
Figure 7.7: The GuessingGame applet guesses the users secret letter.
198
199
/**
* init() sets up the user interface, which contains three buttons
* that tell the program whether the guess was high, low or correct.
* It also contains a TextArea to report the progress of the game.
*/
public void init() {
prompt1 = new Label("Think of a letter and click Start.");
prompt2 = new Label("I will then try to guess the letter you entered.");
outputArea = new TextArea(5,40);
tooHigh = new Button("Too High");
tooHigh.addActionListener(this);
tooLow = new Button("Too Low");
tooLow.addActionListener(this);
start = new Button("Start");
start.addActionListener(this);
add(prompt1);
add(prompt2);
add(start);
add(tooHigh);
add(tooLow);
add(outputArea);
setSize(300,300);
} // init()
/**
* actionPerformed() handles clicks on the applets buttons.
* The guesser object manages the guessing task. Each time
* getGuess() is called, it returns a new guess. When
* guessTooHigh() and guessTooLow() are called, guesser adjusts
* the range of the alphabet that it must search.
* @param e -- the ActionEvent that generated this method call
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == start) {
guesser.reset();
outputArea.setText("");
outputArea.append("My guess is " + guesser.getGuess() + "\n");
outputArea.append("Tell me if my guess is too high or low.\n");
}
else if (e.getSource() == tooHigh) {
guesser.guessTooHigh();
outputArea.append("My guess is " + guesser.getGuess() + "\n");
outputArea.append("Tell me if my guess is too high or low.\n");
}
else if (e.getSource() == tooLow) {
guesser.guessTooLow();
outputArea.append("My guess is " + guesser.getGuess() + "\n");
200
23. Challenge: Find a partner and concoct your own encryption scheme. Then
work separately with one partner writing encode() and the other writing decode(). Test to see that a message can be encoded and then decoded to yield
the original message.
/*
* File: CodeApplet.java
* Author: Java, Java, Java
* Description: This applet provides a GUI for
* the Coder class. It lets the user type text into
* a TextArea and then encodes the text using a cipher
* supplied by the Coder object.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class CodeApplet extends Applet implements ActionListener
{
private Label prompt;
// The GUI components
private TextArea inputArea;
private TextArea outputArea;
private String inputString;
private Button encode;
private Button decode;
Coder coder = new Coder();
// The Coder object
/**
* init() sets up the applets interface
*/
public void init() {
prompt = new Label ("Enter a document to encode or decode:");
encode = new Button("Encode");
201
202
/**
* encode() encrypt its string parameter
* @param s -- a String to be processed
* @return a String that is encrypted
*/
public String encode (String s) {
StringBuffer result = new StringBuffer("");
StringTokenizer words = new StringTokenizer(s);
while (words.hasMoreTokens()) {
String str = words.nextToken() + " "; // Get each word
str = str.toLowerCase();
// Lowercase it
result.append(invertWord(str));
// Invert it
}
String newStr = result.toString();
newStr = specialTakeOutSpaces(newStr); // Insert jzs
newStr = convertToFive(newStr);
// Make blocks of 5
return newStr;
// Return it
} // encode()
/**
* decode() decrypts its string parameter
* @param s -- a String to be processed
* @return a String that is decrypted
*/
public String decode (String s) {
StringBuffer result = new StringBuffer("");
String noSpaces = takeOutSpaces(s);
// Remove all spaces
StringTokenizer words = new StringTokenizer(noSpaces, "jz");
while (words.hasMoreTokens()) {
String str = words.nextToken() + " "; // Get each word
str = str.toLowerCase();
// Lowercase it
result.append(invertWord(str));
// Invert it
}
return result.toString();
// Return the result
} // decode()
/**
* takeOutSpaces() removes the spaces from s
* @param s -- a String to be processed
* @return a String with its spaces removed
*/
private String takeOutSpaces (String s) {
StringBuffer result = new StringBuffer("");
StringTokenizer words = new StringTokenizer(s);
while (words.hasMoreTokens())
result.append(words.nextToken());
return result.toString();
203
} // takeOutSpaces()
/**
* specialTakeOutSpaces() removes the spaces from s
* and replaces them with "jz"
* @param s -- a String to be processed
* @return a String with its spaces replaced by "jz"
*/
private String specialTakeOutSpaces (String s) {
StringBuffer result = new StringBuffer("");
StringTokenizer words = new StringTokenizer(s);
while (words.hasMoreTokens())
result.append(words.nextToken() + "jz");
return result.toString();
} // specialTakeOutSpaces()
/**
* convertToFive() removes the natural word boundaries in s
* and creates a new string with blocks of 5 characters
* @param s -- a String to be processed
* @return a String with 5-character blocks
*/
private String convertToFive(String s){
StringBuffer result = new StringBuffer();
for (int k = 0; k < s.length(); k++) {
if ((k+1) % 5 != 0){
result.append(s.charAt(k));
}
else if ((k + 1) % 5 == 0)
result.append(s.charAt(k) + " ");
}
return result.toString();
} // convertToFive()
/**
* invertWord() inverts the letters in a string
* replacing the first with the last and vice versa
* @param s -- a String to be processed
* @return a String that has been flipped
*/
private String invertWord (String s){
StringBuffer result = new StringBuffer("");
char character;
for (int k = 0; k < s.length(); k++) {
character = s.charAt((s.length() - 1) - k);
result.append(character);
}
return result.toString();
} // invertWord()
} // Coder
204
205
24. Challenge: A list is a sequential data structure. Design a List class which uses
a comma-delimited String such as, a,b,c,d,12,dog to implement a list.
Implement the following methods for this class:
void addItem( Object o );
// Use Object.toString()
String getItem(int position);
String toString();
void deleteItem(int position);
void deleteItem(String item);
int getPosition(String item);
String getHead();
// First element
List getTail();
// All but the first element
int length();
// Number of items
/*
* File: List.java
* Author: Java, Java, Java
* Description: This class uses a comma,delimited string to store
* strings in a list. It implements a variety of standard list
* processing methods.
*/
import java.util.*;
public class List {
private StringBuffer list = new StringBuffer();
/**
* List() constructor creates a list using s as its initial
* value.
* @param s -- a comma-delimited String such as "a,b,c,12,dog"
*/
public List(String s) {
list.append(s);
} // List()
/**
* addItem() appends a String representation of the Object o to the list
* @param o -- a reference to an Object
*/
public void addItem(Object o) {
list.append(o.toString() + ",");
} // addItem()
/**
* getItem() returns the item stored in the nth position
* @param n -- an int giving the items position
* @return a String representing the nth item
*/
206
207
// If it matches item
// return its position
25. Challenge: Use a delimited string to create a PhoneList class with an instance
method to insert names and phone numbers, and a method to look up a phone
number given a persons name. Since your class will take care of looking things
up, you dont have to worry about keeping the list in alphabetical order. For
example, the following string could be used as such a directory:
mom:860-192-9876::bill g:654-0987-1234::mary lancelot:123842-1100
/*
* File: PhoneListApplet.java
* Author: Java, Java, Java
* Description: This applet provides a user interface
* to a phonelist. It provides buttons that let the
* user add, remove, and lookup entries in a phone list.
*/
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class PhoneListApplet extends Applet implements ActionListener {
private
private
private
private
private
private
Label prompt1;
Label prompt2;
Label prompt3;
Button findNumber;
Button addEntry;
Button removeEntry;
// GUI elements
208
209
210
/**
* init() creates the user interface. Three buttons are
* assigned ActionListeners.
*/
public void init() {
prompt1 = new Label("Add Entry: enter name:phone and press Add");
prompt2 = new Label("Remove Entry : enter name and press Remove");
prompt3 = new Label("Lookup: enter name and press Lookup");
inputField = new TextField(40);
inputField.setEditable(true);
outputArea = new TextArea(5,40);
findNumber = new Button("Lookup");
findNumber.addActionListener(this);
addEntry = new Button("Add");
addEntry.addActionListener(this);
removeEntry = new Button("Remove");
removeEntry.addActionListener(this);
add(prompt1);
add(prompt2);
add(prompt3);
add(inputField);
add(findNumber);
add(addEntry);
add(removeEntry);
add(outputArea);
setSize(400,400);
} // init()
/**
* actionPerformed() handles ActionEvents on the three buttons.
* In each case it gets data from the inputField and invokes
* methods of the phonelist object.
*/
public void actionPerformed(ActionEvent e){
if (e.getSource() == findNumber) {
String name = inputField.getText();
inputField.setText("");
if (phonelist.isAnEntry(name)) {
String num = phonelist.getNumber(name);
outputArea.setText(name + "s phone number is " + num);
} else {
outputArea.setText(name + " does not have an entry");
}
}
211
if (e.getSource() == addEntry) {
String entry = inputField.getText();
inputField.setText("");
phonelist.addEntry(entry);
outputArea.setText(entry + " has been added to your list");
}
if (e.getSource() == removeEntry) {
String name = inputField.getText();
inputField.setText("");
if (phonelist.isAnEntry(name)) {
phonelist.removeEntry(name);
outputArea.setText(name + "s entry is removed");
} else {
outputArea.setText(name + " does not have an entry");
}
}
outputArea.append("\nList: " + phonelist.toString() + "\n");
} // actionPerformed()
} // PhoneListApplet
/*
* File: PhoneList.java
* Author: Java, Java, Java
* Description: This class implements a phone list
* database using a delimited string to store the
* individual entries. Entries take the following form:
*
name1:number1::name2:number2::...
*/
import java.util.*;
public class PhoneList {
private String phoneList = "";
/**
* isAnEntry() returns true iff its parameter is an entry
* of the phone list
* @param name -- a String giving a persons name
* @return the boolean true iff the persons name is on the list
*/
public boolean isAnEntry (String name) {
if (phoneList.indexOf(name) != -1)
return true;
else
return false;
} // isAnEntry()
/**
* addEntry() inserts its parameter into the phone list
212
*
pos1
pos2
* Then pos1 gives the position where the name entry starts
* and pos2 gives the entry ends. So you replace the list
* with the concatenation of the folloinwg two substrings:
* phoneList.substring(0,pos1) and phoneList.substring(pos2 +2).
*/
public void removeEntry(String name) {
StringBuffer result = new StringBuffer("");
int pos1 = getPosition(name);
int pos2 = phoneList.indexOf("::", pos1);
result.append(phoneList.substring(0, pos1));
result.append(phoneList.substring(pos2 + 2));
phoneList = result.toString();
} // removeEntry()
/**
* getPosition() returns the string index of name
* @param name -- a String giving a persons name
*/
public int getPosition(String name) {
return phoneList.indexOf(name);
} // getPosition()
/**
* toString() returns the entire phone list
*/
public String toString() {
return phoneList;
}
} // PhoneList
213
214
Miscellaneous Types
Label
StringBuffer
ActionEvent
Button
StringTokenizer
TextField
TextArea
Exercise 7.12
Exercise 7.13
interface
ActionListener
Applet
+init()
Object
interface
ActionListener
Applet
+actionPerformed()
+init()
+actionPerformed()
AnalyzeDocApplet
-LONG : int = 6
-prompt : Label
-inputArea : TextArea
-button : Button
-outputArea : TextArea
DigitConverterApplet
-prompt : Label
-inputArea : TextArea
-button : Button
-outputArea : TextArea
+init()
+actionPerformed(in e : ActionEvent)
Uses
+init()
+actionPerformed(in e : ActionEvent)
DigitConverter
DocumentAnalzer
-document : String
-words : StringTokenizer
+DocumentAnalyzer(in s : String)
+countWords() : int
+countChars() : int
+countLongWords(in n : int) : int
Exercise 7.17
Exercise 7.14
Applet
+init()
Uses
Applet
interface
ActionListener
+init()
interface
ActionListener
Cipher
+actionPerformed()
+actionPerformed()
+encrypt(in s : String) : String
+decrypt(in s : String) : String
+encode(in s : String) : String
+decode(in s : String) : String
SubstitutionCipherApplet
PalindromeApplet
-prompt : Label
-inputArea : TextArea
-button : Button
-outputArea : TextArea
+init()
+actionPerformed(in e : ActionEvent)
Uses
-prompt : Label
-inputField : TextField
-outputArea : TextArea
-encode : Button
-decode : Button
-inputString : String
+init()
+actionPerformed(in e : ActionEvent)
Palindrome
MyCipher
Uses
+encode(in word : String) : String
+decode(in word : String) : String
Exercises 7.18-7.19
Cipher
interface
ActionListener
Applet
+init()
215
+actionPerformed()
SubstitutionCipherApplet
KeywordCipher
-prompt : Label
-prompt2 : Label
-inputField : TextField
-keyField : TextField
-outputArea
-encode : Button
-decode : Button
-inputString : String
Uses
-plainAlphabet : String
-cipherAlphabet : String
-alpha : Alphabet
+KeywordCipher(in keyword : String)
+encode(in word : String) : String
+decode(in word : String) : String
+init()
+actionPerformed(in e : ActionEvent)
Uses
Alphabet
-PlainAlphabet : String
+newAlphabet(in keyWord : String) : String
+main()
Exercise 7.20
interface
ActionListener
Applet
+init()
+actionPerformed()
TimeBombApplet
SecretWord
Uses
-prompt1 : Label
-prompt2 : Label
-inputField : TextField
-outputArea
-inputString : String
-numberOfGuesses : int = 0
-secret : SecretWord
-secretWord : String
-guessedWord : String
+reset()
+isGuessed() : <unspecified>
+checkProgress() : String
+getSecretWord() : String
+makeGuess(in ch : char) : <unspecified>
+init()
+actionPerformed(in e : ActionEvent)
Miscellaneous Classes
Exercise 7.22
Applet
+init()
interface
ActionListener
Label
StringBuffer
ActionEvent
Button
Object
+actionPerformed()
StringTokenizer
GuessingGame
Uses
-prompt1 : Label
-prompt2 : Label
-tooHigh : Button
-tooLow : Button
-start : Button
-outputArea
-inputString : String
-guesser : Guesser
Guesser
-guess : char
-low : char
-high : char
+init()
+actionPerformed(in e : ActionEvent)
+getGuess() : char
+reset()
+guessTooHigh()
+guessTooLow()
TextField
TextArea
216
Exercise 7.23
Miscellaneous Classes
interface
ActionListener
Applet
+init()
Label
StringBuffer
ActionEvent
Button
Object
+actionPerformed()
StringTokenizer
CodeApplet
-prompt : Label
-inputArea : TextArea
-outputArea : TextArea
-inputString : String
-encode : Button
-decode : Button
-coder : Coder
TextField
TextArea
Uses
+init()
+actionPerformed(in e : ActionEvent)
Coder
StringBuffer
Uses
StringTokenizer
Exercise 7.25
Exercise 7.24
interface
ActionListener
Applet
List
+List(in s : String)
+addItem(in o)
+getItem(in position : int) : String
+deleteItem(in position : int)
+deleteItem(in item : String)
+getPosition(in item : String) : int
+getHead() : String
+getTail() : String
+toString() : String
+length() : int
+main()
+actionPerformed()
+init()
StringBuffer
Uses
PhoneListApplet
Uses
StringTokenizer
-phonelist : PhoneList
+init()
+actionPerformed()
StringBuffer
Uses
StringTokenizer
PhoneList
-phoneList : String
+isAnEntry(in name : String) : <unspecified>
+addEntry(in name : String) : <unspecified>
+getNumber(in name : String) : String
+removeEntry() : String
+getPosition(in name : String) : int
+toString() : String
Uses
Chapter 8
218
(f) An expression that can be used during array instantiation to assign values
to the array is known as an
. Answer: array initializer
(g) A
(h) A sort method that be used to sort different types of data is known as a
method. Answer: polymorphic
(i) To instantiate an array you have to use the
(j) An array of objects stores
219
(f)
(g)
(h)
(i)
(j)
arr[
arr[
arr[
arr[
arr[
5 % 2 ]
arr[ arr[0] ] ]
5 / 2.0 ]
1 + (int) Math.random() ]
arr[3] / 2 ]
Answer: (a) 10, (b) 5, (c) 6, (d) 6, (e) 10, (f) 4, (g) no such number, (h) no such
number, (i) 2, (j) 6
6. Evaluate each of the following expressions, some of which may be erroneous.
int
(a)
(b)
(c)
(d)
(e)
arr[][] = { {2,4,6},{8,10} };
arr.length
(f) arr[0][1]
arr[1].length
(g) arr[arr.length -1 ][0]
arr[3][0]
(h) arr[0][3]
++arr[0][0]
(i) arr[0][1] * arr.length
arr[0] * arr.length
(j) arr[ arr[0][0] ][1]
Answer: (a) 2, (b) 2, (c) no such number, (d) 3, (e) no such number, (f) 4, (g) 8,
(h) no such number, (i) 8, (j) no such number
7. What would be printed by the following code segment?
int arr[] = { 24, 0, 19, 21, 6, -5, 10, 16};
for (int k = 0; k < arr.length; k += 2)
System.out.println( arr[k] );
24
19
6
10
220
0
6
16
1
19
5
3
0
10. Whats wrong with the following code segment, which is supposed to swap the
values of the int variables, n1 and n2?
int temp = n1;
n2 = n1;
n1 = temp;
// it should be n1 = n2;
// it should be temp = n2;
11. Whats wrong with the following method, which is supposed to swap the values
of its two parameters?
public void swapEm(int n1, int n2) {
int temp = n1;
n1 = n2;
// it should be n1 = n2;
n2 = temp;
// it should be temp = n2;
}
12. Declare and initialize an array to store the following two-dimensional table of
values:
1
5
9
2
6
10
3
7
11
4
8
12
13. For the two-dimensional array you created in the previous exercise, write a
nested for loop to print the values in the following order: 1 5 9 2 6 10 3 7 11
4 8 12. That is, print the values going down the columns instead of going across
the rows.
/* **** Print intArr column by column **** */
for (int col = 0; col < intArr[0].length; col++)
for (int row = 0; row < intArr.length; row++)
System.out.print(intArr[row][col] + " ");
System.out.println();
14. Define an array that would be suitable for storing the following values:
221
15. Write a code segment that will compute the sum of all the elements of an array
of int.
int arrInt[] = { 25, 67, 100, -9, 20, 675, 102, 99};
int sum = 0;
for (int k = 0; k < arrInt.length; k++)
sum += arrInt[k];
16. Write a code segment that will compute the sum of the elements a two-dimensional
array of int.
int arrint = new int[num1][num2]
int sum = 0;
for (int k = 0; k < arrint.length; k++)
for (int j = 0; j < arrint[k].length; j++)
sum += arrint[k][j];
17. Write a method that will compute the average of all the elements of a twodimensional array of float.
/**
* average() computes the average of a 2-D array of float
* @param dArr -- a two-dimensional array of floats
222
223
18. Write a method that takes two parameters, an int array and an integer, and
returns the location of the last element of the array which is greater than or equal
to the second parameter.
/**
* findAnElement() finds the location of last element of arr
* that is >= num. It returns -1 if no such number exists
* @param arr -- an integer array
* @param num -- a bound for the search
* @return the last array element >= num
*/
public static int findAnElement (int arr[], int num) {
int largest = -1;
for (int k = 0; k < arr.length; k++) {
if (arr[k] >= num)
largest = k;
}
return largest;
} // findAnElement()
19. Write a program that tests whether a 3 3 array, input by the user, is a magic
square. A Magic square is an N N matrix of numbers in which every number
from 1 to N 2 must appear just once and every row, column and diagonal must
add up to the same total for example,
6 7 2
1 5 9
8 3 4
/* File: MagicSquareTester.java
* Author: Java, Java, Java
* Description: This class determines whether a 3 x 3 array of ints is a magic
* square, where a magic square is an array all of whose rows, columns and diagonals
* add up to the same sum. The algorithm works as follows. Compute the sum of the
224
* first column and store this as magicSum. Then, one by one, compute the sum of
* the remaining columns, the rows, and each diagonal. After each sum is computed
* compare it with magicSum. If it is different, return false. If all the sums
* equal magicSum, return true.
*
* Note that an array is used to store the sums.
*/
import java.io.*;
public class MagicSquareTester
/**
* isMagic() determines if its parameter is a magic square
* @param arr[][] is the array being tested
* @return is the boolean returned that is true iff the array is magic
*/
public boolean isMagic(int arr[][]) {
int sums[] = new int[8];
// A 3 x 3 array has 8 sums
for (int k = 0; k < 3; k++)
sums[0] += arr[k][0];
int magicSum = sums[0];
225
/**
* print() prints an array of integers as a magic square
* @param arr[][] is the array being printed
*/
public void print(int arr[][]) {
for (int j = 0; j < arr.length; j++) {
for (int k = 0; k < arr[j].length; k++)
System.out.print(arr[j][k] + " ");
System.out.println();
}
} // print()
/**
* main() creates an instance of MagicSquareTester and uses it to test arrays
* of different dimensionality
*/
public static void main(String argv[]) {
int magic[][] = { {6,7,2}, {1,5,9}, {8,3,4} };
int notMagic[][] = { {1,7,2}, {6,5,9}, {3,8,4} };
MagicSquareTester tester = new MagicSquareTester();
tester.print(magic);
if ( tester.isMagic(magic))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
tester.print(notMagic);
if ( tester.isMagic(notMagic))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
} // main()
} // MagicSquareTester
20. Revise the program in the previous exercise so that it allows the user to input the
dimensions of the array, up to 4 4.
226
/*
* File: GenericMagicSquareTester.java
* Author: Java, Java, Java
* Description: This class determines whether an N x N array of ints is a magic
* square, where a magic square is an array all of whose rows, columns and diagonals
* add up to the same sum. The key to making this work for the generic case is
* to use simple arithmetic to refer to the various sums. For an N x N array
* the sums array must have 2N +2 elements. For example, a 4 x 4 would have 10
* sums. The following scheme can be used to keep track of what sums go where.
*
*
sums[0] ... sums[N-1] are used for the columns
*
sums[N] ... sums[2N-1] are used for the rows
*
sums[2N]
is used for the left diagonal
*
sums[2N+1]
is used for the right diagonal
*
* Finally, note that the isMagic(int arr[][]) does not refer to the
*
length of the array. So its algorithm can work for any square array
*
as long as you use arr.length as your loop bound.
*/
import java.io.*;
public class GenericMagicSquareTester
/**
* isMagic() determines if its parameter is a magic square
* @param arr[][] is the array being tested
* @return is the boolean returned that is true iff the array is magic
*/
public boolean isMagic(int arr[][]) {
int sums[] = new int[2 * arr.length + 2]; // Sums of rows, cols, diags
for (int k = 0; k < arr.length; k++)
sums[0] += arr[k][0];
int magicSum = sums[0];
for (int j = 1; j < arr.length; j++) { // Sum the rest of the columns
for (int k = 0; k < arr.length; k++)
sums[j] += arr[k][j];
if (magicSum != sums[j])
return false;
} // for each column
for (int j = 0; j < arr.length; j++) { // Sum the rows
for (int k = 0; k < arr.length; k++)
sums[j + arr.length] += arr[j][k];
if (magicSum != sums[j + arr.length])
return false;
} // for each row
227
/**
* print() prints an array of integers as a magic square
* @param arr[][] is the array being printed
*/
public void print(int arr[][]) {
for (int j = 0; j < arr.length; j++) {
for (int k = 0; k < arr[j].length; k++)
System.out.print(arr[j][k] + " ");
System.out.println();
}
} // print()
/**
* main() creates an instance of MagicSquareTester and uses it to test
* arrays of different dimensionality
*/
public static void main(String argv[]) {
int magic[][] = { {6,7,2}, {1,5,9}, {8,3,4} };
int notMagic[][] = { {1,7,2}, {6,5,9}, {3,8,4} };
int magic4[][] = { {16,3,2,13}, {5,10,11,8}, {9,6,7,12}, {4,15,14,1} };
int notMagic4[][] = { {1,7,2,6}, {6,5,9,10}, {3,8,4,65}, {2,2,2,2}};
int magic2[][] = {{1,1},{1,1}};
GenericMagicSquareTester tester = new GenericMagicSquareTester();
tester.print(magic);
if ( tester.isMagic(magic))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
tester.print(notMagic);
if ( tester.isMagic(notMagic))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
tester.print(magic4);
if ( tester.isMagic(magic4))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
tester.print(notMagic4);
if ( tester.isMagic(notMagic4))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
tester.print(magic2);
if ( tester.isMagic(magic2))
System.out.println("This is a magic square");
else
System.out.println("This is NOT a magic square");
} // main()
} // MagicSquare
21. Although most dice are 6-sided, they also come in other sizes. Write a Java
expression that generates random integers for a 12-sided die. The die contains
the numbers 1 to 12 on its faces.
die = 1 + (int)(Math.random() * 12);
22. Revise the DieExperiment() program to test the fairness of the 12-sided
die from the previous exercise.
/*
* File: DieExperiment.java
* Author: Java, Java, Java
* Description: This class tests the "fairness" of a 12 sided die
* with the numbers 1 to 12 on its sides.
*/
public class DieExperiment {
public static final int NTRIALS = 6000;
private final int NFACES = 12;
int counter[] = {0,0,0,0,0,0,0,0,0,0,0,0};
/**
* testDie() "rolls" the die and keeps track of the values
* it returns in an array of integer named counter.
* @param nTrials is the number of times the die is rolled.
*/
228
229
23. Suppose the 12-sided die from the previous exercise has the numbers 3 through
14 on its faces. Write a Java expression that generates random integers for this
die.
die = 3 + (int)(Math.random() * 12);
24. A cryptogram is a message written in secret writing. Suppose you are developing
a program to help solve cryptograms. One of the important bits of evidence is
to compute the frequencies of the letters in the cryptogram. Write a program
that takes a bunch of text as input and displays the relative frequencies of all 26
letters, a to z. (In English, the e is the most frequent letter, with a relative
frequency of around 12 percent.
Design: For this problem we define three classes. (1) FrequencyApplet
provides the graphical user interface. It uses TextAreas for user input and
to display the frequencies. (2) The Frequency class contains the expertise
needed to compute frequencies. Its calcFrequency() method will be called
from the applet. (3) The LetterFreq class creates a data structure which pairs
a letter (a) with its frequency (10). An array of LetterFreqs is then used to
tally the letter frequencies.
Figure 8.1: This applet computes the frequency of letters contained in the input text.
/*
* File: FrequencyApplet.java
* Author: Java, Java, Java
* Description: This applet provides a GUI for
* the Frequency class. It lets the user type text into
* a TextArea and then analyzes the text and prints the
* frequency of each letter.
*/
import java.util.*;
230
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class FrequencyApplet extends Applet implements ActionListener {
private Label prompt;
private TextArea inputArea;
private Button button;
private static TextArea outputArea;
/**
* init() sets up the applets interface
*/
public void init() {
prompt = new Label("Frequency Calculator: Enter a String.");
inputArea = new TextArea(5, 40);
inputArea.setEditable(true);
outputArea = new TextArea(5, 40);
outputArea.setEditable(false);
button = new Button("Calculate Frequencies");
button.addActionListener(this);
add(prompt);
add(inputArea);
add(button);
add(outputArea);
setSize(400,350);
} // init()
/**
* actionPerformed() analyzes the text in
* the input TextArea and displays the frequencies
* of each letter in a TextArea.
*/
public void actionPerformed(ActionEvent e){
outputArea.setText("");
Frequency freq = new Frequency();
String inputString = new String(inputArea.getText());
freq.calcFreq(inputString);
outputArea.append(freq.results());
} // actionPerformed()
} // FrequencyApplet
/*
* File: Frequency.java
* Author: Java, Java, Java
* Description: The frequency class takes a String and analyzes the relative frequencies
* of all 26 letters, a to z.
*/
231
232
import java.util.*;
public class Frequency {
LetterFreq letters [] = new LetterFreq[26];
// Frequency array
/**
* lowercase() takes a character and converts it
* into lowercase.
* @param ch is the character being converted to lowercase.
* @return the character is returned as a lowercase letter
*/
public char lowercase(char ch){
if (ch >= A && ch <= Z)
return (char)(ch + 32);
else
return ch;
} // lowercase()
/**
* initLetter() initializes the frequencies of all the letters in the
* array to zero.
*/
private void initLetters() {
char ch = a;
for (int k = 0; k < 26; k++) {
letters[k] = new LetterFreq(ch,0);
ch = (char)(ch + 1);
}
} // initLetters()
/**
* calcFreq() takes a String and analyzes it for the frequency of each letter.
* The frequencies of the letters are stored in an array of 26 LetterFreq objects each
* representing a letter of the alphabet. Each time an instance of the letter
* is found the corresponding integer in the array is incremented.
* @param s is the String that is passed to the method to be analyzed
*/
public void calcFreq(String s) {
initLetters();
for (int k = 0; k < s.length(); k++) {
char ch = s.charAt(k);
if (ch >= a && ch <= z || ch >= A && ch <= Z) {
int num = lowercase(ch) - (a);
letters[num].freq++;
}
233
}
} // calcFreq()
/**
* results() creates a String that states the frequency of each letter in the String that
* was analyzed.
*/
public String results() {
StringBuffer result = new StringBuffer();
for (int k = 0; k < 26; k++) {
result.append("There were " + letters[k].freq + " " + letters[k].letter + "s\n");
}
return result.toString();
} // results()
} // Frequency
/*
* File: LetterFreq.java
* Author: Java, Java, Java
* Description: This class stores the frequency of a letter as an integer and
* the letter as a character.
*/
public class LetterFreq {
public int freq;
public char letter;
/**
* LetterFreq() is a constructor that sets the values of the freq and letter
* variables.
* @param ch is the character that the LetterFreq object will store
* @param num is the frequency of the letter stored by the object
*/
public LetterFreq (char ch, int num) {
letter = ch;
freq = num;
}
} // LetterFreq
25. Modify the program from the previous exercise to that it can display the relative frequencies of the 10 most frequent and 10 least frequent letters. Use
your program to help you distinguish between messages that were created using a substitution cipher and those that were created using a transposition cipher.
What differences in letter frequencies would you expect between transposition
and substitution?
Design: The only modifications needed for this problem occur in the Frequency class, to which we add a sort() method, which sorts the frequencies
contained in the array of LetterFreq. Of course, we must also modify the
234
Figure 8.2: This version of the frequency applet sorts the frequencies and reports the
10 most frequent and 10 least frequent letters.
/**
* sort() does a bubblesort on an array of LetterFreq objects by their frequencies
* so the most frequent letter is first and the least frequent letter is last.
* @param letterFreq is the array of integers that is passed to the method to be
235
* ordered.
*/
public void sort(LetterFreq arr[]) {
LetterFreq temp;
for (int pass = 1; pass < arr.length; pass++)
for (int pair = 1; pair < arr.length; pair++)
if (arr[pair - 1].freq < arr[pair].freq) {
temp = arr[pair - 1];
arr [pair - 1] = arr [pair];
arr[pair] = temp;
}
} // sort()
/**
* results() creates a String that states the frequency of the ten most frequent
* and the ten least frequent letters in the String that was analyzed.
*/
public String results() {
sort (letters);
// Sort the letters
StringBuffer result = new StringBuffer();
result.append("Ten most frequent letters: \n");
for (int k = 0; k < 10; k++) {
result.append(letters[k].letter + " (" + letters[k].freq + ") ");
}
result.append("\nTen least frequent letters: \n");
for (int k = letters.length - 1; k >= letters.length 11; k--) {
result.append(letters[k].letter + " (" + letters[k].freq + ") ");
}
return result.toString();
} // results()
26. The merge sort algorithm takes two collections of data that have been sorted and
merges them together. Write a program that takes two 25-element int arrays,
sorts them, and then merges them, in order, into one 50-element array.
Design: A single class, the Merge class, can be used for this problem. Its main
component will be the mergeSort() algorithm. Its main() method contains
a simple test of the merge sort algorithm.
/*
* File: Merge.java
* Author: Java, Java, Java
* Description: This class contains the mergeSort method, which takes
* two sorted integer arrays and merges them, in order, into one single
* array.
236
// Index to arr1
// Index to arr2
// Index to newArr
newArr[i++] = arr1[m];
return newArr;
} // mergeSort()
237
/**
* bubbleSort() sorts an array of integers and orders it according to size
* @param arr[] is the array of integers the method is passed to sort according
* to size
*/
public void bubbleSort(int arr[]) {
int temp;
for (int pass = 1; pass < arr.length; pass++)
for (int pair = 1; pair < arr.length; pair++)
if (arr[pair - 1] > arr[pair]) {
temp = arr[pair - 1];
arr [pair - 1] = arr [pair];
arr[pair] = temp;
}
} // bubbleSort()
/**
* print() prints all the integers in the new array of 50 integers
* created by merging the two 25 integer arrays.
*/
public void print(int arr[]) {
for (int k = 0; k < arr.length; k++) {
System.out.print(arr[k] + ", ");
if ((k+1) % 10 == 0)
System.out.println();
}
} // print()
/**
* main() creates a Merge instance and then calls its bubbleSort() method
* two sort two integer arrays, which contain an arbitrary number of elements.
* It then passes the two arrays to the mergeSort() method where they are
* merged into a single sorted array. It then displays the result.
*/
public static void main(String args[]) {
int intArr1[] = {1230,1,24,3,4,5,6,7,89,9,10,101,12,13,14,152,16,17,242};
int intArr2[] = {110,12,2,3,4,533,6,7,8,9,101,411,12,133,14,15,167};
Merge merger = new Merge();
merger.bubbleSort(intArr1); // Sort and display the two arrays
merger.bubbleSort(intArr2);
merger.print(intArr1);
238
System.out.println("\n");
merger.print(intArr2);
System.out.println("\n");
// Create a new array by merging the two arrays
int intArrNew[] = merger.mergeSort(intArr1, intArr2);
merger.print(intArrNew);
System.out.println("\n");
} // main()
} // Merge
27. Challenge: Design and implement a BigInteger class that can add and
subtract positive integers with up to 25 digits. Your class should also include
methods for input and output of the numbers. If youre really ambitious, include
methods for multiplication and division.
Design: The BigInteger class contains data structures and methods needed
to perform arithmetic on arbitrarily large integers. An int array is used to store
the numbers digits. Addition and subtraction algorithms process the arrays from
right to left, performing carries and borrows as necessary. Its important to override the toString() method, which can be used in a wide variety of contexts
to display big integers. The following is sample output from the BigInteger
program:
big1 = 99999999999999999999999999999999999999999999999999
big2 = 00000000000000000000000000000000000000000000000001
---------------------------------------------------------sum = 100000000000000000000000000000000000000000000000000
big3 = 98888888888888888888888888888888888888888888888881
big4 = 09999999999999999999888764399999999999999999999791
---------------------------------------------------------diff = 88888888888888888889000124488888888888888888889090
/*
* File: BigInteger.java
* Author: Java, Java, Java
* Description: This class represents extremely long positive integers, those too
* long to be stored in either an int or a long. The digits of the BigInteger
* are stored in an int array. One limitation of this class is that it only
* works for positive integers.
*/
public class BigInteger {
private int[] bigNum;
239
/**
* BigInteger() is a constructor that takes a String and enters the digits into
* an array of integers
* @param s is the String passed to the method to be entered into the array
*/
public BigInteger(String s) {
bigNumStr = s;
length = s.length();
bigNum = new int[length];
for (int k = 0; k < s.length(); k++) {
bigNum[k] = (int) (s.charAt(k) - 0);
}
} // BigInteger()
/**
* BigInteger(int) constructor sets the size of the BigInteger from its parameter
* @param n gives the size of the BigInteger
*/
public BigInteger(int n) {
bigNum = new int[n];
length = n;
}
/**
* toString() returns a String representation of this BigInteger, creating
* a new String from the bigNum array if necessary.
*/
public String toString() {
if (bigNumStr ==null) {
StringBuffer buff = new StringBuffer();
for (int k = 0; k < bigNum.length; k++)
buff.append(bigNum[k] + "");
bigNumStr = buff.toString();
}
return bigNumStr;
}
/**
* add() computes the sum of this big integer and its parameter
* @param num -- a BigInteger to be added to this
* @return -- a BigInteger giving the sum of this + num
* Algorithm: Create a new BigIntger with room for 1 digit more
240
* than the longer of this and num. Then, proceeding right to left
* add a digit from this and a digit from num plus a carry. Then
* update the carry. Since this and num can be different lengths,
* treat the cases where one or the other or both run out
* of digits as special cases.
*/
public BigInteger add(BigInteger num) {
int digits = Math.max(this.length, num.length);
BigInteger result = new BigInteger(digits + 1);
int carry = 0;
int j = length -1;
// Pointer to rightmost digit of this integer
int k = num.length -1;
// Pointer to rightmost of num
for (int i = digits; i >= 0; i--) {
if (j < 0 && k < 0) {
// If both are out of digits
result.bigNum[i] = carry;
//
just add the carry
} else if (j < 0) {
// If this is out of digits
result.bigNum[i] = (carry + num.bigNum[k]) % 10;
carry = (carry + num.bigNum[k]) / 10;
k--;
} else if ( k < 0) {
// If num is out of digits
result.bigNum[i] = (carry + this.bigNum[j]) % 10;
carry = (carry + this.bigNum[j] / 10);
j--;
} else {
// If both have digits left
result.bigNum[i] = (carry + this.bigNum[j] + num.bigNum[k]) % 10;
carry = (carry + this.bigNum[j] + num.bigNum[k]) / 10;
j--;
k--;
}
}
return result;
} // add()
/**
* subtract() subtracts num from this big integer
* @param num -- a BigInteger to be subtracted from this
* @return -- a BigInteger giving the sum of this + num
* Pre: this integer is >= num
* Algorithm: Create a new BigInteger with the same number of digits
* as this BigInteger. Then proceeding from right to left, compute
* the difference between this and num. If the difference is negative,
* borrow from the from the next digit of this BigInteger.
*/
public BigInteger subtract(BigInteger num) {
BigInteger result = new BigInteger(length);
int diff = 0;
241
28. Challenge: Design a data structure for this problem: As manager of Computer
Warehouse, you want to keep track of the dollar amount of purchases made by
those clients that have regular accounts. The accounts are numbered from 0,
1, ..., N. The problem is that you dont know in advance how many purchases each account will have. Some may have one or two purchases. Others
may have 50 purchases.
Design: The Account class uses an array of double to store purchase amounts.
Each account also has a unique account number, which is generated by a static
integer defined in the class.
/*
* File: Account.java
* Author: Java, Java, Java
* Description: This class defines a data structure for
* an account that keeps track of purchases made by
* individual customers. The accounts are numbers 0, 1, ...
* An array is used to store purchase amounts.
*/
import java.util.*;
public class Account {
private static final int MAXPURCHASES = 100;
ber of purchases per account
private static int nAccounts;
Figure 8.3: This applet provides an interface that lets the user test the Account class.
242
243
29. An anagram is a word made by rearranging the letters of another word. For
example, act is an anagram of cat, and aegllry is an anagram of allergy.
Write a Java program that accepts two words as input and determines if they are
anagrams.
Design: The Anagram class implements the areAnagrams() method to determine if two strings are anagrams of each other. Two strings are anagrams of
each other if, after sorting each of them, they are equal.
Figure 8.4: This applet provides an interface that lets the user test the Anagram class.
/*
244
245
* File: Anagram.java
* Author: Java, Java, Java
* Description: This class analyzes Strings and determines if they are anagrams
* of each other. To determine if two strings are anagrams, sort both strings
* and see if they are equal. A version of bubblesort is used for the sort.
*/
public class Anagram {
/**
* areAnagrams() is a method that analyzes two Strings and determines if they
*
are anagrams of each other. It sorts the letters of the strings and
*
test if the results are equal.
* @param str1 is one of the Strings to analyze
* @param str2 is the second String to analyze
* @return is the boolean true if the Strings are anagrams and false otherwise
*/
public boolean areAnagrams (String str1, String str2) {
String s1 = stringSort(str1);
String s2= stringSort(str2);
System.out.println(s1 + " " + s2);
return s1.equals(s2);
} // areAnagrams()
/**
* stringSort() sorts a string of characters into alphabetical order.
* It uses the bubblesort algorithm
* @param s -- the string to be sorted
* @return a string whose letters are in alphabetical order
*/
public String stringSort(String s) {
StringBuffer buff = new StringBuffer(s);
for (int pass = 1; pass < buff.length(); pass++)
for (int pair = 1; pair < buff.length(); pair++)
if (buff.charAt(pair-1) > buff.charAt(pair)) {
char temp = buff.charAt(pair-1);
buff.setCharAt(pair-1, buff.charAt(pair));
buff.setCharAt(pair, temp);
}
return buff.toString();
} // stringSort()
public static void main(String argv[]) {
Anagram tester = new Anagram();
if (tester.areAnagrams("act", "cat"))
System.out.println("act and cat are anagrams");
if (tester.areAnagrams("act", "cate"))
System.out.println("act and cate are anagrams");
} // main()
} // Anagram
/**
* Dictionary() breaks the String into tokens and inserts each token into the
* dictionary
* @param s is the String the dictionary is made from
*/
public Dictionary (String s) {
StringTokenizer words = new StringTokenizer(s);
while (words.hasMoreTokens()) {
String word = words.nextToken();
insert(word);
}
246
Figure 8.5: This applet constructs an anagram dictionary from user input.
247
} // Dictionary
/**
* insert() adds the String to an entry if it matches an Entry already
* in the dictionary and creates a new Entry if there are no matches
* @param s is the String being inserted
*/
public void insert(String s) {
int k = 0;
boolean entryfound = false;
while (!entryfound && k < entries.size()) {
Entry o = (Entry)entries.elementAt(k);
if (o.matches(s)) {
o.insert(s);
entryfound = true;
}
else
k++;
}
if (!entryfound) {
Entry e = new Entry(s);
entries.addElement(e);
}
} // insert()
/**
* toString() returns the Dictionary as a String
*/
public String toString() {
StringBuffer result = new StringBuffer("");
for (int k = 0; k < entries.size(); k++)
result.append(entries.elementAt(k).toString() + "\n");
return result.toString();
} // toString()
} // Dictionary
/*
* File: Entry.java
* Author: Java, Java, Java
* Description: This class stores an entry in the Dictionary as a Vector
*/
import java.util.*;
public class Entry {
Anagram anagram;
private Vector words = new Vector();
248
249
/**
* Entry() creates a new Entry
* @param s is the String that the new entry is created from
*/
public Entry (String s) {
anagram = new Anagram(s);
words.addElement(s);
} // Entry()
/**
* toString() returns the Entry as a String
*/
public String toString() {
StringBuffer result = new StringBuffer(anagram.toString() + ": ");
for (int k = 0; k < words.size(); k++) {
Object o = words.elementAt(k);
result.append(o.toString() + ", ");
}
return result.toString();
} // toString()
/**
* matches() checks whether a one String is an anagram of the Entry
* @param s is the String being tested
*/
public boolean matches(String s) {
return anagram.matches(s);
} // matches()
/**
* insert() adds a new String to the Vector which the entrys words are stored in
* @param s is the String being added to the Vector
*/
public void insert(String s) {
words.addElement(s);
} // insert()
} // Entry
/*
* File: Anagram.java
* Author: Java, Java, Java
* Description: This class analyzes Strings and determines if they are anagrams
* of each other. To determine if two strings are anagrams, sort both strings
* and see if they are equal. A version of bubblesort is used for the sort.
*/
public class Anagram {
private String anagram;
/**
250
251
252
* actionPerformed() gets the text from the input TextArea and makes it into an
* anagram dictionary which it displays
*/
public void actionPerformed(ActionEvent e){
outputArea.setText("");
String inputString = new String(inputArea.getText());
Dictionary dict = new Dictionary(inputString);
outputArea.append(dict.toString());
} // actionPerformed()
} // AnagramApplet
31. The Acme Trucking company has hired you to write software to help dispatch its
trucks. One important element of this software is knowing the distance between
any two cities that it services. Design and implement a Distance class that
stores the distances between cities in a two-dimensional array. This class will
need some way to map a city name, Boise, into an integer that can be used
as an array subscript. The class should also contain methods that would make
it useful for looking up the distance between two cities. Another useful method
would tell the user the closest city to a given city.
Design: The Distance class uses a two-dimensional array to store distances
between pairs of cities. A one dimensional array is used to store the names of
the cities. Given any two city names, the lookup algorithm converts the names
to integers, and then uses the integers as indices into the distance table. The
distance between the two cities will be distance stored at distances[j][k],
where j and k are the cities indices.
/* File: Distance.java
* Author: Java, Java, Java
* Description: This class analyzes the distances between different cities.
* The main data structure for this program is a two-dimensional table
* storing the distances between pairs of cities. The cities, represented
* by numbers between 0 and MAXCITIES-1, will serve as indices to the table.
* The tables diagonal will contain all 0s, since that represents the
* all the distances between a city and itself. The names of cities are
* stored in a one-dimensional array.
*/
public class Distance {
private static final int MAXCITIES = 5;
private double[][] distances = {{0,
3000,2000,2900,2950}, // Distances
{3000,0
,1000,105 ,150 }, // Table
{2000,1000,0
,900 ,1000},
{2900,105 ,900 ,0
,100 },
{2950,150 ,1000,100 ,0
}};
253
/**
* getDistance() analyzes two cities entered into the array and determines the distance
* between them
* @param s1 and s2 are the Strings passed to the method that are the names of the cities
* @return is the distance between the cities returned as an double
*/
public double getDistance(String s1, String s2) {
return distances[getCityIndex(s1)][getCityIndex(s2)];
} // getDistance()
/**
* getNearestCity() analyzes determines the city that is the nearest to the city passed to
* the method
* @param s is the name of the city passed to the method
* @return is the name of the city that is closest to the city passed to the method
* Algorithm: Initialize a variable called closestDistance and another one
* called closestCity. Then go through each pairing of this city with some other
* city in the table -- all of these will occur in the same row. If a pairing has
* a distance that is less than closestDistance, make it the new closest city.
*/
public String getNearestCity (String s) {
double closestDistance = 10000;
// Initial to a big value
int cityIndx = getCityIndex(s);
// Get this citys index
int closestCity = cityIndx;
for (int k = 0; k < MAXCITIES; k++) { // For each city in the table
if (k != cityIndx) {
// If k is not this city
double distance = distances[cityIndx][k]; // Get the distance
if (distance < closestDistance) {
// If this distance is shorter
closestDistance = distance;
closestCity = k;
member its city index
} // if shorter
} // if
} // for
return cityNames[closestCity];
} // getNearestCity()
254
//
//
32. Write a SlideShowApplet that displays an endless slide show. Use GIF files
to store the images that make up the show. Load the images into an array and
then repeatedly display an image from the array, each time the user clicks on a
control button. One modification to this program might be to show the slides in
random order. That would make it less boring!
/*
* File: SlideShowApplet.java
* Author: Java, Java, Java
* Description: This applet illustrates how to download
* images from the Internet using the Applet.getImage()
* method. A set of slides is downloaded and stored in
* an array of Image. The applet then displays a new slide
* each time the user clicks on the control button.
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
255
import java.net.*;
public class SlideShowApplet extends Applet implements ActionListener {
public static final int WIDTH=300, HEIGHT=300;
private static final int NIMGS = 4;
private Image[] slide = new Image[NIMGS];
private Image currentImage = null;
private Button nextImgButton = new Button("Next Image");
private int nextImg = 0;
/**
* init() sets up the applets interface and loads
*
the images from GIF files.
*/
public void init() {
add(nextImgButton);
nextImgButton.addActionListener(this);
for (int k=0; k < NIMGS; k++)
slide[k] = getImage(getCodeBase(), "demo" + k + ".gif");
currentImage = slide[nextImg];
setSize(WIDTH, HEIGHT);
} // init()
/**
* paint() is invoked automatically to draw
*
the applet whenever necessary. It displays
*
the current image.
*/
public void paint(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, WIDTH, HEIGHT);
if (currentImage != null)
g.drawImage(currentImage, 10, 50, this);
} //paint()
/**
* actionPerformed() displays the next slide each time
*
the button is clicked
*/
public void actionPerformed(ActionEvent e) {
currentImage = slide[nextImg];
nextImg = (nextImg + 1) % NIMGS;
repaint();
} // actionPerformed()
} // SlideShowApplet
33. Revise CyberPet (Text Figure 5-15) so that approximately half the time when
commanded to eat or sleep it goes into a NOTHUNGRY or NOTSLEEPY state
instead.
256
257
// Instance variables
/**
* CyberPet() initializes the pets state to EATING
*/
public CyberPet() {
// Constructor #1
name = "no name";
petState = EATING;
}
/**
* CyberPet(str) initializes the pets name
* @param str -- a string giving pets name
*/
public CyberPet(String str) { // Constructor #2
name = str;
petState = EATING;
}
/**
* CyberPet(str, inState) initializes the pets name and state
* @param str -- a string giving pets name
* @param inState -- an int giving the pets state
*/
public CyberPet(String str, int inState) { // Constructor #3
name = str;
petState = inState;
}
/**
* CyberPet(str, sleeping) preserves backward compatibility
* with previous versions of CyberPet by taking a boolean parameter
* representing the pets state.
* @param str -- a string giving the pets name
* @param sleeping -- a boolean set to SLEEPING (true) or EATING (false)
*/
public CyberPet(String str, boolean sleeping) { // Constructor #4
name = str;
if (sleeping == true)
petState = SLEEPING;
else
petState = EATING;
}
/**
* setName() sets the CyberPets name.
* @param str -- a string giving the pets name
*/
public void setName(String str) {
name = str;
} // setName()
/**
* getName() returns the CyberPets name.
* @return -- a string giving the CyberPets name
*/
public String getName() {
return name;
} // getName()
/**
* eat() sets the pets state to EATING
* Algorithm: Note that approximately half the time the
*
CyberPet goes into the NOTHUNGRY state, thereby not
*
obeying the users command.
258
*/
public void eat() {
if (Math.random() * 2 < 1)
petState = NOTHUNGRY;
else
petState = EATING;
} // eat()
/**
* sleep() sets the pets state to SLEEPING
* Algorithm: Note that approximately half the time the
*
CyberPet goes into the NOTSLEEPY state
*
obeying the users command.
*/
public void sleep() {
if (Math.random() * 2 < 1)
petState = NOTSLEEPY;
else
petState = SLEEPING;
} // sleep()
/**
* think() sets the pets state to THINKING
*/
public void think() {
petState = THINKING;
} // think()
/**
* toString() returns a string representation of CyberPet
*/
public String toString() {
return "I am a CyberPet named " + name;
}
/**
* getState() returns the pets state
* @return a String representing the pets state
*/
public String getState() {
if (petState == EATING)
return "Eating";
// Exit the method
if (petState == SLEEPING)
return "Sleeping";
// Exit the method
if (petState == THINKING)
return "Thinking";
if (petState == NOTHUNGRY)
return "Not Hungry";
if (petState == NOTSLEEPY)
return "Not Sleepy";
259
260
261
Exercise 8-19
Exercise 8-22
MagicSquareTester
DieExperiment
+NTRIALS : int = 6000
-NFACES : int = 12
-counter : int[]
Applet
+actionPerformed()
Exercise 8-26
+init()
Merge
Uses
FrequencyApplet
+init()
+actionPerformed()
Frequency
-letter : LetterFreq[]
Uses
LetterFreq
+freq : int
+letter : char
+LetterFreq(in ch : char, in num : int)
Exercise 8-28
Exercise 8-27
BigInteger
-bigNum : int[]
-length : int
-bigNumStr : String
+BigInteger(in s : String)
+BigInteger(in n : int)
+toString() : String
+add(in num : BigInteger) : BigInteger
+subtract(in num : BigInteger) : BigInteger
+main()
Miscellaneous Types
Account
-MAXPURCHASES : int
-nAccounts : int
-accountNum : int
-numPurchases : int
-purchases : double[]
+Account()
+addPurchase(in newPurchase : double)
+toString() : String
+acctToString() : String
datatype
double[][]
datatype
int[]
datatype
String[]
datatype
int[][]
datatype
boolean
datatype datatype
double[] LetterFreq[]
262
Exercise 8-29
Anagram
Exercise 8-32
-anagram : String
+areAnagrams(in str1 : String, in str2 : String) : boolean
+stringSort(in s : String) : String
+matches(in s : String) : boolean
+main()
interface
ActionListener
Applet
+actionPerformed()
+init()
Exercise 8-30
SlideShowApplet
Dictionary
interface
ActionListener
-entries : Vector
+actionPerformed()
+Dictionary(in s : String)
+insert(in s : String)
+toString() : String
Applet
Uses
Uses
+init()
Uses
Image
+init()
+paint(in g : Graphics)
+actionPerformed()
Vector
Uses
AnagramApplet
+init()
+actionPerformed()
Uses
Uses
Entry
-anagram : Anagram
-words : Vector
+Entry(in s : String)
+toString() : String
+matches(in s : String) : boolean
+insert() : String
Anagram
-anagram : String
+areAnagrams(in str1 : String, in str2 : String) : boolean
+stringSort(in s : String) : String
+matches(in s : String) : boolean
+main()
Exercise 8.31
Distance
-MAXCITIES : int = 5
-distances : double[][]
-cityNames : String[]
+getCityIndex(in s : String) : int
+getDistance(in city1 : String, in city2 : String) : double
+getNearestCity(in city : String) : String
+main()
Exercise 8-33
CyberPet
+EATING : int = 0
+SLEEPING : int = 1
+THINKING : int = 2
+NOTSLEEPY : int = 3
+NOTHUNGRY : int = 4
-petState : int
-name : String
+CyberPet()
+CyberPet(in name : String)
+CyberPet(in name : String, in state : int)
+CyberPet(in name : String, in sleeping : boolean)
+setName(in s : String)
+getName() : String
+eat()
+sleep()
+think()
+toString() : String
+getState() : String
Miscellaneous Types
datatype
Image[]
Graphics
Button
datatype
boolean
Chapter 9
264
model to
. Answer: contain-
3. Describe in general terms what you would have to do to change the standard look
and feel of a Swing JButton.
Answer: An objects look and feel is defined by its view and its controller. To
simplify changing the look and feel, for most classes the view and controller are
combined into a single class. For example, for a JButton you would redefine
the methods in the BasicButtonUI to implement your own look and feel.
4. Explain the differences between the model-view-controller design of a JButton and the design of an AWT Button. Why is MVC superior?
Answer: In the model-view-controller design, each of these aspects are treated
separately. In a AWT Button the components state, view, and control methods
are combined into one class. Swing components are more flexible. By redefining
the controller and view you can change their look and feel. Not so for AWT
components.
5. Suppose you have an applet that contains a JButton and a JLabel. Each time
the button is clicked the applet rearranges the letters in the label. Using Javas
event model as a basis, explain the sequence of events that happens in order for
this action to take place.
Answer: When the user clicks on the button, that generates an ActionEvent
which is passed by Java virtual machine (JVM) to the buttons ActionListener. The ActionListener must implement a actionPerformed()
method, which should contain code (or a method call) to rearrange the JLabels
letters.
6. Draw a containment hierarchy for the most recent version of the CyberPetApplet program.
Applet
|
|-------------------------------|
|
|
|
Label TextField EatButton SleepButton
7. Create a GUI design, similar to the one shown in Text Figure 9-25, for a program
that would be used to buy tickets on-line for a rock concert.
8. Create a GUI design, similar to the one shown in Text Figure 9-25, for an on-line
program that would be used to play musical recordings.
9. Design and implement a GUI for the CDInterest program (Text Figure 5-18).
This program should let the user input the interest rate, principal, and period, and
should accumulate the value of the investment.
/*
265
Figure 9.3: Exercise 9: A graphical user interface for the CD Interest program.
266
267
* File: CDInterest.java
* Author: Java, Java, Java
* Description: This application program illustrates the use of Java library
* classes to perform certain useful calculations.
*
pal
*
est
*
mat
*
*/
import javax.swing.*;
import java.awt.event.*;
import java.text.NumberFormat;
/**
* CDInterest() constructor creates the layout for the user interface.
*
It uses three panels to organize the GUI components and uses the
*
default layout managers.
*/
public CDInterest () {
dailyButton.addActionListener(this); // Control buttons
yearlyButton.addActionListener(this);
controls.add(dailyButton);
controls.add(yearlyButton);
inputs.add(rateLabel);
// Input fields
inputs.add(rateFld);
inputs.add(prinLabel);
inputs.add(prinFld);
inputs.add(yrsLabel);
inputs.add(yrsFld);
268
getContentPane().add(inputs, "North");
// Border layout
getContentPane().add(display, "Center");
getContentPane().add(controls, "South");
} // CDInterest
/**
* convertStringTodouble() converts a String of the form "54.87" into
* its corresponding double value (54.87).
* @param s -- stores the string to be converted
* @return A double is returned
*/
private double convertStringTodouble(String s) {
Double doubleObject = Double.valueOf(s) ;
return doubleObject.doubleValue();
}
/**
* actionPerformed() handles actions on the two buttons and computes
*
the programs results. Note the use of the NumberFormat.format() methods
*
for making the output look pretty.
*/
public void actionPerformed(ActionEvent e) {
double principal;
// The CDs initial principal
double rate;
// CDs interest rate
double years;
// Number of years to maturity
double result;
// Accumulated principal
NumberFormat dollars = NumberFormat.getCurrencyInstance(); // Set up formats
NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMaximumFractionDigits(2);
principal = convertStringTodouble(prinFld.getText());
rate = convertStringTodouble(rateFld.getText());
years = convertStringTodouble(yrsFld.getText());
// Get data
if (e.getSource() == dailyButton) {
// Calculate results
result = CDExpert.computeCDDaily(principal, rate, years);
display.append("The resulting principal compounded daily at " +
percent.format(rate) + " is " + dollars.format(result) + "\n");
} else {
result = CDExpert.computeCDYearly(principal, rate, years);
display.append("The resulting principal compounded yearly at " +
percent.format(rate) + " is " + dollars.format(result) + "\n");
}
} // actionPerformed()
/**
*
269
*
the WindowAdapter to handle window close events.
*/
public static void main( String args[] ) {
CDInterest cd = new CDInterest();
cd.setSize(450,300);
cd.setVisible(true);
cd.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // Interest
/*
* File: CDExpert.java
* Author: Java, Java, Java
* Description: The CDExpert class contains two static methods for calculating
* the maturity value of a CD given its principal, interest rate and years.
*/
public class CDExpert {
/**
* computeCDDaily() computes CD value given daily compounding.
* @param p -- a double giving the initial principal
* @param r -- a double giving the interest rate
* @param yrs -- a double giving the number of years before maturity
*/
public static double computeCDDaily (double p, double r, double yrs) {
return p * Math.pow(1 + r/365, yrs*365);
}
/**
* computeCDYearly() computes CD value given daily compounding.
* @param p -- a double giving the initial principal
* @param r -- a double giving the interest rate
* @param yrs -- a double giving the number of years before maturity
*/
public static double computeCDYearly (double p, double r, double yrs) {
return p * Math.pow(1 + r, yrs);
}
} // CDExpert
10. Design and implement a GUI for the Temperature class (Text Figure 5-5).
270
One challenge of this design is to find a good way for the user to indicate whether
a Fahrenheit or Celsius value is being input. This should also determine the order
of the conversion: F to C, or C to F.
/*
* File: TemperatureGUI.java
* Author: Java, Java, Java
* Description: This class provides a GUI to test the Temperature class.
* The GUI consists of a text field, into which the user can type a
* temperature value, a radio button, which can be toggled from celsius
* to fahrenheit to indicate the units of the input value, and a text
* area, into which the results are displayed.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TemperatureGUI extends JFrame implements ActionListener {
private JPanel inputPanel = new JPanel();
// Input panel
private JTextField inField = new JTextField(15);
// GUI components
private JTextArea display = new JTextArea();
private JLabel prompt = new JLabel("Temperature: ");
private JRadioButton celsUnit = new JRadioButton("in Celsius");
private JRadioButton fahrUnit = new JRadioButton("in Fahrenheit");
private JButton convert = new JButton("Convert");
private ButtonGroup unitsGroup = new ButtonGroup();
private Temperature temperature = new Temperature();
// The tem-
271
perature object
/**
* TemperatureGUI() sets the layout and adds components to the toplevel JFrame.
*/
public TemperatureGUI(String title) {
super(title);
setSize(250,200);
getContentPane().setLayout(new BorderLayout());
inputPanel.add(prompt);
// Input elements
inputPanel.add(inField);
inField.addActionListener(this); // Register text field with listener
inputPanel.add(celsUnit);
// Radio buttons
inputPanel.add(fahrUnit);
unitsGroup.add(celsUnit);
// Button group
unitsGroup.add(fahrUnit);
fahrUnit.setSelected(true);
inputPanel.add(convert);
convert.addActionListener(this);
getContentPane().add(inputPanel, "North");
getContentPane().add(display, "Center");
display.setText("Input a temperature and press <RET>\n");
} // TemperatureGUI()
/**
* actionPerformed() handles input into the text field. The
*
TextField input must be converted from String to double.
* @param e -- the ActionEvent that caused this method to be called
*/
public void actionPerformed(ActionEvent e) {
String inputStr = inField.getText();
// Get users input
double userInput = convertStringTodouble (inputStr); // Convert it to double
double result = 0;
if (celsUnit.isSelected()) {
// Process and report
result = temperature.celsToFahr(userInput);
display.append(inputStr + " C = " + result + " F \n");
} else {
result = temperature.fahrToCels(userInput);
display.append(inputStr + " F = " + result + " C \n");
}
} // actionPerformed()
/**
* convertStringTodouble() converts a String of the form "54.87" into
* its corresponding double value (54.87).
272
11. Convert the CyberPetApplet to a Swing-based version. The top-level window should be a JApplet.
/* * File: AnimatedCyberPet.java * Author: Java, Java, Java * Description: This
applet provides a Graphical User * Interface for the CyberPet class. It animates
the * CyberPets eating actions by looping through a * set sequence of images.
The images simulate the pet * chewing its food. */
import java.applet.*; import java.awt.*; import java.awt.event.*;
public class AnimatedCyberPet extends Applet implements ActionListener private final int PAUSE = 20000; // Named constant // Instance variables. private
CyberPet pet1 = new CyberPet(Socrates); // CyberPet private Label nameLabel = new Label(Hi! My name is // Label + pet1.getName() + and currently I am : ); private TextField stateField = new TextField(12); // A TextField
private Button eatButton = new Button(Eat!); // Two Buttons private Button
sleepButton = new Button(Sleep!); private Image eatImg, eat2Img, sleepImg,
happyImg; // Images for animation
/** * init() sets up the applets interface and loads the * images used in the
animation */ public void init() eatButton.addActionListener(this); // Assign the
listeners to the buttons. sleepButton.addActionListener(this); stateField.setText(
pet1.getState() ); // Initialize the TextField stateField.setEditable(false); add(nameLabel);
// Add the components to the applet. add(stateField); add(eatButton); add(sleepButton);
eatImg = getImage(getCodeBase(), eatImage.gif); // Load the images eat2Img
= getImage(getCodeBase(), eat2Image.gif); sleepImg = getImage(getCodeBase(),
sleepImage.gif); happyImg = getImage(getCodeBase(), happyImage.gif); setSize(300,300); // Set the applets size // init()
/** * paint() paints an appropriate image based on CyberPets state * @param
g the applets Graphics context */ public void paint(Graphics g) String petState = pet1.getState(); if (petState.equals(Eating)) doEatAnimation(g); else if
(petState.equals(Sleeping)) g.drawImage(sleepImg, 20, 100, this); // paint()
/** * doEatAnimation() loops through the five images that make up * the eating animation, pausing for a brief instant between each image * @param g
the applets Graphics context */ private void doEatAnimation(Graphics g) for
(int k = 0; k 5; k++) g.drawImage( eatImg ,20, 100, this); busyWait(PAUSE);
g.drawImage(eat2Img, 20, 100, this); busyWait(PAUSE); g.drawImage(happyImg,
20, 100, this); // doEatAnimation()
273
274
275
/*
* File: PasswordField.java
* Author: Java, Java, Java
* Description: This extension of TextField masks its input
* thereby making it suitable for use as a password field.
* Its actionPerformed() methods guards against passwords
* that contain fewer than 6 characters.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PasswordField extends TextField implements ActionListener {
/**
* PasswordField() constructor sets the echo character to mask input.
*/
public PasswordField() {
super();
setEchoChar(#);
addActionListener(this);
} // PassWordField()
/**
* PasswordField() constructor sets the echo character to mask input.
*/
public PasswordField(int width) {
super(width);
setEchoCharacter(#);
addActionListener(this);
} // PassWordField()
276
/**
* actionPerformed() guards against invalid passwords.
*/
public void actionPerformed(ActionEvent e) {
String s = getText();
if (s.length() < 6)
JOptionPane.showMessageDialog(this, "Password must be at least 6 characters");
} // actionPerformed()
} // PasswordField
/*
* File: Password.java
* Author: Java, Java, Java
* Description: This class provides an applet interface to test the PasswordField.
* It checks the users password against "javajavajava". In a real program
* the users password would be store, usually in encrypted form, in a system file.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Password extends JApplet implements ActionListener {
private
private
private
private
private
/**
* init() sets up a simple interface
*/
public void init() {
setSize(250, 200);
display.setEditable(false);
inPassword.addActionListener(this);
inputPanel.add(prompt);
inputPanel.add (inPassword);
getContentPane().add(inputPanel, "North");
getContentPane().add(display, "Center");
} // init()
/**
* actionPerformed() tests whether the user has entered the
* correct password.
*/
public void actionPerformed( ActionEvent e ) {
277
String s = inPassword.getText();
if (s.equals( password)) // Check Password
display.setText("Thank you!");
else
display.setText("Invalid Password. Try Again!");
} //actionPerformed()
} // Password
13. Design an interface for a 16-button integer calculator that supports addition, subtraction, multiplication, and division. Implement the interface so that the label
of the button is displayed in the calculators display that is, it doesnt actually
do the math.
/*
* File: CalculatorUI.java
* Author: Java, Java, Java
* Description: This class creates an user interface for a fourfunction
*
integer calculator. The keys are arranged in a 4 x 4 grid, which is
*
at the center of the Frames border layout. At the north of the border
*
layout is the calculators accumulator/display, implemented with a
*
text field. This version merely displays what key was clicked in the
*
accumulator. It does not perform arithmetic.
*/
import javax.swing.*;
278
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class CalculatorUI extends JFrame implements ActionListener{
private final static int NBUTTONS = 16; // Constants
private JPanel keyPadPanel; // Panel to hold keyPad
private JTextField accumulator; // The calculators display
private JButton keyPad[]; // Internal keyPad array
private String label[] =
/**
* CalculatorUI() constructor sets up the user interface.
*/
public CalculatorUI(String title) {
// Set up the keypad grid layout
super(title);
keyPadPanel = new JPanel();
keyPadPanel.setLayout(new GridLayout (4,4,1,1));
// Create an array of buttons
keyPad = new JButton [NBUTTONS];
// Create the array
for (int k = 0; k < keyPad.length; k++){
// For each array slot
keyPad[k] = new JButton( label[k] );
// Create a button
keyPad[k].addActionListener(this);
// And a listener for it
keyPadPanel.add(keyPad[k]);
// And add it to the panel
} // for
// Set up the accumulator display
accumulator = new JTextField("0",20);
accumulator.setEditable (false);
// Add components to the frame
getContentPane().setLayout (new BorderLayout(10, 10)); // Border layout
getContentPane().add("North", accumulator);
getContentPane().add("Center", keyPadPanel);
} // CalculatorUI()
/**
* actionPerformed() handles all the action on the calculators keys.
* In this version the keys label is just displayed in the accumulator.
*/
279
14. Challenge: Design and implement a Calculator class to go along with the
interface you developed in the previous exercise. It should function the same
way as a hand calculator except it only handles integers.
Design:
For this problem, the interface (CalculatorUI) needs only minor changes.
It must create an instance of the Calculator class and then pass each
keystroke to this instance in the actionPerformed() method:
/**
* actionPerformed() handles all the action on the calculators keys.
* In this version the key plus the current value of the calculators
* display are passed to the Calculator object, which performs an
* operation and returns a result.
*/
public void actionPerformed (ActionEvent e) {
JButton b = (JButton) e.getSource();
// Get the button that was clicked
String key = b.getText();
// And its label
String result = calcMachine.handleKeyPress(key, accumulator.getText());
accumulator.setText(result);
} // actionPerformed()
280
The hardest part of this problem is designing an algorithm. Because the calculator uses infix notation, where the operation occurs between the two operands,
as in operand1 operation opcode2, you must store the opcode of the operation
while the second operand is being input. The problem can be simplified somewhat if you restrict the operations to those of the form: 23 + 65 = 88 that is,
those in which the equal key is pressed after every arithmetic operator. Its a little
trickier if you want to allow operations of the form: 23 + 65 - 31 * 2 / 4 ... In
this case, whenever an operator key is pressed, you must perform the previous
operation. So when the - key is pressed, you perform the + operation, and so on.
Another challenge is managing the input of digits. When should a typed digit be
appended to the current number in the calculators display, and when should it
start a new number. A control variable can be used to keep track of this. See the
comments in the code for further details.
/*
* File: Calculator.java
* Author: Java, Java, Java
* Description: Implements a multifunction integer calculator. Heres how it works.
* All calculations are performed using two internal registers, the accumulator,
*
which keeps a running total of ongoing calculations, and the displayRegister,
*
which is set to the value displayed in the external display just before an
*
operation is performed. Inputs to the calculator occur by pressing either digit
*
keys, which signal that an integer operand is being input, and operation keys
*
(+ - * / C =), which indicate that an operation should be performed.
*
* Control of the machine is managed by the handleKeyPress() method. Two internal
*
state variables are used to control the machine. (1) The displayState variable keeps
*
track of when a new number is being started (REPLACE) and when incoming digits should be
*
APPENDed to the present value of the display. In APPEND mode, it appends each
*
digit typed to the external display. In REPLACE mode, it replaces the external
*
display with the digit typed. (2) The opCode variable stores the current operation.
*
What makes control of the calculator somewhat tricky is that it uses INFIX
*
notation, so operations take the form Operand1 opCode Operand2. The OpCode
*
has to be remembered while Operand2 is being input. The following example shows
*
the state of these control variables after each key press. The vertical lines (|)
*
show when each operation is done. For the expression 56 + 23 5 the calculator does
281
*
the addition (+) after the - key is pressed. It does the subtraction (-) after the
*
= key is pressed. The equal key resets everything but the accumulator, which always stores
*
the present total. The accumulator is only reset after a Clear or an error.
*
*
KEYPRESS:
5 6 + | 2 3
- | 5 = |
*
DISPLAY:
0 5 56 56 56 2 23 23 79 5
74
*
DISPLAYREG:
0
56 0
23 0
5 0
*
ACCUM:
0
0 56 56
56 79
79 74
*
OPCODE
-1
1 1
2
-1
*
DISPLAYSTATE: R A
R
A
R A
R
*/
import java.lang.*;
public class Calculator
public final static
public final static
public final static
public final static
public final static
public final static
public final static
{
int
int
int
int
int
int
int
NOOP = -1;
// Operations
EQUAL = 0;
ADD = 1;
SUBTRACT = 2;
MULTIPLY = 3;
DIVIDE = 4;
CLEAR = 5;
// Display states
282
accumulator = 0;
// Reset the machines registers
displayRegister = 0;
displayState = REPLACE; // Replace the display with the next digit typed
opCode = NOOP;
// No current operation
error = false;
} // initialize()
/**
* keyToIntCode() converts key characters, such as +, to an integer code.
* @return an int representing the key that was pressed
*/
private int keyToIntCode(char keyCh) {
switch (keyCh) {
case C: return CLEAR;
case =: return EQUAL;
case +: return ADD;
case -: return SUBTRACT;
case *: return MULTIPLY;
case /: return DIVIDE;
}
return -1;
// Error Return
} // keyToIntCode()
/**
* doCurrentOp() is invoked whenever C, =, +, -, *, or / is pressed. Except
* for the Clear key, it performs an operation, storing the result in the
* accumulator, which is returned as the methods value.
* The Clear key is treated as a special case and the machine is reinitialized.
* For all other keys the opCode field stores the operation that is waiting for
* its second operand to be input. That operation is performed, using the
* accumulator and displayRegister.
* After each operation, the displayState is set to REPLACE, so the next digit
* typed will start a new integer operand. Note that EQUAL key, resets the opCode
* to NOOP, thus beginning another complete INFIX operation. All other keys
* (+ - / *) set the opCode to their keyCodes, thus getting the machine ready to
* complete that operation the next time an operator key is pressed.
* @param keyCode -- an int representing one of EQUAL, ADD, SUBTRACT, DIVIDE, MULT, CLEAR
* @return an int representing the result of the calculation
*/
private int doCurrentOp(int keyCode) { // do the current opCode
if (keyCode == CLEAR) {
283
initialize();
return accumulator;
}
switch (opCode) {
case NOOP:
accumulator = displayRegister;
case ADD :
accumulator = accumulator + displayRegister; break;
case SUBTRACT : accumulator = accumulator - displayRegister; break;
case MULTIPLY : accumulator = accumulator * displayRegister; break;
case DIVIDE :
if (displayRegister == 0)
error = true;
else
accumulator = accumulator/displayRegister;
break;
} // switch
if (keyCode == EQUAL)
opCode = NOOP;
// Reset opCode
else
opCode = keyCode;
// Set up for next operation
displayState = REPLACE;
displayRegister = 0;
return accumulator;
} // doCurrentOp
break;
/**
* handleKeyPress() handles all key presses. It distinguishes two
* types of keys, digit keys, which are used to create integer operands
* by appending digits, and opCode keys such as + and C.
* @return a String giving the value that should be displayed by the calculator.
*/
public String handleKeyPress (String keyStr, String external_display) {
String resultStr;
// Stores the result
char keyCh = keyStr.charAt(0);
// Convert the key label to a char
if (Character.isDigit(keyCh)) {
// If this was a digit key
if (displayState == APPEND)
// either append it
resultStr = external_display + keyCh;
else {
// or use it to replace the display
displayState = APPEND;
resultStr = keyStr;
}
284
15. Modify the Converter application so that it can convert in either direction:
from miles to kilometers, or from kilometers to miles. Use radio buttons in your
design to let the user select on or the other alternative.
/*
*
*
*
*
*
*
*
File: Converter.java
Author: Java, Java, Java
Description: This version of the Converter class
presents a more elaborate GUI for interacting with
the MetricConverter class. In the previous version
the user had to type in their input. In this version
a numeric key pad is used to input miles.
// Packages used
Figure 9.7: A graphical user interface for the Metric Converter program.
285
private
private
private
private
private
private
private
286
// An array of buttons
// An array of button labels
/**
* Converter() constructor sets the layout and adds
*
components to the top-level JFrame. Note that components
*
are added to the ContentPane rather to the JFrame itself.
* Note how the RadioButtons are created and added to the
*
ButtonGroup.
*/
public Converter(String title) {
super(title);
getContentPane().setLayout(new BorderLayout());
initKeyPad();
JPanel inputPanel = new JPanel();
// Input panel
inputPanel.add(prompt);
inputPanel.add(input);
inputPanel.add(miUnit);
// Configure and add radio buttons
inputPanel.add(kmUnit);
unitsGroup.add(miUnit);
unitsGroup.add(kmUnit);
miUnit.setSelected(true);
getContentPane().add(inputPanel,"North");
JPanel controlPanel = new JPanel(new BorderLayout(0, 0)); // Control panel
controlPanel.add(keypadPanel, "Center");
controlPanel.add(convert, "South");
getContentPane().add(controlPanel, "East");
getContentPane().add(display,"Center");
display.setLineWrap(true);
display.setEditable(false);
convert.addActionListener(this);
input.addActionListener(this);
} // Converter()
// Output display
287
/**
* initKeyPad() creates an array of JButtons and organizes them
*
into a graphical key pad panel. Note that you must distinguish
*
the JButton array, an internal memory structure, from the
*
key pad panel, a graphical object that appears in the user interface.
*/
public void initKeyPad() {
keypadPanel.setLayout(new GridLayout(4,3,1,1)); // Grid layout
keyPad = new JButton[NBUTTONS];
// Create the array itself
for(int k = 0; k < keyPad.length; k++) {
// For each button
keyPad[k] = new JButton(label[k]);
// Create a labeled button
keyPad[k].addActionListener(this);
// and a listener
keypadPanel.add(keyPad[k]);
// and add it to the panel
} // for
} // initKeyPad()
/**
* actionPerformed() handles all action events for the program.
*
It must distinguish whether the user clicked on one of the
*
buttons on the keypad or on the "Convert" or "Input" button.
* Note how the state of the radio buttons is used to determine
*
whether to convert mi to km or vice versa.
* @param e -- the ActionEvent which prompted this method call
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == convert || e.getSource() == input) {
if (miUnit.isSelected()) {
double miles = Double.valueOf(input.getText()).doubleValue();
double km = MetricConverter.milesToKm(miles);
display.append(miles + " miles equals " + km + " kilometers\n");
input.setText("");
} else {
double km = Double.valueOf(input.getText()).doubleValue();
double miles = MetricConverter.kmToMile(km);
display.append(km + " km equals " + miles + " miles\n");
input.setText("");
}
} else {
// A keypad button was pressed
JButton b = (JButton)e.getSource();
if (b.getText().equals("C"))
input.setText("");
else
input.setText( input.getText() + b.getText() );
}
} // actionPerformed()
288
/**
* itemStateChanged() handles clicks on the radio buttons
*/
public void itemStateChanged(ItemEvent e) {
}
/**
* main() creates an instance of this (Converter) class and sets
*
the size and visibility of its JFrame.
* An anonymous class is used to create an instance of the
*
WindowListener class, which handles the window close events
*
for the application.
*/
public static void main(String args[]) {
Converter f = new Converter("Metric Converter");
f.setSize(400, 300);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
// Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // Converter
/*
* File: MetricConverter.java
* Author: Java, Java, Java
* Description: This class implements the static milesToKm()
*
method, which converts miles to kilometers.
*/
public class MetricConverter {
/**
* mileToKm() converts miles to kilometers
* @param miles -- the number of miles to convert
* @return -- a double giving the number of kilometers
*/
public static double milesToKm(double miles) {
return miles / 0.62;
}
/**
* kmToMile() converts kilometers to miles
* @param km -- the number of kilometers to convert
* @return -- a double giving the number of miles
*/
public static double kmToMile(double km) {
return km * 0.62;
}
}
16. Heres a design problem for you. A biologist needs an interactive program that
calculates the average of some field data represented as real numbers. Any real
number could be a data value, so you cant use a sentinel value, such as 9999, to
indicate the end of the input. Design and implement a suitable interface for this
problem.
Design: See the next problem for a GUI design that solves both this problem
and the next problem.
17. Challenge: A dialog box is a window associated with an application that appears
only when needed. Dialog boxes have many uses. An error dialog is used to
report an error message. A file dialog is used to help the user search for and open
a file. Creating a basic error dialog is very simple in Swing. The JOptionPane
class has class methods that can be used to create the kind of dialog shown in
Text Figure 9-41. Such a dialog box can be created with a single statement:
JOptionPane.showMessageDialog(this, "Press OK to dismiss me.");
Convert the Average program (Text Figure 6-7) to a GUI interface and use the
JOptionPane dialog to report errors.
Figure 9.8: A graphical user interface for inputting an unlimited number values to be
averaged.
289
290
Design: This is not a difficult design problem for a GUI. A textfield can be used
for the input values. Each time a value is input, it is added to a running total and
a new average is computed. Theres no real need to worry about a sentinel value.
/*
* File: Average.java
* Author: Java, Java, Java
* Description: This class computes the average of an
*
unlimited number of grades input by the user. The
*
user terminates the input by typing the sentinel
*
value 9999.
*/
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Average extends JFrame implements ActionListener {
private
private
private
private
public Average() {
getContentPane().setLayout(new BorderLayout());
controls.add(prompt);
controls.add(inField);
inField.addActionListener(this);
getContentPane().add(controls,"North");
getContentPane().add(display,"Center");
display.setText("This program will compute your exam average.\n");
}
/**
* actionPerformed() computes and displays a new average every time
*
the user hits a return in the input text field.
*/
public void actionPerformed(ActionEvent e) {
double grade = convertStringTodouble(inField.getText()); // Get a grade
if (grade < 0 || grade > 100)
JOptionPane.showMessageDialog(this, "The grade must be between 0 and 100");
else {
runningTotal += grade;
291
count++;
display.append("Your current average for " + count + " grades is "
+ runningTotal/count + "\n");
}
} // actionPerformed()
/**
* convertStringTodouble() converts a String of the form "54.87" into
* its corresponding double value (54.87).
* @param s -- stores the string to be converted
* @return A double is returned
*/
private double convertStringTodouble(String s) {
Double doubleObject = Double.valueOf(s);
return doubleObject.doubleValue();
}
/**
* main() -- Creates an instance of the Average object to compute
*
the average of the users test grades.
*/
public static void main( String args[] ) {
Average avg = new Average();
avg.setSize(450,300);
avg.setVisible(true);
avg.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // Average
18. Challenge: Design and implement a version of the game Memory. In this game
you are given a two-dimensional grid of boxes that pairs of matching images or
strings. The object is to find the matching pairs. When you click on a box, its
contents are revealed. You then click on another box. If its contents match the
first one, their contents are left visible. If not, the boxes are closed up again. The
user should be able to play multiple games without getting the same arrangement
every time.
Design: We use a grid layout of buttons for the game board. This is placed in
one control panel located at the center of a border layout. At the north border
should be a second panel containing the games controls. This solution contains a
single control a reset button. A nice refinement would be some kind of display
that counts the users guesses. The games main control algorithm is put right
into the actionPerformed() method.
/*
292
*
*
*
ory
*
*
*
*
*
*
*
*/
293
File: MemoryGame.java
Author: Java, Java, Java
Description: This class creates an user interface a memgame.
It displays an NCELLS x NCELLS grid of buttons, each labeled
initially by "?". Under the buttons are pairs of letters A,
B, and so on. The object of the game is to find all the pairs
in the fewest guesses. The user clicks on one button and then
another to show their hidden letters. If they match, the letters
remain showing, otherwise, they are covered up again when the user
clicks on another button.
import
import
import
import
javax.swing.*;
java.awt.*;
java.awt.event.*;
java.applet.Applet;
294
295
if (firstGuess == null) {
// If first guess, store it
firstGuess = b;
firstGuessName = b.getName();
} else if (secondGuess == null) {
// If second guess, store it
secondGuess = b;
secondGuessName = b.getName();
} else {
// If third guess, restart
if (!firstGuessName.equals(secondGuessName)) { // If guesses wrong
firstGuess.setText("?");
// Cover up the names
secondGuess.setText("?");
}
firstGuess = b;
// Reset the guesses
firstGuessName = b.getName();
secondGuess = null;
secondGuessName = "?";
}
} // actionPerformed()
/**
* main() creates an instance of the interface.
*/
public static void main( String args[] ) {
MemoryGame game = new MemoryGame("Memory Game");
game.setSize(400,400);
game.setVisible(true);
game.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // MemoryGame
296
297
Exercise 9.9
Exercise 9.10
interface
ActionListener
datatype
ActionListener
JFrame
+actionPerformed()
+actionPerformed()
JFrame
TemperatureGUI
CDInterest
-rateField : JTextField
-principalField : JTextField
-yrsField : JTextField
-dailyButton : JButton
-yearlyButton : JButton
-display : JTextArea
-inField : JTextField
-display : JTextArea
-celsUnit : JRadioButton
-fahrUnit : JRadioButton
-convert : JButton
-unitsGroup : ButtonGroup
-temperature : Temperature
Uses
Uses
+CDInterest()
+actionPerformed()
+main()
CDExpert
Temperature
Exercise 9.11
interface
ActionListener
JApplet
JPanel
+actionPerformed()
Miscellaneous Types
CyberPetApplet
Uses
-statefield : JTextField
-eatButton : JButton
-sleepButton : JButton
-nameLabel : JLabel
+init()
+paint(in g : Graphics)
+actionPerformed()
Canvas
-applet : JApplet
-eatImg : Image
-sleepImg : Image
Uses
CyberPet
Graphics
datatype
JButton[]
ButtonGroup
Image
JButton
JTextArea
datatype
String[]
datatype
boolean
JTextField
JLabel
JRadioButton
298
Exercise 9.12
interface
ActionListener
interface
ActionListener
JFrame
+actionPerformed()
+actionPerformed()
JApplet
CalculatorUI
Password
Uses
-keyPadPanel : JPanel
-accumulator : JTextArea
-keyPad : JButton[]
-labels : String[]
-inPassword : PasswordField
-password : String
+init()
+actionPerformed()
+display() : JTextArea
TextField
Calculator
Uses
+NOOP : int = -1
+EQUAL : int = 0
+ADD : int = 1
+SUBTRACT : int = 2
+MULTIPLY : int = 3
+DIVIDE : int = 4
+CLEAR : int = 5
+APPEND : int = 0
+REPLACE : int = 1
-accumulator : int
-displayRegister : int
-opCode : int
-displayState : int
-error : boolean
PasswordField
+PasswordField()
+PasswordField() : int
+actionPerformed()
Exercise 9.15
interface
ActionListener
+actionPerformed()
MetricConverter
JFrame
+milesToKm(in mi : double) : double
+kmToMile(in mi : double) : double
+Calculator()
-initialize()
-keyToIntCode(in keyCh : char) : int
-doCurrentOp(in keyCode : int) : int
+handleKeyPress(in keyStr : String, in externalDisplay : String) : String
Converter
-NBUTTONS : <unspecified> = 12
-input : JTextField
-display : JTextArea
-convert : JButton
-keyPadPanel : JPanel
-miUnit : JRadioButton
-kmUnit : JRadioButton
-unitsGroup : JButtonGroup
-keyPad : JButton[]
-labels : String[]
+Converter(in title : String)
+initKeyPad()
+actionPerformed()
+main()
Uses
Miscellaneous Types
JButton
JPanel
datatype
JButton[]
JTextArea
JButtonGroup
datatype
String[]
JRadioButton
datatype
boolean
JTextField
299
Exercise 9.18
Exercise 9.16-9.17
JFrame
Miscellaneous Types
interface
ActionListener
interface
ActionListener
JFrame
+actionPerformed()
+actionPerformed()
MemoryGame
Average
-infield : JTextField
-display : JTextArea
+Average()
+actionPerformed()
+main()
-reset : JButton
-cells : JButton[]
-alphabet : String
-firstGuess : JButton
-secondGuess : JButton
-firstGuessName : String
-secondGuessName : String
+MemoryGame(in title : String)
-initBoard()
+shuffle(in s : String) : String
+actionPerformed()
+main()
JPanel
JButton
JTextArea
JFrame
JButtonGroup
JRadioButton
JTextField
datatype
JButton[]
datatype
boolean
datatype
String[]
Chapter 10
(h)
(i)
(j)
(k)
(l)
(m)
the pixel is redrawn in the resulting color. In XOR mode drawing the same
shape twice in the same location will make it appear and then disappear.
The paint() and paintComponent() methods.
Answer: The paint() method is used to draw AWT components and all
top-level Swing components. The paintComponent() method is used
to draw all Swing components descended from JComponent.
A mouse event and a mouse motion event.
Answer: A mouse event is generated when the mouse is clicked. A mouse
motion event is generated when the mouse is moved.
A public and a protected element.
Answer: A public element is accessible to all objects. A protected
element is accessible only to objects of the same type or those descended
from that type.
A private and a protected element.
Answer: A private element is accessible only to objects of the same
type. A protected element is accessible only to objects of the same type
or those descended from that type.
A Font and a Fontmetrics object.
Answer: A Font object represents a font in terms of its name, size, and
style. A Fontmetrics object describes a font in terms of the width and
height of its characters.
A Dimension and a Point object
Answer: A Dimension represents the width and height of a certain
object. A Point represents a location within a coordinate system.
301
302
(c) When a
component is updated, its background is not automatically
cleared. Answer: Swing
(d) When a
component is updated, its background is automatically cleared.
Answer: AWT
(e) When the mouse is clicked, this event should be handled by methods of the
interface. Answer: MouseListener
(f) When the mouse is dragged, this event should be handled by methods of
interface. Answer: MouseMotionListener
the
5. Write Java statements to implement the following tasks. Where necessary, use g
as a reference to the graphics context.
(a) Move the default origin to a point thats displaced 50 pixels to the right and
100 pixels above the origins current location.
g.translate(50, 100);
(i) Set a JPanels foreground color to yellow and its background color to
blue.
panel.setForeground(Color.yellow);
panel.setBackground(Color.blue);
7. One Graphics method that was not demonstrated in the chapter was the drawPolygon() method. For parameters this method takes two int arrays representing the x and y coordinates of the polygons points. A third int parameter
gives the number of points in the polygon. Heres an example of how this can be
used:
int xcoords[] = {100, 50, 70, 130, 100};
int ycoords[] = {100, 150, 200, 200, 100};
g.drawPolygon(xcoords, ycoords, xcoords.length);
Use graph paper and pencil to design a hexagon (six-sided figure) and an octagon
(eight-sided figure). Then use drawPolygon() to draw their shapes in an
application.
private
private
private
private
int
int
int
int
xHex[]
yHex[]
xOct[]
yOct[]
=
=
=
=
303
Figure 10.1: Polygons and rectangles are used to draw this figure.
/*
* File: ThreeDShapes.java
* Author: Java, Java, Java
* Description: Uses drawPolygon() and fillPolygon() to
*
draw a three-dimensional object.
*/
import java.awt.*;
import javax.swing.*;
public class ThreeDShapes extends JPanel {
304
9. Write a method to draw a bullseye. This method can make good use of g.setXORMode(
Color.black ). Heres how the method should work. Draw the outer circle of the bullseye. Then draw a slightly smaller circle within it, then a slightly
smaller circle within that. And so on. The method should take a Graphics
parameters as well as parameters for the bullseyes location and diameter.
/**
* bullsEye() draws a bullseye using XOR mode to alternate
* between black and white circles
* @param g -- a reference to the Graphics context
*/
public void bullsEye(Graphics g) {
g.setXORMode(Color.black);
int xRef = 40, yRef = 40, size = 200;
305
306
10. Write a method that takes an array of Points and draws a line between each
pair of consecutive points. This should be a void method and should also take
a Graphics parameter.
/**
* drawLines() draws lines between each pair of consecutive
* points in its array parameter
* @param g -- the Graphics context
* @param p -- an array of Point
*/
public void drawLines(Graphics g, Point p[]) {
for (int k = 0; k < p.length -1; k++) {
System.out.println("point");
g.drawLine(p[k].x, p[k].y, p[k+1].x, p[k+1].y);
}
} // drawLines()
11. Design and implement a Java applet or application that draws a colored pie chart
representing the relative numbers of As, Bs, Cs, Ds, and Fs in a fictitious computer science course. Allow the numbers of each grade to be input by the user.
Design: An array of JTextFields (with associated prompts) is provided for
inputting the number of As, Bs, and so on. Two buttons (Draw and Clear) control
the drawing of the chart. A BorderLayout is used, in which a control panel is
located on the north and a drawing canvas is located in the center of the JFrame.
Note that PieChart is a subclass of JPanel. This allows it to inherit the
necessary drawing capabilities.
A nice refinement of this exercise would be to label the pie chart. One possibility
is to use a rectangular- shaped color chart to associate the different colors with
the different letter grades.
/*
* File: PieChart.java
* Author: Java, Java, Java
* Description: This subclass of JPanel draws a
* given an array of data representing a grade
- that is,
* so many As, Bs, Cs, and so on. The charts
ative to
* the size of its containing JPanel and it is
pie chart
distribution size is made relcentered in the panel
Figure 10.2: The PieChartGUI application draws an unlabeled pie chart, centered
on the drawing canvas.
307
308
*/
import java.awt.*;
import javax.swing.*;
public class PieChart extends JPanel {
private int chartSize;
/**
* PieChart() constructor
*/
public PieChart () {
super();
}
/**
* paintComponent() paints the JPanel
* @param g -- a reference to the Graphics context
*/
public void paintComponent(Graphics g) {
Dimension size = this.getSize();
g.setColor(getBackground());
g.fillRect(0, 0, size.width, size.height);
chartSize = Math.min(getSize().width, getSize().height) -
40;
} // paintComponent()
/**
* computeTotal() calculates the sum of the elements of its array parameter
* @param arr -- an array of integers
* @return -- an int giving the sum of the arrays elements
*/
private int computeTotal(int arr[]) {
int sum = 0;
for (int k = 0; k < arr.length; k++)
sum += arr[k];
return sum;
} // computeTotal()
/**
* drawPieChart() draws a pie chart of the data given in its array parameter. Note
* that the chart is draw relative to the size of the panel. Each pie segment is
* drawn in a different shade of gray.
* @param grades -- an array of integers representing a grade distribution,
*
that is, so many As, so many Bs, and so on
309
*/
public void drawPieChart(int grades[]) {
Graphics g = getGraphics();
Dimension size = this.getSize();
g.translate(size.width/2 - chartSize/2, size.height/2 chartSize/2);
double total = computeTotal(grades);
// Compute sum
int rgb = 32;
// For grays, r = g = b
Color color = null;
int startAngle = 0;
for(int k = 0; k < grades.length; k++) {
// For each letter grade
color = new Color(rgb, rgb, rgb);
// For grays, r = g = b
g.setColor(color);
rgb+=32;
// Lighten the color
double percent = grades[k] / total;
// Percentage of total grades
int currAngle = (int) Math.round(360 * percent); // Scale to 360 Degrees
g.fillArc(0, 0, chartSize, chartSize, startAngle, currAngle);
// Draw a pie slice
startAngle += currAngle;
// Advance the start angle
} // for
} // drawPieChart
} // PieChart
/*
* File: PieChartGUI.java
* Author: Java, Java, Java
* Description: This class provides a graphical user interface for the
* PieChart class. Several text fields are used to input a grade distribution -* that is, so many As, Bs, Cs, and so on. A control button causes the grades
* to be displayed as a pie chart within a drawing JPanel.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PieChartGUI extends JFrame implements ActionListener {
public static final int WIDTH = 450, HEIGHT = 300; // Initial Width and Height
public static final int NGRADES = 5;
private JLabel prompt[] = new JLabel[NGRADES];
private JTextField gradeField[] = new JTextField[NGRADES];
ray of text fields
// An ar-
310
f.setSize(WIDTH, HEIGHT);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // PieChartGUI
12. Design and implement an applet or application that draws a histogram representing the relative numbers of As, Bs, Cs, Ds, and Fs in a fictitious computer science
course. Allow the numbers of each grade to be input by the user.
Design: The design of this GUI is the same as that used in the previous exercise.
/*
311
312
* File: BarChart.java
* Author: Java, Java, Java
* Description: This subclass of JPanel draws a bar chart (histogram)
* given an array of data representing a grade distribution - that is,
* so many As, Bs, Cs, and so on. The charts size is made relative to
* the size of its containing JPanel. It is located at the bottom
* left of the panel.
*/
import java.awt.*;
import javax.swing.*;
public class BarChart extends JPanel {
private final int MAXBAR = 200;
imum bar
private final double SCALE = 0.75;
private int chartSize;
/**
* BarChart() constructor
*/
public BarChart () {
super();
}
/**
* paintComponent() paints the JPanel
* @param g -- a reference to the Graphics context
*/
public void paintComponent(Graphics g) {
Dimension size = this.getSize();
g.setColor(getBackground());
g.fillRect(0, 0, size.width, size.height);
chartSize = Math.min(getSize().width, getSize().height) 40;
} // paintComponent()
/**
* computeTotal() calculates the sum of the elements of its array parameter
* @param arr -- an array of integers
* @return -- an int giving the sum of the arrays elements
*/
private int computeTotal(int arr[]) {
int sum = 0;
for (int k = 0; k < arr.length; k++)
sum += arr[k];
313
return sum;
} // computeTotal()
/**
* drawBarChart() draws a histogram of the data given in its array parameter. Note
* that the chart is draw relative to the size of the panel.
* @param grades -- an array of integers representing a grade distribution,
*
that is, so many As, so many Bs, and so on
*/
public void drawBarChart(int grades[]) {
Dimension size = this.getSize();
Graphics g = getGraphics();
int maxBar = (int)(SCALE * size.height);
// Size of biggest bar in histogram
int barwidth = size.width/40;
// Width of bars
int hgap = size.width/60;
// Gap between bars
g.translate(40, size.height - 40 );
// Move origin to bottom left of panel
g.drawLine(0,0,grades.length * (2 * barwidth + hgap), 0);
// Draw the xaxis
int href = 0;
for (int k = 0; k < grades.length; k++ ) {
int hgt = (int) (maxBar * grades[k]/ MAXBAR );
culate height of bar
g.setColor( Color.black );
g.drawString( k+1 + "", href+5, 13);
bel the chart
g.fillRect(href, -hgt, barwidth, hgt);
href += barwidth + hgap;
erence pt for bar
} // for
} // drawBarChart()
} // BarChart
// La-
// Move ref-
/*
* File: BarChartGUI.java
* Author: Java, Java, Java
* Description: This class provides a graphical user interface for the
* BarChart class. Several text fields are used to input a grade distribution -* that is, so many As, Bs, Cs, and so on. A control button causes the grades
* to be displayed as a bar chart within a drawing JPanel.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
314
chart.drawBarChart(grades);
} else
chart.repaint();
} // actionPerformed()
315
/**
* main() creates an instance of the top-level frame. Note the use of the anonymous
* WindowAdapter to manage closing of the top-level frame.
*/
public static void main(String args[]) {
BarChartGUI f = new BarChartGUI("Bar Chart");
f.setSize(WIDTH, HEIGHT);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // BarChartGUI
13. Design and implement an applet or application that displays a multiline message
in various fonts and sizes input by the user. Let the user choose from among a
fixed selection of fonts, sizes, and styles.
Design: Two JComboBoxes are used to let the user choose among the various
fonts and sizes. This applet must therefore implement the ItemListener interface to handle the users selections. Whenever a selection is made, the default
font is changed and the applet is repainted. A subclass of JPanel is used as the
actual drawing surface. Once again, the top-level frame uses a BorderLayout with controls at the north and the drawing panel in the center. The solution
provided here lets the user select fonts and sizes. Extending it to allow selection
of font styles is a simple matter of using an additional JComboBox.
/*
*
*
*
*
ing
*
*/
File: FontChooser.java
Author: Java, Java, Java
Description: This applet lets the user select a font and a size from
a choice box and then draws a messages, centered in a drawpanel,
in the selected font.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class FontChooser extends JApplet implements ItemListener {
316
private
private
private
private
private
JComboBox fonts;
// Font choices
JComboBox sizes = new JComboBox();
// Size choices
JPanel controls = new JPanel();
Canvas canvas = new Canvas("Java, Java, Java");
String message = "Java, Java, Java";
/*
* init() sets up the applets interface. It uses the GraphicsEnvironment object
*
to get a list of the fonts available on the system and then displays these
*
in a choice box. It also creates a size choice box.
*/
public void init() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
fonts = new JComboBox(ge.getAvailableFontFamilyNames());
for (int k = 10; k < 24; k++)
// Add different font sizes
sizes.addItem(k + "" );
canvas.setBorder(BorderFactory.createTitledBorder("Drawing Area"));
controls.add(fonts);
controls.add(sizes);
getContentPane().add(controls,"North");
// And add it to the applet
getContentPane().add(canvas,"Center");
// And add it to the applet
sizes.addItemListener(this);
// And register it with listener
fonts.addItemListener(this);
// And regis-
317
/*
* File: Canvas.java
* Author: Java, Java, Java
* Description: This class implements a drawing canvas as
*
a subclass of JPanel. It is used with the FontChooser applet. It
*
sets the font to a user-selected font and print a message whenever it is repainted.
*/
import javax.swing.*;
import java.awt.*;
public class Canvas extends JPanel {
private String message;
// Current message
private Font font;
/*
* Canvas() constructor sets the internal message from its parameter
* @param msg -- a String used to set the message
*/
public Canvas(String msg) {
super();
message = msg;
}
/*
*
*
*
318
*/
public void setFont(String fontName, int fontsize) {
font = new Font(fontName, Font.PLAIN, fontsize);
} // setFont()
/*
* paintComponent() is called each time the canvas needs to be painted.
*
It draws the current message, centered in the panel.
* @param g -- the Canvass Graphics object
*/
public void paintComponent(Graphics g) {
g.setFont(font);
// Set the font
FontMetrics metrics = g.getFontMetrics();
// And get its metrics
Dimension d = getSize();
// Get the applets size
int x = (d.width - metrics.stringWidth(message)) / 2; // Calculate coordinates
int hgt = metrics.getHeight();
int y = (d.height + hgt ) / 2;
g.drawString(message, x, y);
// Draw the message
} // paintComponent()
} // Canvas
14. Modify the Graph program so the user can enter the coordinates of the linear or
quadratic equations to be graphed.
Design: JTextFields (and associated prompts) are used to input the coordinates for either a quadratic or linear graph. JButtons are used to draw either
a quadratic or a linear graph and to clear the drawing panel. The drawing panel
is a subclass of JPanel. As in previous exercises a BorderLayout is used,
with the controls at the north and the drawing panel in the center.
/*
*
*
*
ear
*
*/
File: Graph.java
Author: Java, Java, Java
Description: This class contains methods for drawing linand
quadratic equations. It is accessed through GraphGUI class.
import java.awt.*;
import javax.swing.*;
public class Graph extends JPanel {
/**
* Graph constructor simply calls the superconstructor
*/
public Graph () {
super();
319
}
/**
* paintComponent() clears the drawing area
*/
public void paintComponent( Graphics g ) {
Dimension size = this.getSize();
g.setColor( getBackground() );
// Clear the drawing area
g.fillRect(0,0,size.width+40,size.height+40);
} // paintComponent()
/**
* drawXYAxes() draws the x and y axes to a size that is relative to
* to the panels size.
*/
private void drawXYAxes(Graphics g) {
Dimension size = this.getSize();
// Get the panels size
int hBound = size.width/2;
// Use it to set the bounds
int vBound = size.height/2;
int tic = size.width/100;
g.drawLine(-hBound,0,hBound,0);
// X-axis
for (int k = -hBound; k <= hBound; k+=10)
g.drawLine(k,tic,k,-tic);
g.drawLine(0,vBound,0,-vBound);
// Y-axis
for (int k = -vBound; k <= vBound; k+=10)
g.drawLine(-tic,k,+tic,k);
} // drawXYAxes()
/**
* graphLine() draws the line with slope m and y-intercept b
* @param m -- a double giving the lines slope
* @param b -- a double giving the lines y-intercept
*/
public void graphLine(double m, double b) {
Graphics g = getGraphics();
Dimension size = this.getSize();
// Get the panels size
g.translate(size.width/2,size.height/2); // Place origin at middle
g.setColor( Color.black );
drawXYAxes( g );
// Draw the X and Y axes
int hBound = size.width/2;
// Use it to set the bounds
g.setColor( Color.red );
for (int x = -hBound; x <= hBound; x++ ) { // For each pixel on x axis
int y = (int) (m * x + b );
y = -y;
// Reverse y coordinate (Cartesian)
g.drawLine(x,y,x+1,y+1);
// Draw a point
320
}
} // graphLine()
/**
* graphQuadratic() draws the quadratic curve given coefficients a, b, and c
* @param a -- a double giving the curves a coefficient
* @param b -- a double giving the curves b coefficient
* @param c -- a double giving the curves c coefficient
*/
public void graphQuadratic(double a, double b, double c) {
Graphics g = getGraphics();
Dimension size = this.getSize();
// Get the panels size
g.translate(size.width/2,size.height/2); // Place origin at middle
g.setColor( Color.black );
drawXYAxes( g );
// Draw the X and Y axes
int hBound = size.width/2;
// Use it to set the bounds
g.setColor( Color.red );
for (int x = -hBound; x <= hBound; x++ ) { // For each pixel on x axis
int y = (int) (a * x * x + b * x + c);
y = -y;
// Reverse y coordinate (cartesian)
g.fillOval(x-1,y-1,3,3);
// Draw a point
} // for
} // graphQuadratic()
} // Graph
/*
* File: GraphGUI.java
* Author: Java, Java, Java
* Description: This class provides a graphical user interface to
*
the Graph class. It lets the user input values for a linear
*
and quadratic equation and then graphs the equations. It also
*
contains a button to clear the drawing area.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GraphGUI extends JFrame implements ActionListener {
public static final int WIDTH = 450, HEIGHT = 400; // Default width and height
private Graph graph = new Graph();
ing expert
// The Graph-
private
els for the
private
private
private
JPanel
layout
JPanel
JPanel
JPanel
321
// Pan-
private
private
private
private
private
JLabel
JLabel
JLabel
JLabel
JLabel
322
clearButton.addActionListener(this);
inputs.setLayout(new GridLayout(2, 1, 0, 0));
inputs.add(linearPanel);
inputs.add(quadPanel);
getContentPane().add(inputs, "North");
getContentPane().add(graph, "Center");
getContentPane().add(controls, "South");
graph.setBorder(BorderFactory.createTitledBorder("Graph Panel"));
setSize(WIDTH,HEIGHT);
} // GraphGUI()
/**
* actionPerformed() handles user actions, which consist of
*
either graphing a line, a quadratic, or clearing the window.
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == linearButton) {
double m = Double.parseDouble(mField.getText());
double b = Double.parseDouble(bField.getText());
graph.graphLine(m, b);
} else if (e.getSource() == quadButton) {
double a = Double.parseDouble(aQField.getText());
double b = Double.parseDouble(bQField.getText());
double c = Double.parseDouble(cQField.getText());
graph.graphQuadratic(a, b, c);
} else
graph.repaint();
} // actionPerformed()
/**
* main() creates an instance of this class.
*/
public static void main(String args[]) {
GraphGUI f = new GraphGUI("Graphing Window");
f.setSize(WIDTH, HEIGHT);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // GraphGUI
15. Design and implement a Java applet or application that draws and paints a logo
for a fictitious company.
/*
* File: LogoApplet.java
* Author: Java, Java, Java
* Description: This applet displays a logo image centered within applet window.
*/
import java.awt.*;
import javax.swing.*;
public class LogoApplet extends JApplet {
private Image logo;
/**
* init() loads the image from the applets base directory.
*/
public void init() {
logo = getImage(getDocumentBase(), getParameter("logo"));
}
/**
* paint() calculates the images x and y coordinates relative to
* the applets size, and then displays the image.
*/
public void paint(Graphics g) {
323
Dimension d = getSize();
// Get the applets size
int x = (d.width - logo.getWidth(this)) / 2;
int y = (d.height = logo.getHeight(this)) / 2;
g.drawImage(logo, x, y, this);
// Draw the logo
} // paint()
} // LogoApplet
16. Design and implement an applet or application that plays the following game
with the user. Draw a shape or an image on the screen and invite the user to
click on it. Every time the user clicks on it, move the shape to an new random
location.
Design: In order to handle mouse actions, this applet must implement both the
MouseListener and MouseMotionListener interfaces. The interface
consists of a rectangle boundary, drawn to the dimensions of the top-level frame,
which marks the playing area, and a filled rectangular shape, which serves as the
target. By keeping track of the mouses location and keyclicks, the program can
tell when it is near the target. When it is near enough, the target is erased and
redrawn at a random location.
17. Modify the program in the previous exercise so that the shape moves whenever
the user moves the mouse to within a certain distance of the shape.
Figure 10.6: The MouseClickGame Whenever the mouse comes near the target, the
target will jump.
324
325
/*
* File: MouseClickGame.java
* Author: Java, Java, Java
* Description: This applet draws a target at a random location. Each
* time the user tries to click on the target, it moves to a new random
* location.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MouseClickGame extends JApplet implements MouseListener,
MouseMotionListener {
private
private
ence points
private
private
private
// Back-
// Mouses cur-
// Out-
// Tar-
/**
* init() sets the size of the applet and sets up the mouse listeners
*/
public void init () {
addMouseMotionListener(this);
// ADD Mouse AND Motion LISTENERS
addMouseListener(this);
setSize(WIDTH, HEIGHT);
} // init()
/**
* paint() draws a boundary around the game area and draws the target.
*/
public void paint (Graphics g) {
Dimension d = getSize();
// Get the ap-
326
plets size
g.setColor(lineColor);
g.drawRect(LEFT,TOP,d.width-BORDER, d.height-BORDER); // The game area
drawTarget();
g.drawString("Try to click on the rectangle.",LEFT,d.height5);
} // paint()
/**
* moveTarget() moves the target to a random location.
*/
private void moveTarget() {
Dimension d = getSize();
// Get the applets size
target.x = (int)(BORDER + Math.random() * (d.width 2 * BORDER));
target.y = (int)(BORDER + Math.random() * (d.height 2 * BORDER));
} // moveTarget()
/**
* drawTarget() first erases the target and then draws it in its new location
*/
private void drawTarget() {
Graphics g = getGraphics();
g.setColor(getBackground());
g.fillRect(target.x, target.y, SIZE, SIZE);
// Erase target
moveTarget();
// Move target
g.setColor(Color.black);
g.fillRect(target.x, target.y, SIZE, SIZE);
// Redraw target
} // drawTarget()
// Mouse Handling Interfaces:
/**
* mouseMoved() is called automatically whenever the user moves the mouse.
* If the mouse enters the bounds of the target, the target is moved and redrawn.
*/
public void mouseMoved(MouseEvent e) {
mouse = e.getPoint();
// Get coordinates
int deltax = Math.abs(target.x - mouse.x);
int deltay = Math.abs(target.y - mouse.y);
if (deltax <= SIZE && deltay <= SIZE)
drawTarget();
} // mouseMoved()
/**
327
} // These meth} //
} //
of the lis-
}
}
} // MouseClickGame
18. Challenge: Design and implement an applet or application that plays the following game with the user. Place a puck at a random location on the screen and
paint a goal in some other location. Invite the user to move the puck into the goal.
Have the users mouse-controlled stick exert a repulsive force on the image. The
puck always moves away from the stick on an imaginary line originating at the
stick and intersecting the puck. When the user gets the puck in the goal, draw a
happy face on the screen.
Design: Given the solution to the previous exercise, the challenge in this exercise is determining where and how far to move the puck in response the mouse
click. It should move in a direction that is opposite to the relative location of the
mouse. Given the coordinates for the mouse and the puck, the program calculates deltax and deltay, the difference in the x and y coordinates. You can
image this as a line segment connecting the puck and the mouse. It then moves
the puck by a random amount along this line but in the opposite direction.
/*
* File: MouseHockeyGame.java
* Author: Java, Java, Java
* Description: This applet plays a hockey-like game in which the user tries
* go move a puck into a goal by manipulating the mouse. Whenever the mouse is
* clicked within a certain distance of the center of the puck, the puck is
* "shot" a random distance in the opposite direction. That is, if the user
* clicks on the bottom right of the puck, it should shoot if in the up left
* direction.
Figure 10.7: The MouseHockeyGame applet. Try to shoot the puck into the goal.
328
329
*
* Directions are calculated crudely in terms of deltax and deltay, the changes
* in pucks x- and y- coordinates.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MouseHockeyGame extends JApplet implements MouseListener,
MouseMotionListener {
private
private
ence points
private
private
private
private
// Back-
// Mouses cur-
// Out-
// Tar-
/**
* init() sets the size of the applet and initializes the target (puck).
*/
public void init () {
addMouseMotionListener(this);
// ADD Mouse AND Motion LISTENERS
addMouseListener(this);
setSize(WIDTH, HEIGHT);
initTarget();
} // init()
/**
* paint() draws a boundary around the game area and draws the target.
*/
public void paint (Graphics g) {
Dimension d = getSize();
// Get the applets size
330
g.setColor(lineColor);
g.drawRect(LEFT,TOP,d.width-BORDER, d.height-BORDER); // The game area
int goalSize = d.width / 4;
int left = (d.width / 2) - (goalSize/2);
// Draw the goal
int right = left + goalSize;
// Centered at the top
int top = TOP + 4;
g.drawLine(left, top, right, top);
g.drawLine(left, top + 1, right, top + 1);
g.drawLine(left, top + 1, left, top + 1 + goalSize / 3);
g.drawLine(left+1, top + 1, left+1, top + 1 + goalSize / 3);
g.drawLine(right, top + 1, right, top + 1 + goalSize / 3);
g.drawLine(right+1, top + 1, right+1, top + 1 + goalSize / 3);
g.setColor(Color.black);
g.fillRect(target.x, target.y, SIZE, SIZE);
// The target rectangle
g.drawString("Click the mouse near the puck to drive it into the goal.",
LEFT,d.height-5);
} // paint()
/**
* initTarget() draws the puck at a random location within the game area.
*/
private void initTarget() {
Dimension d = getSize();
// Get the applets size
target.x = (int)(BORDER + Math.random() * (d.width-2*BORDER));
target.y = (int)(BORDER + Math.random() * (d.height2*BORDER));
System.out.println(target.x + " " + target.y);
} // initTarget()
/**
* moveTarget() moves the target in reference to the mouses location.
* The target moves a random distance in the opposite direction of the
* mouses location each time the mouse button is clicked.
* @param deltax -- an int giving the distance (+/-) between the puck
*
and the mouses x coordinates
* @param deltay -- an int giving the distance (+/-) between the puck
*
and the mouses y coordinates
*/
private void moveTarget(int deltax, int deltay) {
System.out.println(deltax + " " + deltay);
target.x += deltax * (int)(Math.random() * MAXSHOT); // Calc new location
target.y += deltay * (int)(Math.random() * MAXSHOT);
331
Dimension d = getSize();
if (target.x > d.width - BORDER)
target.x = d.width - BORDER - SIZE - 1;
else if (target.x < LEFT)
target.x = LEFT + BORDER + 1;
/**
* mouseClicked() is called automatically whenever the user clicks the
* mouse. If the click occurs within a certain distance of the center of
* the puck, the puck is "shot" toward the goal by drawTarget().
*/
public void mouseClicked(MouseEvent e) {
// When mouse is clicked
mouse = e.getPoint();
// Get coordinates
int deltax = (target.x + SIZE / 2) - mouse.x;
int deltay =(target.y + SIZE / 2) - mouse.y;
if (Math.abs(deltax) <= SIZE && Math.abs(deltay) <= SIZE)
drawTarget(deltax, deltay);
} // mouseClicked()
public void mouseEntered(MouseEvent e) { } // These five methods are not used
332
} //
}
}
}
333
// Default location
/**
* DrawableRectangle() constructor
* @param l -- a double giving the
* @param w -- a double giving the
*/
public DrawableRectangle(double l,
super(l, w);
location = new Point(0, 0);
} // DrawableRectangle()
/**
* DrawableRectangle() constructor sets its initial location
* @param l -- a double giving the rectangles length
* @param w -- a double giving the rectangles width
* @param loc -- a Point giving the initial location
*/
public DrawableRectangle(double l, double w, Point loc) {
super(l, w);
location = loc;
}
/**
* scale() is part of the Scalable interface. It sets the
* rectangles size by scaling it by its parameter value.
* @param ration -- a double by which to scale the rectangle
*/
public void scale(double ratio){
length = (int) (length * ratio);
width = (int) (width * ratio);
} // scale()
/**
* draw() is part of the Drawable interface. It draws the outline
* of the rectangle.
* @param g -- a reference to the Graphics context
*/
public void draw(Graphics g){
g.drawRect(location.x, location.y, (int)length, (int)width);
System.out.println(location.x + " " + location.y + " " + length + " " + width);
} // draw()
/**
* fill() is part of the Scalable interface. It paints the
* rectangles interior
* @param g -- a reference to the Graphics context
*/
public void fill(Graphics g){
g.fillRect(location.x, location.y, (int)length, (int)width);
334
} // fill()
} // DrawableRectangle
/*
* File: DrawFrame.java
* Author: Java, Java, Java
* Description: This is the top-level frame for an application that
* draws and rescales rectangles.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawFrame extends JFrame {
/**
* DrawFrame() constructor sets the windows title by calling the
*
super constructor.
*/
public DrawFrame(String title) {
super(title);
}
/**
* paint() creates a rectangle, then draws it, shrinks it and fills it.
*/
public void paint(Graphics g) {
DrawableRectangle rect = new DrawableRectangle(100, 50, new Point( 50, 50) );
rect.draw( g);
rect.scale(0.5);
rect.fill( g );
} // paint()
/**
* main() creates an instance of this class. Note the use of the anonymous
* WindowAdapter to manage closing of the top-level frame.
*/
public static void main (String argv[]) {
DrawFrame f = new DrawFrame("Drawable Rectangle");
f.setSize(200, 200);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // DrawFrame
335
/*
* File: Rectangle.java
* Author: Java, Java, Java
* Description: This class represents a geometric rectangle. It is
* defined by its length and width.
*/
public class Rectangle
{
protected double length;
protected double width;
// Instance variables
// Constructor method
// Access method
} // Rectangle
/*
* File: Drawable.java
* Author: Java, Java, Java
* Description: The Drawable interface defines two methods used for drawing
*
objects, the draw() and fill() methods.
*/
import java.awt.*;
public interface Drawable {
public abstract void draw(Graphics g);
public abstract void fill(Graphics g);
}//Drawable
/*
* File: Scalable.java
* Author: Java, Java, Java
* Description: The Scalable interface defines the scale() method, which
*
is used to resize graphical objects.
*/
import java.awt.*;
public interface Scalable {
20. Challenge: Add the ability to handle mouse operations to the DrawableRectangle class defined in the previous exercise. In other words, it should implement MouseListener and MouseMotionListener. These handlers
should enable a user to pick up and move a rectangle to a new location.
Design: The mousePressed() and mouseReleased() methods take care
of picking up and putting down the rectangle. The mouseDragged()
method takes care of moving it. The rectangle is repeatedly erased and redrawn
to simulate movement.
Figure 10.9: The user can pick up and move the rectangle.
/*
* File: DrawFrame.java
* Author: Java, Java, Java
* Description: This is the top-level frame for an application that
* draws and rescales rectangles. This version allows the user to
* grab and move the rectangle to a new location.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawFrame extends JFrame implements
336
337
MouseListener, MouseMotionListener{
private Point mouse;
private DrawableRectangle rect;
private boolean moving = true;
/**
* DrawFrame() constructor sets the windows title by calling the
*
super constructor. It also creates the listeners.
*/
public DrawFrame(String title) {
super(title);
addMouseListener(this);
addMouseMotionListener(this);
}
/**
* paint() creates a rectangle and draws it at a fixed location.
*/
public void paint(Graphics g) {
rect = new DrawableRectangle(100, 50, new Point( 50, 50) );
rect.draw( g);
}
// Mouse Handling Interfaces:
/**
* mouseDragged() is invoked when the user is moving the mouse while
* its button is clicked. It erases the rectangle and redraws it at
* its new location, giving the impression that the user is "holding"
* the rectangle. The moving variable is set true by mousePressed().
*/
public void mouseDragged(MouseEvent e) {
mouse = e.getPoint();
// Get coordinates
Graphics g = getGraphics();
if (moving) {
g.setXORMode(Color.white);
rect.draw(g);
// Erase
rect.setLocation( mouse ); // Move
rect.draw(g);
// Redraw
} // if
} // mouseDragged()
/**
* mousePressed() is invoked when the user presses the mouse button.
* If the user clicked within the rectangle (rect.isClicked()),
* the global variable moving is set true and the rectangle is erased.
*/
338
339
import java.awt.*;
import java.awt.event.*;
public class DrawableRectangle extends Rectangle implements Drawable, Scalable {
protected Point location;
// Default location
/**
* DrawableRectangle() constructor
* @param l -- a double giving the
* @param w -- a double giving the
*/
public DrawableRectangle(double l,
super(l, w);
location = new Point(0, 0);
}
/**
* DrawableRectangle() constructor sets its initial location
* @param l -- a double giving the rectangles length
* @param w -- a double giving the rectangles width
* @param loc -- a Point giving the initial location
*/
public DrawableRectangle(double l, double w, Point loc) {
super(l, w);
location = loc;
}
/**
* setLocation() moves the rectangle to the given point
* @param p -- a Point giving the rectangles new location
*/
public void setLocation(Point p) {
location = p;
} // setLocation()
/**
* isClicked() returns true if its parameters is a point within
* the rectangles bounds
* @param p -- a Point giving the location of the mouse click
*/
public boolean isClicked(Point p) {
int deltax = Math.abs(p.x - location.x);
int deltay = Math.abs(p.y - location.y);
System.out.println(deltax + " " + deltay);
System.out.println(location.x + " " + location.y);
return (deltax <= 3 && deltay <= 3);
} // isClicked()
340
/**
* scale() is part of the Scalable interface. It sets the
* rectangles size by scaling it by its parameter value.
* @param ration -- a double by which to scale the rectangle
*/
public void scale(double ratio){
length = (int) (length * ratio);
width = (int) (width * ratio);
} // scale()
/**
* draw() is part of the Drawable interface. It draws the outline
* of the rectangle.
* @param g -- a reference to the Graphics context
*/
public void draw(Graphics g){
g.drawRect(location.x, location.y, (int)length, (int)width);
System.out.println(location.x + " " + location.y + " " + length + " " + width);
} // draw()
/**
* fill() is part of the Scalable interface. It paints the
* rectangles interior
* @param g -- a reference to the Graphics context
*/
public void fill(Graphics g){
g.fillRect(location.x, location.y, (int)length, (int)width);
} // fill()
} // DrawableRectangle
/*
* File: Rectangle.java
* Author: Java, Java, Java
* Description: This class represents a geometric rectangle. It is
* defined by its length and width.
*/
public class Rectangle
{
protected double length;
protected double width;
// Instance variables
// Constructor method
// Access method
341
21. Challenge: Design and implement your own Polygon class, using an array of
Point as the primary data structure. Use the Drawable interface.
Design: An array of Points is used to store the polygons vertices. The
draw() method simply plots the points. The fill() method connects the
points with lines.
/*
* File: Polygon.java
* Author: Java, Java, Java
* Description: This class defines a drawable polygon. It uses an
* array of Point to stores the polygons points. It implements
* the Drawable interface.
*/
import java.awt.*;
public class Polygon extends Object implements Drawable {
Figure 10.10: The Polygon application draws a random five-sided figure each time
the window is resized.
342
343
344
*
super constructor.
*/
public DrawFrame (String title) {
super(title);
}
/**
* paint() clears the frame and then creates and draws two polygons.
*/
public void paint(Graphics g) {
Dimension d = getSize();
// Clear the frame
g.setColor(getBackground());
g.fillRect(0, 0, d.width, d.height);
g.setColor(Color.black);
Polygon p = new Polygon(5, Math.min(d.width, d.height));
p.draw(g);
Polygon p2 = new Polygon(5, Math.min(d.width, d.height));
p2.fill(g);
} // paint()
/**
* main() creates an instance of this class. Note the use of the anonymous
* WindowAdapter to manage closing of the top-level frame.
*/
public static void main (String argv[]) {
DrawFrame f = new DrawFrame("Polygon");
f.setSize(200, 200);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // DrawFrame
/*
* File: Drawable.java
* Author: Java, Java, Java
* Description: The Drawable interface defines two methods used for drawing
*
objects, the draw() and fill() methods.
*/
import java.awt.*;
public interface Drawable {
public abstract void draw(Graphics g);
public abstract void fill(Graphics g);
}//Drawable
22. Challenge: Design and implement a class that creates and renders three-dimensional
cubes, of varying size. The class should contain a constructor that takes a parameter that gives the length of the cubes side. Use the Drawable interface in your
design.
Design: The DrawableCube class is modeled after the DrawableRectangle class. It implements the Drawable interface. The draw() method draws
polygons representing the various faces of the cube as a wireframe image. The
fill() method fills the faces with color. As in the other interfaces, the drawing
takes place on a subclass of JPanel.
/*
* File: DrawableCube.java
* Author: Java, Java, Java
* Description: This class represents a drawable cube. It is
* subclass of Cube which implements the Drawable interface.
*/
import java.awt.*;
import java.awt.event.*;
345
346
Point
Point
Point
Point
Point
Point
Point
location;
topLeft;
bottomLeft;
topRight;
backLeft;
backRight;
backBottom;
// Default location
// Place the cube
// Calc location of corners
/**
* DrawableCube() constructor sets its initial location
* @param side -- an int giving the cubes dimensions
*/
public DrawableCube(int side) {
super(side);
location = new Point(60, 60);
}
/**
* draw() is part of the Drawable interface. It draws the outline
* of the cube by drawing three faces: the front face, the top
* face and the left face. The other three faces are hidden.
* @param g -- a reference to the Graphics context
*/
public void draw(Graphics g) {
location = new Point(60, 60);
setPoints();
g.drawRect(topLeft.x, topLeft.y, side, side);
347
348
/*
* File: DrawFrame.java
* Author: Java, Java, Java
* Description: This is the top-level frame for an application that
* draws three dimensional cubes give the cubes dimension which is
* input by the user.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DrawFrame extends JFrame implements ActionListener {
private DrawableCube cube;
private
ing canvas
private
private
private
// Draw-
/**
* DrawFrame() constructor sets the windows title by calling the
*
super constructor. It also creates the listener.
*/
public DrawFrame(String title) {
super(title);
sideField.addActionListener(this);
controls.add(prompt);
controls.add(sideField);
getContentPane().add(controls, "North");
getContentPane().add(canvas, "Center");
setSize(400, 400);
}
/**
* actionPerformed() is invoked whenever the user inputs a value
* for the cubes side. It instructs canvas to create a new cube
* and then repaints the frame.
*/
public void actionPerformed(ActionEvent e) {
canvas.setCube(Integer.parseInt(sideField.getText()));
repaint();
} // actionPerformed()
/**
* main() creates an instance of this class. Note the use of the anonymous
* WindowAdapter to manage closing of the top-level frame.
*/
349
350
/*
* File: Drawable.java
* Author: Java, Java, Java
* Description: The Drawable interface defines two methods used for drawing
*
objects, the draw() and fill() methods.
*/
import java.awt.*;
public interface Drawable {
public abstract void draw(Graphics g);
public abstract void fill(Graphics g);
}//Drawable
351
Exercise 10.8
Exercise 10.11
interface
ActionListener
JPanel
ThreeDShapes
+actionPerformed()
JPanel
PieChartGUI
PieChart
-chartSize : int
+PieChart()
+paintComponent(in g : Graphics)
+computeTotal(in arr : int[]) : int
+drawPieChart(in grades : int[])
+paintComponent(in g : Graphics)
+main()
Exercise 10.12
interface
ActionListener
JPanel
+PieChartGUI()
+actionPerformed(in e : ActionEvent)
+main(in args : String[])
+actionPerformed()
Uses
BarChartGUI
BarChart
-MAXBAR : int = 200
-SCALE : double = 0.75
-chartSize : int
+paintComponent(in g : Graphics)
+computeTotal(in arr : int[]) : int
+drawBarChart(in grades : int[])
Uses
Exercise 10.13
JPanel
Canvas
-message : String
-font : Font
+Canvas(in msg : String)
+setFont(in fontName : String, in fontSize : int)
+paintComponent(in g : Graphics)
Exercise 10.14
Uses
interface
ItemListener
JApplet
GraphGUI
-WIDTH : int = 450
-HEIGHT : int = 400
-graph : Graph
-inputs : JPanel
-linearPanel : JPanel
-quadPanel : JPanel
-inputs : JPanel
-controls : JPanel
-mField : JTextField
-bField : JTextField
-aQField : JTextField
-bQField : JTextField
-cQField : JTextField
-mPrompt : JLabel
-bPrompt : JLabel
-aQPrompt : JLabel
-bQPrompt : JLabel
-cQPrompt : JLabel
-linearButton : JButton
-quadButton : JButton
-clearButton : JButton
FontChooser
-fonts : JComboBox
-sizes : JComboBox
-controls : JPanel
-canvas : Canvas
-message : String
JFrame
+init()
+itemStateChanged(in e : ItemEvent)
interface
ActionListener
+actionPerformed()
Miscellaneous Types
JPanel
datatype
int[]
Graph
+Graph()
+paintComponent(in g : Graph)
+drawXYAxes(in g : Graph)
+graphLine(in m : double, in n : double)
+graphQuadratic(in a : double, in b : double, in c : double)
JTextField
datatype
JLabel[]
ItemEvent
Font
datatype
JTextField[]
JComboBox
ActionEvent
datatype
String[]
Uses
JLabel
Graphics
JButton
352
Exercise 10.15
Exercise 10.19
LogoApplet
interface
Drawable
JApplet
Rectangle
-logo : Image
#length : double
#width : double
+init()
+paint(in g : Graphics)
+draw(in g : Graphics)
+fill(in g : Graphics)
interface
Scalable
JApplet
interface
MouseListener
MouseClickGame
-WIDTH : int = 300
-HEIGHT : int = 300
-LEFT : int = 10
-TOP : int = 10
-SIZE : int = 10
-BORDER : int = 30
-backColor : Color = Color.gray
-lineColor : Color = Color.red
-mouse : Point
-target : Point
+init()
+paint(in g : Graphics)
+moveTarget()
+drawTarget()
+mouseMoved(in e : MouseEvent)
+mouseClicked(in e : MouseEvent)
+mouseEntered(in e : MouseEvent)
+mouseExited(in e : MouseEvent)
+mouseDragged(in e : MouseEvent)
+mousePressed(in e : MouseEvent)
+mouseReleased(in e : MouseEvent)
-location : Point
+DrawableRectangle(in l : double, in w : double)
+scale(in ratio : double)
+draw(in g : Graphics)
+fill(in g : Graphics)
Uses
JFrame
DrawFrame
Exercise 10.20
interface
Drawable
Rectangle
+draw(in g : Graphics)
+fill(in g : Graphics)
#length : double
#width : double
+Rectangle(in l : double, in w : double)
+calculateArea() : double
interface
Scalable
+scale(in ratio : double)
DrawableRectangle
Exercise 10.18
JApplet
interface
MouseMotionListener
interface
MouseListener
MouseHockeygame
-WIDTH : int = 300
-HEIGHT : int = 300
-LEFT : int = 10
-TOP : int = 10
-SIZE : int = 10
-BORDER : int = 30
-MAXSHOT : int = 25
-backColor : Color = Color.gray
-lineColor : Color = Color.red
-mouse : Point
-target : Point
+init()
+paint(in g : Graphics)
+initTarget()
+moveTarget(in deltax : int, in deltay : int)
+drawTarget(in deltax : int, in deltay : int)
+mouseClicked(in e : MouseEvent)
+mouseEntered(in e : MouseEvent)
+mouseExited(in e : MouseEvent)
+mouseMoved(in e : MouseEvent)
+mouseDragged(in e : MouseEvent)
+mousePressed(in e : MouseEvent)
+mouseReleased(in e : MouseEvent)
-location : Point
+DrawableRectangle(in l : double, in w : double, in loc : Point)
+setLocation(in p : Point)
+isClicked(in p : Point) : boolean
+scale(in ratio : double)
+draw(in g : Graphics)
+fill(in g : Graphics)
JFrame
DrawFrame
-mouse : Point
-rect : DrawableRectangle
-moving : boolean = true
+DrawFrame(in title : String)
+paint(in g : Graphics)
+mouseDragged(in e : MouseEvent)
+mousePressed(in e : MouseEvent)
+mouseEntered(in e : MouseEvent)
+mouseExited(in e : MouseEvent)
+mouseMoved(in e : MouseEvent)
+mouseClicked(in e : MouseEvent)
+mouseReleased(in e : MouseEvent)
+main(in argv : String[])
Miscellaneous Types
Uses
datatype
boolean
Graphics
Image
Point
MouseEvent
Color
datatype
String[]
353
Exercise 10.21
interface
Drawable
+draw(in g) : Graphics
+fill(in g) : Graphics
Object
Miscellaneous
Classes
JFrame
Graphics
Polygon
DrawFrame
-npoints : int = 0
-points : Point[]
Point
datatype
String[]
datatype
Point[]
datatype
boolean
Uses
ActionEvent
Exercise 10.22
JLabel
JTextField
interface
Drawable
Cube
+draw(in g) : Graphics
+fill(in g) : Graphics
JFrame
interface
ActionListener
DrawableCube
#location : Point
#topLeft : Point
#bottomLeft : Point
#topRight : Point
#backLeft : Point
#backRight : Point
#backBottom : Point
JPanel
DrawFrame
-cube : DrawableCube
-canvas : Canvas
-controls : JPanel
-sideField : JTextField
-prompt : JLabel
Canvas
-cube : DrawableCube
Uses
Chapter 11
(b) The only place that an exception can be thrown in a Java program is within
. Answer: try block
a
(c) The block of statements placed within a catch block are generally known
. Answer: exception handlers
as an
(d) To determine a statements
execution. Answer: dynamic
(e) To determine a statement
swer: static
(h) A
exception must be either caught or declared within the method in
which it might be thrown. Answer: checked
(i) An
3. Compare and contrast the four different ways of handling exceptions within a
program.
Answer: Generally, there are four ways to handle an exception: (1) Let Java
handle it. This way would be recommended if your handling of the exception
does not improve significantly upon Javas default handling of it. (2) Fix the
problem that led to the exception and resume the program. This approach is
warranted only if the error can be fixed and the program resumed, or in the case of
a failsafe program. (3) Report the problem and resume the program. This would
be the preferred technique for a failsafe program in which the detected error
cannot really be fixed. (4) Print an error message and terminate the program.
Most erroneous conditions reported by exceptions are difficult or impossible to
fix. This approach would usually be used during program development.
355
4. Suppose you have a program that asks the user to input a string of no more than
five letters. Describe the steps youd need to take in order to design a StringTooLongException to handle cases where the user types in too many characters.
Answer: Create a subclass of Exception named StringTooLongException. In the method that reads the users input, code a try..catch block.
If the user inputs a string longer than 5 letters, throw a StringTooLongException in the try portion and handle it in the catch class.
5. Exceptions require more computational overhead than normal processing. Explain.
Answer: When an exception is thrown, Java must suspend normal execution.
It was create some kind of data structure to store the programs state and then
locate and branch to the catch clause that handles the exception. All of this
requires time.
6. Suppose the following ExerciseExample program is currently executing the
if statement in method2(). Draw a picture of the method call stack
that represents this situation.
public class ExerciseExample {
public void method1(int M) {
try {
System.out.println("Entering try block");
method2(M);
System.out.println("Exiting try block");
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
} // method1()
public void method2(int M) {
if (M > 100)
throw new ArithmeticException(M + " is too large");
}
public static void main(String argv[]) {
ExerciseExample ex = new ExerciseExample();
ex.method1(500);
}
} // ExerciseExample
Answer: The method call stack would contain the following entries, from bottom to top:
main()
method1()
method2()
356
7. Repeat the previous exercise for the situation where the program is currently
executing the second println() statement in method1().
Answer: The method call stack would contain the following entries, from bottom to top:
main()
method1()
8. Draw a hierarchy chart that represents the static scoping relationships among the
elements of the ExerciseExample program.
ExerciseExample
|
-------------------------|
|
|
method1() method2()
main()
11. Consider again the ExerciseExample program. If the exception thrown were
Exception rather than ArithmeticException, explain why we would
get the following error message: java.lang.Exception must be caught,
or it must be declared....
Answer: An ArithmeticException is a subclass of RuntimeException and therefore it is an unchecked exception. Unchecked exceptions do not
have to be caught or declared in the methods in which they are thrown. On the
other hand, an Exception include subclasses that are checked exceptions, and
must therefore be caught or declared in method2().
12. Write a try/catch block which throws an Exception if the value of variable X is less than zero. The exception should be an instance of Exception
and when it is caught, the message returned by getMessage() should be ERROR: Negative value in X coordinate.
357
358
try {
if (X < 0)
throw new Exception("ERROR: Negative value in X coordinate");
} catch (Exception e) {
System.out.println("ERROR: " + e.getMessage());
}
13. Look at the IntFieldTester program and the IntField class definition.
Suppose the user inputs a value thats greater than 100. Show what the method
call stack would look like when the IntField.getInt() method is executing the num > bound expression.
The method call stack would keep track of the method calls leading
to the error. The getInt() method would be on the top:
Top: IntField.getInt()
IntFieldTester.actionPerformed()
IntFieldTester.main()
14. As a continuation of the previous exercise, show what the programs output
would be if the user output a value greater than 100.
java.lang.Exception.IntOutOfRangeException: The input value exceeds the bound 100
at IntField.getInt(IntField.java:25)
at IntFieldTester.actionPerformed(IntFieldTester.java:35)
at IntFieldTester.main(IntFieldTester.java:45)
15. As a continuation of the previous exercise, modify the IntOutOfRangeException handler so that it prints the message call stack. Then show what it
would print.
Answer: It would print what is shown in the previous exercise. The change to
IntOutOfRangeException would be to add a call to the printStackTrace() method.
public class IntOutOfRangeException extends Exception {
public IntOutOfRangeException(int Bound) {
super("The input value exceeds the bound " + Bound);
printStackTrace();
}
}
16. Define a subclass of RuntimeException named InvalidPasswordException, which contains two constructors. The first constructor takes no parameters and an exception thrown with this constructor should return ERROR:
359
invalid password when its getMessage() is invoked. The second constructor takes a single String parameter. Exceptions thrown with this constructor
should return the constructors argument when getMessage() is invoked.
/*
* File: InvalidPasswordException.java
* Author: Java, Java, Java
* Description: This Exception subclass is invoked when the
*
user inputs an invalid password.
*/
public class InvalidPasswordException extends Exception {
public InvalidPasswordException() {
super("Error: invalid password");
}
public InvalidPasswordException(String s) {
super(s);
}
}
17. Extend the IntField class so that it will constrain the integer JTextField
to an int between both a lower and upper bound. In other words, it should
throw an exception if the user types in a value lower than the lower bound or
greater than the upper bound.
/*
* File: IntField.java
* Author: Java, Java, Java
* Description: This version of IntField has both an upper and lower bound
* associated with it. The user must type a number within these bounds
* into the field. A programmer defined exception, IntOutOfRangeException, is
* thrown if the bound is exceeded.
* Note that upperBound and lowerBound are set initially to MAX and MIN possible
* values respectively. This allows the field to accept any numeric input if
* its first constructor is used.
*/
import javax.swing.*;
public class IntField extends JTextField {
private int upperBound = Integer.MAX_VALUE;
private int lowerBound = Integer.MIN_VALUE;
/**
* IntField() constructor merely invokes its superclass
360
18. Modify the ColorPicker program presented in the last chapter so that its
JTextFields will restrict user inputs to values between 0 and 255. Use the
extended IntField class that you defined in the previous exercise.
/*
*
*
*
*
*
*
File: ColorPicker.java
Author: Java, Java, Java
Description: This Swing applet illustrates the use of the
java.awt.Color class. It lets the user type red, green and
blue (RGB) values into text fields, and displays the resulting
color both as a font color and as a colored rectangle.
*
*
*
*
*
*
*/
361
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ColorPicker extends JApplet implements ActionListener {
private IntField redIn, greenIn, blueIn;
private JLabel R = new JLabel("R:"),
G = new JLabel("G:"),
B = new JLabel("B:");
private JPanel controls = new JPanel();
private Canvas canvas = new Canvas();
/**
* init() sets up the applets interface. A (default) border layout
*
is used, with the controls at the north and the drawing canvas
*
in the center.
*/
public void init() {
initControls();
getContentPane().add(controls, "North");
getContentPane().add(canvas, "Center");
canvas.setBorder(BorderFactory.createTitledBorder("The Color Display"));
getContentPane().setBackground(Color.white);
setSize(250,200);
} // init()
/**
* initControls() arranges the applets control components in a separate
*
JPanel, which is placed at the north border. The controls consist of
*
three JTextFields into which the user can type RGB values.
*/
private void initControls() {
redIn = new IntField(4, 0, 255);
// Create 3 integer textfields
greenIn = new IntField(4, 0, 255);
// that accept values between
blueIn = new IntField(4, 0, 255);
// 0 and 255
redIn.setText("128");
// And set their ini-
362
19. Design Issue: One of the preconditions for the bubbleSort() method (Text
Figure 8-16) is that its array parameter not be null. Of course this precondition
would fail if the array were passed a null array reference. In that case Java
would throw a NullPointerException and terminate the program. Is this
an appropriate way to handle that exception?
Answer: It is appropriate to terminate the program in this case because it is
363
not clear how the program could recover from this error. The program should
be modified to so that it checks that the array reference is not null before calling
bubbleSort().
20. With respect to the previous exercise, suppose you decide that it is more appropriate to handle the NullPointerException by presenting an error dialog.
Modify the method to accommodate this behavior.
/*
* File: Sort.java
* Author: Java, Java, Java
* Description: This class implements the Bubble Sort
*
algorithm. This version makes Sort a subclass of JFrame
*
thereby giving it a simple GUI interface. This is necessary
*
in order to open a message dialog when a NullPointerException
*
is thrown in main().
*
* Note: This example is somewhat contrived, but it illustrates
*
the separation of exception handling from exception throwing,
*
and for a GUI application, the best way to report an exception
*
is to use some kind of message dialog.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Sort extends JFrame {
/**
* bubbleSort() sorts the values in arr into ascending order
* Pre: arr is not null.
* Post: The values arr[0]...arr[arr.length-1] will be
* arranged in ascending order.
*/
public void bubbleSort(int arr[]) {
if (arr == null)
throw new NullPointerException("ERROR: bubbleSort() parameter is null");
int temp;
// Temporary variable for swap
for (int pass = 1; pass < arr.length; pass++)
// For each pass
for (int pair = 1; pair < arr.length; pair++) // For each pair
if (arr[pair-1] > arr[pair]) {
//
Compare
temp = arr[pair-1];
//
and swap
arr[pair-1] = arr[pair];
arr[pair] = temp;
} // if
364
} // bubbleSort()
/**
* print() prints the values in an array
* @param arr -- an array of integers
*/
public void print(int arr[]) {
for (int k = 0; k < arr.length; k++)
System.out.print( arr[k] + " \t ");
System.out.println();
} // print()
/**
* main() creates an instance of this (Sort) class and sets
*
the size and visibility of its JFrame.
* An anonymous class is used to create an instance of the
*
WindowListener class, which handles the window close events
*
for the application.
*/
public static void main(String args[]) {
Sort sorter = new Sort();
int intArr[] = { 21, 20, 27, 24, 19 };
try {
sorter.setSize(400, 300);
sorter.setVisible(true);
sorter.addWindowListener(new WindowAdapter() {
// Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
sorter.print(intArr);
sorter.bubbleSort(intArr);
sorter.print(intArr);
} catch (Exception e) {
JOptionPane.showMessageDialog(sorter,"bubbleSort() was passed a null array");
}
} // main()
} //Sort
365
/**
* CyberPet(str, inState) initializes the pets name and state. Note that
*
this version throws the InvalidPetStateException if the inState is
*
invalid. The exception just prints an error and leaves the pets state
*
set to its default value.
* @param str -- a string giving pets name
* @param inState -- an int giving the pets state
*/
public CyberPet(String str, int inState) { // Constructor #3
try {
if (inState < 0 || inState > MAXSTATENO)
throw new InvalidPetStateException(inState);
petState = inState;
} catch (InvalidPetStateException e) {
System.out.println(e.getMessage());
petState = EATING;
} finally {
name = str;
}
}
23. CyberPet Challenge: One of the problems with the animated CyberPet applet
366
(Text Figure 8-14) is that if the image files are missing from the applets directory, the applet will continue to run but no images will show up. First, convert the
applet from an AWT program to a Swing program. Then design and implement
a way to use exceptions to handle this problem. What kind of exception will you
throw? Where and how will you detect it? If an exeption is thrown, open an error
dialog and inform the user.
Design: If the applet fails to load a designated image file, the reference to the
loaded image will be null. Therefore the program should throw a NullPointerException in the init() method.
/*
*
*
*
*
*
*
*
*
*
*
*
*
*/
File: AnimatedCyberPet.java
Author: Java, Java, Java
Description: This applet provides a Graphical User
Interface for the CyberPet class. It animates the
CyberPets eating actions by looping through a
set sequence of images. The images simulate the pet
chewing its food.
This version throws a NullPointerException if one or
more of the image files cannot be opened. It handles the
exception by reporting an error message and then stopping
the applet. See init() for details.
import
import
import
import
java.applet.*;
java.awt.*;
java.awt.event.*;
javax.swing.*;
367
368
busyWait(PAUSE);
g.drawImage(eat2Img, 20, 100, this);
busyWait(PAUSE);
}
g.drawImage(happyImg, 20, 100, this);
} // doEatAnimation()
/**
* busyWait() -- loops through N iterations, doing nothing. This is
*
called "busy waiting" because nothing else can be done while the
*
program is looping in this method.
* @param N -- the wait loop bound
*/
private void busyWait(int N) {
for (int k = 0; k < N; k++) ;
// Empty for body -- does nothing
} // busyWait()
/**
* actionPerformed() -- handles the applets action events
* @param e -- the ActionEvent the caused this method to be invoked
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == eatButton)
pet1.eat();
else if (e.getSource() == sleepButton)
pet1.sleep();
stateField.setText(pet1.getState());
repaint();
} // actionPerformed()
} // AnimatedCyberPet
Exercise 11.16
369
Exercise 11.17
Exercise 11.20
JTextField
RuntimeException
JFrame
IntField
InvalidPasswordException
+InvalidPasswordException()
+InvalidPasswordException(in s : String)
Sort
Throws
IntOutOfRangeException
Exercise 11.18
JApplet
interface
ActionListener
Exercise 11.23
Exercise 11.21
+actionPerformed()
+init()
interface
ActionListener
JApplet
Exception
+actionPerformed()
+init()
ColorPicker
InvalidPetStateException
Uses
-redIn : IntField
-greenIn : IntField
-blueIn : IntField
-canvas : Canvas
-controls : JPanel
Canvas
+InvalidPetStateException(in n : int)
AnimatedCyberPet
Uses
+init()
-initControls()
+actionPerformed()
IntField
IntOutOfRangeException
Uses
CyberPet
Miscellaneous
Classes
datatype
int[]
Image
JButton
NullPointerException
JPanel
Graphics
JTextField
Chapter 12
371
containing information about that method call is placed on the top of method
call stack. Among other things the information on the stack includes the method
calls arguments, local variables, and the address to which the program should
return when the method call is finished. A stack is a last-in-first-out structure, so
the last method called will be on the top of the stack and will be the first block
removed from the stack when a return statement is executed. When a return is
executed, the return address is retrieved from the top block on the method call
stack, and then that block is removed from the stack.
3. Why is a recursive algorithm generally less efficient than an iterative algorithm?
Answer: Recursive algorithms use method calls to effect repetition. A loop,
such as a for loop, does not. Method calls involve more computational overhead
than a for loop, because an block representing the method call must be placed
on the method call stack. This causes recursive algorithms to be somewhat less
efficient than iterative ones.
4. A tree, such as a maple tree or pine tree, has a recursive structure. Describe how
a trees structure displays self-similarity and divisibility.
Answer: The tree can be divided into branches (divisibility) each of which has
the same general structure and appearance as the tree itself (self-similarity).
5. Write a recursive method to print each element of an array of double.
/**
* print() prints each element of the array dArr starting at first. To
* print the array named myArray, you would call this method with:
*
print(myArr, 0);
* Algorithm: In addition to the array parameter we need a second
* parameter to keep track of the recursion. So first will start
* at 0 and increment on each recursive call until it reaches dArr.length.
* @param dArr -- the array of double to be printed
* @param first -- the index of the first element to be printed
* Pre: 0 <= first <= dArr.length -1
* Post: none
*/
public void print (double dArr[], int first) {
if (first != dArr.length) {
System.out.print(dArr[first] + " ");
print(dArr, first + 1);
// Recursive case
}
else
System.out.println();
// Base case
}
6. Write a recursive method to print each element of an array of double, from the
last to the first element.
372
/**
* printRev() prints each element of the array dArr starting at last. To
* print the array named myArray, you would call this method with:
*
print(myArr, myArr.length-1);
* Algorithm: In addition to the array parameter we need a second
* parameter to keep track of the recursion. So last will start
* at dArr.length-1 and decrement on each recursive call until it reaches 0.
* @param dArr -- the array of double to be printed
* @param last -- the index of the last element to be printed
* Pre: 0 <= last <= dArr.length -1
* Post: none
*/
public void printRev (double dArr[], int last) {
if (last >= 0) {
System.out.print(dArr[last] + " ");
printRev(dArr, last - 1);
// Recursive case
}
else
System.out.println();
// Base case
}
7. Write a recursive method that will concatenate the elements of an array of String
into a single String delimited by blanks.
/**
* concat() concatenates each element of the array strArr into a single
* string. To call it, use: concat(myStrArr, 0);
* Algorithm: In addition to the array parameter we need a second
* parameter to keep track of the recursion. So first will start
* at 0 and increment on each recursive call until it reaches strArr.length.
* @param strArr -- the array of strings to be concatenated
* @param first -- the index of the first element to be concatenated
* Pre: 0 <= first <= dArr.length -1
* Post: none
*/
public String concat (String strArr[], int first) {
if (first != strArr.length) {
// recursive case
return strArr[first] + " " + concat(strArr,first + 1);
}
else
return " ";
// base case
}
0, and
373
0 and prints
/**
* printEvens() prints the even numbers between N and 0
* Algorithm: The parameter N serves as the starting point
* of the sequence, which is bounded by 0. N is decremented
* on each recursion.
* @param N -- the starting point of the sequence
* Pre: N >= 0
* Post: none
*/
public void printEvens (int N) {
if (N < 0 )
System.out.println();
// base case
else if (N % 2 == 0) {
System.out.print(N + " ");
printEvens(N - 1);
// recursive case
} else
printEvens(N - 1);
// recursive case
} // printEvens()
0 and prints
/**
* printTens() prints the multiples of 10 between 0 and N. Call this
* method with: printTens(20);
* Algorithm: The sequence starts at 0 and is bounded by the parameter N.
* N is decremented on each recursion. However, in order to print
374
*
*
#
# #
# # #
# # # #
/**
* printPattern1() prints a triangular pattern that consists of 1
* asterisk in the first row, 2 in the second, 3 in the third, and
* so on, with all lines left justified. The parameter N determines
* the number of rows and the number of asterisks per row.
* Algorithm: In order to print 1 asterisk in the first row, we have
* recurse down until N is 1, then start printing. The rows with 2, 3
* and more asterisks will be printed after the row with 1, because they
* recursion behaves in a last-in-first-out fashion. Note that we use
* a for loop to print the asterisks themselves.
* @param N -- the number of rows in the pattern
* Pre: N >= 0
* Post: none
*/
public void printPattern1 (int N) {
if (N <= 0)
return;
// Base case
else {
printPattern1(N-1);
// Recursive case
for (int j = 0; j < N; j++) // Note: print after recursion
System.out.print("# ");
System.out.println();
375
}
} // printPattern1()
Pattern 2
---------------
Pattern3
---------------
# # # #
# # #
# #
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
# # # #
# # #
# #
#
/**
* printPattern2() prints a triangular pattern that consists of N
* asterisks in the first row, N-1 in the second, and so on down to
* to 1 asterisk in the Nth row, with all rows right justified.
* Algorithm: In this case printing precedes the recursive call.
* But the K parameter controls the recursion, which is bounded when
* K > N. K determines what row it is and how many leading spaces to print.
* For loops are used to print the spaces and asterisks.
* @param K -- the number of spaces in each row
* @param N -- the number of rows in the pattern and number # per row
* Pre: N >= 0 and 0 < K <= N
* Post: none
*/
public void printPattern2 (int K, int N) {
if (K > N)
return;
// Base case
else {
// Recursive case
for (int j = 1; j < K; j++)
System.out.print(" ");
// Print leading spaces
for (int j = K; j <= N; j++)
System.out.print("# ");
// Print #s
System.out.println();
printPattern2(K+1, N);
}
} // printPattern2()
/**
* printPattern3() prints a triangular pattern that consists of N
376
14. Write a recursive method to compute the sum of grades stored in an array.
377
/**
* sum() computes the sum of the values in an array of double.
* Algorithm: In addition to the array parameter we need a length
* parameter to keep track of the recursion. The array is summed
* from last down to first. Recursion stops when length == 0.
* @param array -- the array of double to be summed
* @param length -- the length of the array
* @return -- a double equal to the sum of the elements of array
* Pre: 0 <= length <= array.length -1
* Post: The return value equals the sum of the array elements
*/
public double sum(double array[], int length) {
if (length == 0)
// Base case
return 0;
else
return array[length-1] + sum(array,length - 1);
} // sum()
15. Write a recursive method to count the occurrences of a substring within a string.
/**
* countSubStrs() counts the occurrences of substr in str starting at N.
* Algorithm: Use str.indexOf(substr, N) to determine if str contains substr,
* Ns new value on each recursion is 1 + str.indexOf(substr, N). Note
* that there are two base cases, one when N runs off the end of the string
* and two when there are no further occurrences of substr.
* @param substr -- the substring to be counted
* @param str -- the string to be searched
* @param N -- the starting location in the str, should initially be 0
*
*/
public int countSubStrs(String substr, String str, int N) {
if (N >= str.length())
return 0;
// Base case, end of str
else if (str.indexOf(substr, N) == -1)
return 0;
// Base case, no more substr
else
// Recursive case
return 1 + countSubStrs(substr, str, str.indexOf(substr, N) + 1);
} // countSubStrs()
16. Write a recursive method to remove the HTML tags from a string.
/**
* removeHTML() removes all HTML tags from its parameter, where an HTML tag
* is any sequence of characters between < and > .
* Algorithm: Use indexOf() to find the HTML tag. If there are none, return
378
* the original string. If one is found, remove it and return the resulting string.
* A new value of str is passed on to the next level of recursion, which is stopped
* when the parameter has no HTML tags.
* @param str -- the string to be searched for HTML tags
* PRE: If str contains a <, it contains a matching >
* POST: The result contains no HTML tags.
*/
public String removeHTML(String str) {
int p1 = str.indexOf("<");
int p2 = str.indexOf(">");
if (p1 == -1)
return str;
else {
String tempS = str.substring(0,p1) + str.substring(p2 + 1);
return removeHTML(tempS);
}
} // removeHTML()
379
//
Perform cae-
sar shift
return ch + encode(word.substring(1)); //
}
} // encode()
/*
* decode(String word) --- performs a reverse Caesar
* shift on word where the shift is fixed at 3.
* Pre: word != NULL
* Post: each letter in word has been shifted by 26-3
*/
public String decode(String word) {
if (word.length() == 0)
return "";
// Base case
else {
char ch = word.charAt(0);
// Get the first character
ch = (char)(a + (ch - a + 23) % 26); // Perform reverse caesar shift
return ch + decode(word.substring(1));
// Do rest of the word
}
} // decode()
} // Caesar
18. The Fibonacci sequence (named after the Italian mathematician Leonardo of
Pisa, ca. 1200) consists of the numbers 0,1,1,2,3,5,8,13,... in which
each number (except for the first two) is the sum of the two preceding numbers. Write a recursive method fibonacci(N) that prints the Nth Fibonacci
number.
/*
* File: Fibonacci.java
* Author: Java, Java, Java
* Description: The Fibonacci sequence (named after the Italian mathematician
* Leonardo of Pisa, ca. 1200) consists of the numbers 0,1,1,2,3,5,8,13,...
* Each number (except for the first two) is the sum of the two preceding
* numbers. Write a recursive method fibonacci(N) that prints the
* Nth Fibonacci number.
*/
public class Fibonacci {
/**
* fibonacci() returns the first Nth Fibonacci number
* @param N -- the index in the fibonacci sequence
* @return -- the Nth value in the sequence
*/
public int fibonacci(int N) {
380
if (N == 0 || N == 1)
return N;
else
return fibonacci(N - 1) + fibonacci(N - 2);
} // fibonacci()
/**
* main() creates an instance of this class and tests its fibonacci()
* method on values from 0 to 20
*/
public static void main(String argv[]) {
Fibonacci tester = new Fibonacci();
for (int k = 0; k <= 20; k++)
System.out.println("The " + k + "th Fibonacci number is " + tester.fibonacci(k));
} // main()
} // Fibonacci
19. Write a recursive method to rotate a String by N characters to the right. For
example, rotateR("hello", 3) should return llohe.
/*
* File: Rotater.java
* Author: Java, Java, Java
* Description: This class implements methods to rotate strings.
*/
public class Rotater {
/**
* rotateR() rotates its string parameter N characters to the right
* Algorithm: Each level of recursion rotates by 1 character. To
* rotate right, take the last character, "o", and concatenate to the
* left of the first four, "hell", giving "ohell".
* @param s -- the String to be rotated -- e.g., hello
* @param N -- the number of rotations
-- e.g., 3
* @return -- the rotated string
-- e.g., llohe
*/
public String rotateR(String s, int n) {
if (n <= 0)
return s;
else
return rotateR( s.substring(s.length()-1) + s.substring(0,s.length()1), n - 1 );
} // rotateR()
/**
381
20. Write a recursive method to rotate a String by N characters to the left. For
example, rotateL("hello", 3) should return lohel.
Answer: See the previous answer.
21. Write a recursive method to convert a String representing a binary number
to its decimal equivalent. For example, binTodecimal("101011") should
return the int value 43.
/*
* binToDecimal() takes a string of bits "101011" and treats it
* like a binary number, converting it to its decimal equivalent.
* Algorithm: The bit string is processed from right to left. It
* uses the fact that 11001 which equals 25 is equivalent to
* 1 + 2 * 12, that is it is the rightmost bit plus twice the
* value of the remaining leftmost bits (1100 which is decimal 12).
* @param bitString -- a String of 0s and 1s
* @return -- an int giving the decimal value of bitString
382
22. A palindrome is a string that is equal to its reverse mom, i, radar and
able was i ere i saw elba. Write a recursive boolean method that determines
whether its String parameter is a palindrome.
/*
* File: Palindrome.java
* Author: Java, Java, Java
* Description: This class tests whether strings are palindromes. A
* palindrome is a string that is spelled the same backwards and
* forwards. Examples: radar, mom, i, dad, maam, able was i ere i saw elba.
*/
public class Palindrome {
/**
* isPalindrome() returns true if its parameter is a palindrome
* @param s -- a string to test
* @return -- boolean true if s is a palindrome
*/
public boolean isPalindrome(String s) {
return s.equals(reverse(s)); // Just compare with its reverse
}
/**
* reverse() reverses its string parameter
* @param s -- the string to be reversed
* @return a string giving s in reverse order
* Pre: s != null
* Post: reverse(s) = the characters of s in reverse order
*/
public String reverse(String s) {
if (s.length() <= 1)
// Base case
383
return s;
else
return reverse( s.substring(1)) + s.charAt(0); // Recursive case
}
/**
* main() creates an instance of this class and tests its isPalindrome()
* method on several strings.
*/
public static void main(String argv[]) {
Palindrome tester = new Palindrome();
if (tester.isPalindrome("mama"))
System.out.println("mama is a palindrome");
else
System.out.println("mama is a NOT palindrome");
if (tester.isPalindrome("radar"))
System.out.println("radar is a palindrome");
else
System.out.println("radar is a NOT palindrome");
if (tester.isPalindrome("able was i ere i saw elba"))
System.out.println("able was i ere i saw elba is a palindrome");
else
System.out.println("able was i ere i saw elba is a NOT palindrome");
} // main()
} // Palindrome
23. Challenge: Incorporate a drawBinaryTree() method into the RecursivePatterns program. A level-1 binary tree has two branches. At each
subsequent level, two smaller branches are grown from the endpoints of every
existing branch. The geometry is easier if you use 45 degree angles for the
branches. The following figure shows a level-4 binary tree drawn upside down.
Answer: In general, the following set of instructions can be used to draw a
basic binary tree:
Draw the trunk
Draw a smaller left subtree
Draw a smaller right subtree
The idea here is that the left and right subtrees are just smaller versions of the tree
itself. That is where the recursion comes in. As in our other recursive graphics
we use parameters to control the location and size of the drawing, and the number
of levels of recursion.
For a binary tree, all of these parameters must change in value at each level of
recursion. The level decreases by 1. It is bounded by 0. The size will become
half the original size at every level. The location of the level k-1 subtrees will
be at the ends of the branches of the level k subtree. This leads to the following
definition of the drawBinaryTree() method:
384
385
/**
* drawBinaryTree() draws a Binary Tree recursively
* @param g -- graphics object
* @param level -- the number of levels of recursion
* @param p -- the reference Point (location) of the pattern
* @param h -- the height of the Tree
* Description: Draw two branches. Then if the recursion
* level is > 0, draw two binary trees with height h/2, one from the
* end of the left branch and one from the end of the right branch.
*/
void drawBinaryTree(Graphics g, Point p, int h, int level) {
g.drawLine(p.x, p.y, p.x - h, p.y + h); // No matter what level, draw two branches
g.drawLine(p.x, p.y, p.x + h, p.y + h);
if (level > 0) {
Point newP1 = newPoint(p.x - h, p.y
Point newP2 = newPoint(p.x + h, p.y
drawBinaryTree(g, newP1, h/2, level
drawBinaryTree(g, newP2, h/2, level
}
} // drawBinaryTree
+
+
-
h);
h);
1); // draw 1/2 size tree at branch end
1); // draw 1/2 size tree at branch end
To modify the Recursive Patterns project (from Chapter 12), the drawBinaryTree() method should be added to the Canvas.java class. In addition to the method itself, you should define new class constants to give the
initial size and location of the tree, and you must modify the paintComponent() method which calls the new method. You must also modify RecursivePatterns.java, adding the new pattern as a choice box menu item.
These changes are shown below:
/*
* File: Canvas.java
* Author: Java, Java, Java
* Description: This subclass of JPanel performs all
* the drawing functions for the RecursivePatterns applet.
* Whenever the user selects a pattern, the applet invokes
* the setPattern() method and then calls its repaint()
* method. Since the Canvas is contained within the applet,
* it too will be repainted, by its paintComponent() method,
* which draws the currently selected pattern.
*/
import javax.swing.*;
import java.awt.*;
public class Canvas extends JPanel {
public static final int WIDTH=400, HEIGHT=400;
private final int HBOX=10, VBOX=50, BOXSIDE=200, BOXDELTA=10;
private final int HTREE=200, VTREE=50, TREEHGT = 100;
386
// Ini-
// Cur-
/**
* Canvas() constructor sets its size
*/
public Canvas() {
setSize(WIDTH, HEIGHT);
}
/**
* setPattern() is invoked by the applet to set the
*
current drawing pattern and level
* @param pat -- the pattern to be drawn
* @param lev -- the number of levels of recursion
*/
public void setPattern(int pat, int lev) {
pattern = pat;
level = lev;
}
/**
* paintComponent() is invoked automatically whenever the Canvas
*
needs to be painted -- e.g., when its containing applet is painted
* @param g -- the Canvas graphics object.
*/
public void paintComponent(Graphics g) {
g.setColor(getBackground());
// Redraw the panels background
g.drawRect(0, 0, WIDTH, HEIGHT);
g.setColor(getForeground());
switch (pattern) {
case 0:
drawGasket(g, level, gasketP1, gasketP2, gasketP3 );
break;
case 1:
drawBoxes(g, level, new Point(HBOX, VBOX), BOXSIDE, BOXDELTA );
break;
case 2:
drawBinaryTree(g, level, new Point(HTREE, VTREE), TREEHGT);
break;
} // switch
} // paintComponent()
387
/**
* drawGasket() --- recursively draws the Sierpinski gasket pattern,
* with points p1, p2, p3, representing the vertices of its enclosing triangle.
* @param p1 -- a Point representing 1 vertex of the enclosing triangle
* @param p2 -- a second Point of the enclosing triangle
* @param p3 -- a third Point of the enclosing triangle
* @param level (>= 0) is the recursion parameter (base case: level 0)
*/
private void drawGasket(Graphics g, int lev, Point p1, Point p2, Point p3) {
g.drawLine(p1.x, p1.y, p2.x, p2.y); // Draw a triangle
g.drawLine(p2.x, p2.y, p3.x, p3.y);
g.drawLine(p3.x, p3.y, p1.x, p1.y);
if (lev > 0) {
// If more divisions desired, draw 3 smaller gaskets
Point midP1P2 = new Point( (p1.x + p2.x) / 2, (p1.y + p2.y) / 2 );
Point midP1P3 = new Point( (p1.x + p3.x) / 2, (p1.y + p3.y) / 2 );
Point midP2P3 = new Point( (p2.x + p3.x) / 2, (p2.y + p3.y) / 2 );
drawGasket(g, lev - 1, p1, midP1P2, midP1P3);
drawGasket(g, lev - 1, p2, midP1P2, midP2P3);
drawGasket(g, lev - 1, p3, midP1P3, midP2P3);
}
} // drawGasket()
/**
* drawBoxes() --- recursively draws a pattern of nested squares with loc
* as the top left corner of outer square and side being the length squares side.
* @param loc is the top-left Point of the outer square
* @param side is the length of the squares side
* @param level (>= 0) is the recursion parameter (base case: level 0)
* @param delta is the amount by which the side is adjusted at each level
*/
private void drawBoxes(Graphics g, int level, Point loc, int side, int delta) {
g.drawRect(loc.x, loc.y, side, side );
if (level > 0) {
Point newLoc = new Point( loc.x + delta, loc.y + delta);
drawBoxes(g, level - 1, newLoc, side - 2 * delta, delta);
}
} // drawBoxes()
/**
* drawBinaryTree() draws a Binary Tree recursively
* @param g -- graphics object
* @param level -- the number of levels of recursion
* @param loc -- the reference Point (location) of the pattern
* @param h -- the height of the Tree
* Description: Draw two branches. Then if the recursion
* level is > 0, draw two binary trees with height h/2, one from the
* end of the left branch and one from the end of the right branch.
388
*/
void drawBinaryTree(Graphics g, int level, Point loc, int h) {
g.drawLine(loc.x, loc.y, loc.x - h, loc.y + h); // No matter what level, draw two branches
levels.addItem(k + "" );
patterns.setSelectedItem(choices[0]);
ize the menus
levels.setSelectedItem("4");
389
// Initial-
canvas.setBorder(BorderFactory.createTitledBorder("Drawing Canvas"));
controls.add(levels);
// Control panel for menus
controls.add(patterns);
getContentPane().add(controls,"North");
// Add the controls
getContentPane().add(canvas,"Center");
// And the drawing panel
levels.addItemListener( this );
// Register the menus with a listener
patterns.addItemListener( this );
setSize(canvas.WIDTH,canvas.HEIGHT+controls.getSize().width);
} // init()
/**
* itemStateChanged() is the only method of the ItemListener interface.
* It is invoked whenever the user makes a selection in a JComboBox.
* In this case the selections from both JComboBoxes are passed along
* to canvas.setPattern(). Repainting the applet causes all of its
* contained components to be repainted, including the canvas.
* @param e -- the ItemEvent that describes the users selection.
*/
public void itemStateChanged(ItemEvent e) {
canvas.setPattern(patterns.getSelectedIndex(), levels.getSelectedIndex());
repaint();
// Repaint the applet
} // itemStateChanged()
} // RecursivePatterns
24. Challenge: Towers of Hanoi. According to legend, some Buddhist monks were
given the task of moving 64 golden disks from one diamond needle to another
needle, using a third needle as a backup. To begin with, the disks were stacked
one on top of the other, from largest to smallest (Text Figure 12-35). The rules
were that only one disk can be moved at a time, and that a larger disk can never
go on top of a smaller one. The end of the world was supposed to occur when
the monks finished the task!
Write a recursive method, move(int N, char A, char B, char C),
that will print out directions the monks can use to solve the Towers of Hanoi
problem. For example, heres what it should output for the three-disk case,
move(3,A,B,C:
Move
Move
Move
Move
Move
1
1
1
1
1
disk
disk
disk
disk
disk
from
from
from
from
from
A
A
B
A
C
to
to
to
to
to
B.
C.
C.
B.
A.
390
391
Exercise 12.17
Miscellaneous
Clases
Cipher
Point
Graphics
datatype
String[]
Ceasar
JComboBox
ItemEvent
JPanel
Exercise 12.23
Canvas
interface
ItemListener
JApplet
RecursivePatterns
-choices : String[]
-patterns : JComboBox
-levels : JComboBox
-canvas : Canvas
-controls : JPanel
+init()
+itemStateChanged(in e : ItemEvent)
Chapter 13
393
(b) A method that should not be interrupted during its execution is known as a
. Answer: synchronized method
(c) The scheduling algorithm in which each thread gets an equal portion of the
CPUs time is known as
. Answer: round-robin scheduling
(d) The scheduling algorithm in which some threads can preempt other threads
. Answer: priority scheduling
is known as
(e) A
is a mechanism that enforces mutually exclusive access to a synchronized method. Answer: monitor
(f) A thread that performs an I/O operation may be forced into the
until the operation is completed. Answer: blocked
state
6. Whats the difference between a thread in the sleep state and a thread in the ready
state?
Answer: In the sleep state a thread has voluntarily given up the CPU for a fixed
quantum of time. It cannot be ready to run again until its sleep time has expired.
A thread in the ready state is just waiting to get its turn on the CPU.
7. Deadlock is a situation that occurs when one thread is holding a resource that
another thread is waiting for, while the other thread is holding a resource that
the first thread is waiting for. Describe how deadlock can occur at a four-way
intersection, with cars entering the intersection from each branch. How can it be
avoided?
Answer: Imagine that one car from each of the four directions enters the intersection with the result that the north car is blocking the east car from proceeding, the east car is blocking the south car from proceeding, and so on. This is
deadlock. Each car is holding a resource (a piece of the road) while waiting for
another car to give up a resource (another piece of the road). No car can proceed
until the deadlock is broken. To avoid deadlock, cars should avoid entering the
intersection until it is clear.
8. Starvation can occur is one thread is repeatedly preempted by other threads.
Describe how starvation can occur at a four-way intersection and how it can be
avoided.
Answer: Suppose that the north car must always yield to oncoming traffic
from both the west and east. If traffic is heavy, the north car could be prevented
from proceeding. This would cause starvation in the sense that the north car
would never get the desired resource (the road). To avoid starvation, cars in the
oncoming traffic should yield to the side street occasionally, either because of a
stop light or because of courtesy.
9. Use the Runnable interface to define a thread that repeatedly generates random
numbers in the interval 2 through 12.
/*
* File: RandomNumbers.java
* Author: Java, Java, Java
* Description: This class implements the Runnable
* interface, which consists of the run() method.
* Implementing the Runnable interface is a way to
* turn an existing class into a separate thread.
*/
public class RandomNumbers implements Runnable {
/**
* run() is the threads primary method. It generates a
* random number between 2 and 12
*/
public void run() {
394
395
while (true)
// Infinite loop
System.out.println(2 + (int)(Math.random() * 11));
} // run()
} // RandomNumbers
10. Use the Runnable interface to convert CyberPet into a thread. For its run()
method, have the CyberPet alternate endlessly between eating, sleeping, and
thinking.
/*
* File: CyberPet.java
* Author: Java, Java, Java
* Description: This version of the CyberPet class uses the int
* type to represent the CyberPets state. This makes it easier
* incorporate new states into the model, since each state can
* can be given a distinct integer value. It also simplifies the
* access methods, which can now just assign the appropriate value
* to the state variable. Theres less chance of logical inconsistencies.
* Note the use of class constants, EATING, SLEEPING, THINKING, to
* represent different states.
* This version of CyberPet implements the Runnable interface. So
*
it operates as an independent thread.
*/
public class CyberPet implements Runnable {
public static final int EATING = 0;
// Class constants
public static final int SLEEPING = 1;
public static final int THINKING = 2;
private int petState;
private String name;
// Instance variables
/**
* CyberPet() initializes the pets state to EATING
*/
public CyberPet() {
// Constructor #1
name = "no name";
petState = EATING;
}
/**
* CyberPet(str) initializes the pets name
* @param str -- a string giving pets name
*/
public CyberPet(String str) { // Constructor #2
name = str;
petState = EATING;
}
/**
* CyberPet(str, inState) initializes the pets name and state
* @param str -- a string giving pets name
* @param inState -- an int giving the pets state
*/
public CyberPet(String str, int inState) { // Constructor #3
name = str;
petState = inState;
}
/**
* CyberPet(str, sleeping) preserves backward compatibility
* with previous versions of CyberPet by taking a boolean parameter
* representing the pets state.
* @param str -- a string giving the pets name
* @param sleeping -- a boolean set to SLEEPING (true) or EATING (false)
*/
public CyberPet(String str, boolean sleeping) { // Constructor #4
name = str;
if (sleeping == true)
petState = SLEEPING;
else
petState = EATING;
}
/**
* setName() sets the CyberPets name.
* @param str -- a string giving the pets name
*/
public void setName(String str) {
name = str;
} // setName()
/**
* getName() returns the CyberPets name.
* @return -- a string giving the CyberPets name
*/
public String getName() {
return name;
} // getName()
/**
* eat() sets the pets state to EATING
*/
396
397
Thread.sleep(1000);
} catch (InterruptedException e) {
}
} // while
} // run()
} // CyberPet
/*
* File: TestCyberPet.java
* Author: Java, Java, Java
* Description: This class provides an interface to the
* runnable CyberPet class.
*/
public class TestCyberPet {
public static void main(String args[]) {
Thread pet1 = new Thread(new CyberPet("Socrates"));
Thread pet2 = new Thread(new CyberPet("Plato"));
pet1.start(); // Create and start each thread
pet2.start();
} // main()
} // TestCyberPet
11. Create a version of the Bakery program that uses two clerks to serve customers.
Design: The only change required to implement a two-clerk version of the
Bakery program is to create a second Clerk thread in the main program, and
then start both threads. The synchronization of the two clerks will happen automatically, as a result of the design of the TakeANumber class:
public class Bakery {
public static void main(String args[]) {
System.out.println( "Starting clerk and customer threads" );
TakeANumber numberGadget = new TakeANumber();
Clerk clerk = new Clerk(numberGadget);
Clerk clerk2 = new Clerk(numberGadget);
clerk.start();
clerk2.start();
for (int k = 0; k < 5; k++) {
Customer customer = new Customer(numberGadget);
customer.start();
}
} // main()
} // Bakery
398
However, if just this change is made it will be impossible to tell which clerk
is doing the serving. To remedy this we want to give each clerk a unique ID
number. We can use a static variable to serve as the source of unique IDs and
assign each new clerk object an ID in the constructor method. Then when the
clerk calls the nextCustomer() method, it passes its ID number.
/*
* File: Clerk.java
* Author: Java, Java, Java
* Description: This class defines the clerk thread of
* the bakery simulation. The clerk has a reference to
* the TakeANumber gadget. The clerk "serves" the next
* customer by repeatedly calling takeANumber.nextCustomer().
* To simulate the randomness involved in serving times,
* the clerk sleeps for a random interval on each iteration of
* its run loop.
*/
public class Clerk extends Thread {
private static int id = 0;
private int myId;
private TakeANumber takeANumber;
/**
* Clerk() constructor gives the clerk a reference to the
* TakeANumber gadget.
*/
public Clerk(TakeANumber gadget) {
takeANumber = gadget;
myId = id++;
}
/**
* run() is the main algorithm for the clerk thread. Note
* that it runs in an infinite loop. Note that in this version
* the clerk no longer checks if there are customers waiting before
* calling nextCustomer(). This check has been moved into the
* TakeANumber object itself.
*/
public void run() {
while (true) {
try {
sleep((int)(Math.random() * 1000));
takeANumber.nextCustomer(myId);
} catch (InterruptedException e) {
System.out.println("Exception: " + e.getMessage() );
}
} // while
399
} // run()
} // Clerk
Given these changes, the program should produce something like the following
output:
Starting clerk and customer
Starting clerk and customer
Customer 10001 takes ticket
Customer 10002 takes ticket
Clerk 1 serving ticket 1
Clerk 0 serving ticket 2
Customer 10005 takes ticket
Clerk 1 serving ticket 3
Clerk 1 waiting
Customer 10003 takes ticket
Clerk 1 serving ticket 4
Clerk 0 waiting
Customer 10004 takes ticket
Clerk 0 serving ticket 5
Clerk 0 waiting
Clerk 1 waiting
threads
threads
1
2
12. Modify the Numbers program so that the user can interactively create NumberThreads and assign them a priority. Modify the NumberThreads so that
they print their numbers indefinitely (rather than for a fixed number of iterations).
Then experiment with the system by observing the effect of introducing threads
with the same, lower, or higher priority. How do the threads behave when they
400
all have the same priority? What happens when you introduce a higher-priority
thread into the mix? What happens when you introduce a lower-priority thread
into the mix?
Design: The only change required in the NumberPrinter class is to change
the for loop in run() to an infinite loop. In the Numbers class, a BufferedReader is used to perform input and the user is prompted for the priority of
each of 5 threads. Each threads priority is set in main() before starting the
thread.
/*
* File: NumberPrinter.java
* Author: Java, Java, Java
* Description: This class implements the Runnable
* interface, which consists of the run() method.
* Implementing the Runnable interface is a way to
* turn an existing class into a separate thread.
*/
public class NumberPrinter implements Runnable {
int num;
/**
* NumberPrinter() constructor assigns its
* parameter as the threads number.
* @param n -- the number assigned to this object
*/
public NumberPrinter(int n) {
num = n;
}
/**
* run() is the threads primary method. It prints its
* number 10 times. This version has each thread sleep
* for a random interval. This will cause the threads
* to run in an arbitrary order.
*/
public void run() {
for (; ; ) {
// Infinite Loop
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
System.out.print(num);
} // for
} // run()
} // NumberPrinter
/*
401
402
* File: Numbers.java
* Author: Java, Java, Java
* Description: This class provides an interface to the
* NumberPrinter class. It allows the user to create
* NumberPrinter threads and and assign each one a priority. It starts then
* each one, each of which repeatedly prints its number. This allows you to
* see the order and duration of each threads execution.
*
* In this version, because NumberPrinters are objects that
* implement the Runnable interface, we create them with
* new Thread(new NumberPrinter(k)). Note also that an array is used
* to store the individual threads.
*/
import java.io.*;
public class Numbers {
public static void main(String args[]) throws IOException {
Thread number[] = new Thread[5];
// An array of 5 threads
13. Create a bouncing ball simulation in which a single ball (thread) bounces up and
down in a vertical line. The ball should bounce off the bottom and top of the
enclosing frame.
Design: The Ball class is a subclass of Thread. Its bouncing is effected by
repeatedly drawing, moving and erasing an oval on the screen. In order to insure
that the ball remains within the applets visible window, the Ball is given a
reference to the applet, from which it can get the applets dimensions.
403
404
/*
* File: Ball.java
* Author: Java, Java, Java
* Description: This class defines a ball that bounces up and
* down within an applet. The "bouncing" is effected by repeatedly
* drawing, and erasing and moving the ball in the run() method.
* Note the use class constants in the program and the use of XOR mode
* in the draw method.
*/
import javax.swing.*;
import java.applet.*;
import java.awt.*;
public class Ball extends Thread implements Runnable {
public static final int SIZE = 5;
private static final int DY = 5;
els to move the ball
private static final int BORDER = 10;
der around drawing area
private JApplet applet;
private int topWall, bottomWall;
405
ing and
* erasing the ball on each successive call to draw().
*/
public void draw() {
Graphics g = applet.getGraphics();
g.setXORMode(Color.white);
// Note use of XOR mode here
g.fillOval(location.x, location.y, SIZE, SIZE); // to either draw or erase
} // draw()
/**
* move() changes the balls vertical location (y-coordinate) by DY pixels.
* It then checks if the ball has reached a boundary and if so reverses direction
*/
public void move() {
location.y = location.y + DY * directionY; // Calculate a new location
if (location.y
directionY
location.y
}
if (location.y
directionY
location.y
}
} // move()
> bottomWall) {
= -directionY;
= bottomWall;
< topWall) {
= -directionY;
= topWall;
// If ricochet
// reverse direction
// Reverse direction
/**
* run() repeatedly draws, erases and moves the ball
*/
public void run() {
while (true) {
draw();
// Draw
try {
sleep(100);
}
catch (InterruptedException e) {}
draw();
// Erase = XOR Draw at same location
move();
// Move
} // while
} // run()
} // Ball
/*
* File: BounceApplet.java
* Author: Java, Java, Java
* BounceApplet displays a bouncing ball within a red rectangle.
*/
import
import
import
import
406
javax.swing.*;
java.awt.*;
java.applet.Applet;
java.awt.event.*;
14. Modify the simulation in the previous exercise so that more than one ball can be
introduced. Allow the user to introduce new balls into the simulation by pressing
the space bar or clicking the mouse.
Design: This version must implement the KeyListener interface so that each
time the spacebar is pressed, the applet can create and start a new applet thread.
Only the KeyListener.keyTyped() method must be implemented. The
applet must also requestFocus() in order to be sent key events.
In the Ball class, the only change we require is that we want to start each ball
at a different, random location. We do this by assigning a random value to the
balls x-coordinate. That way each ball will bounce in a different vertical plane.
/*
* File: Ball.java
* Author: Java, Java, Java
* Description: This class defines a ball that bounces up and
* down within an applet. The "bouncing" is effected by repeatedly
* drawing, and erasing and moving the ball in the run() method.
* Note the use class constants in the program and the use of XOR mode
* in the draw method.
*
* In this version of Ball, instead of starting every Ball in the center
* of the bounce area, each ball is given a random x-coordinate. So each
* bounces in its own vertical space.
*/
import javax.swing.*;
import java.applet.*;
Figure 13.2: In this version of the bouncing ball applet the user can add new balls to
the mix by pressing the space bar.
407
408
import java.awt.*;
public class Ball extends Thread implements Runnable {
public static final int SIZE = 5;
private static final int DY = 5;
els to move the ball
private static final int BORDER = 10;
der around drawing area
private JApplet applet;
private int topWall, bottomWall;
409
* It then checks if the ball has reached a boundary and if so reverses direction
*/
public void move() {
location.y = location.y + DY * directionY; // Calculate a new location
if (location.y
directionY
location.y
}
if (location.y
directionY
location.y
}
} // move()
> bottomWall) {
= -directionY;
= bottomWall;
< topWall) {
= -directionY;
= topWall;
// If ricochet
// reverse direction
// Reverse direction
/**
* run() repeatedly draws, erases and moves the ball
*/
public void run() {
while (true) {
draw();
// Draw
try {
sleep(100);
}
catch (InterruptedException e) {}
draw();
// Erase = XOR Draw at same location
move();
// Move
} // while
} // run()
} // Ball
/*
* File: BounceApplet.java
* Author: Java, Java, Java
* Description: This version allows the user to introduce new balls
* by clicking the spacebar. It implements the KeyListener interface.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BounceApplet extends JApplet implements KeyListener {
private Thread ball;
public void init() {
setSize(200,200);
setBackground(Color.white);
requestFocus();
ceive key events
addKeyListener(this);
} // init()
410
// Required to re-
15. Modify your solution to the previous problem by having the balls bounce off the
wall at a random angle.
Design: To introduce randomness we calculate a random value for deltaY, the
amount by which the y-coordinate changes, each time the ball comes in contact
with the left or right wall. The causes the ball to move at an angle, instead of
horizontally. See the Ball.move() method.
/*
*
*
*
*
*
*
*
*
*
*
*
*
File: Ball.java
Author: Java, Java, Java
Description: This class defines a ball that bounces up and
down within an applet. The "bouncing" is effected by repeatedly
drawing, and erasing and moving the ball in the run() method.
Note the use class constants in the program and the use of XOR mode
in the draw method.
In this version of Ball, instead of starting every Ball in the center
of the bounce area, each ball is given a random x-coordinate. So each
bounces in its own vertical space. Also, the balls bounce at random
angles off of the four walls. The randomness is introduced by changing
Figure 13.3: In this version of the bouncing ball applet the ball bounces at random
angles off of the left and right walls.
411
412
-4 to +4, giv-
413
// Set ini-
/**
* draw() either draws or erases the ball, because XORmode reverses the
* background color.
*/
public void draw() {
Graphics g = applet.getGraphics();
g.setXORMode(Color.white);
// Note use of XOR mode here
g.fillOval(location.x, location.y, SIZE, SIZE); // to either draw or erase
} // draw()
/**
* move() changes the balls vertical location (y-coordinate) by DY pixels.
* It then checks if the ball has reached a boundary and if so reverses direction
*/
public void move() {
location.x = location.x + DX * directionX; // Calculate a new location
location.y = location.y + deltaY * directionY;
if (location.y > bottomWall) {
// If ricochet
directionY = -directionY;
// reverse direction
location.y = bottomWall;
}
if (location.y < topWall) {
directionY = -directionY;
// Reverse direction
location.y = topWall;
}
if (location.x > rightWall ) {
directionX = -directionX;
deltaY = MINDY + (int) (Math.random() * MAXDY); // CHANGE VERTICAL DIRECTION
location.x = rightWall;
}
if ( location.x < leftWall ) {
directionX = -directionX;
deltaY = MINDY + (int) (Math.random() * MAXDY); // CHANGE VERTICAL DIRECTION
location.x = leftWall;
}
} // move()
414
/**
* run() repeatedly draws, erases and moves the ball
*/
public void run() {
while (true) {
draw();
// Draw
try {
sleep(100);
}
catch (InterruptedException e) {}
draw();
// Erase = XOR Draw at same location
move();
// Move
} // while
} // run()
} // Ball
/*
* File: BounceApplet.java
* Author: Java, Java, Java
* Description: This version allows the user to introduce new balls
* by clicking the spacebar. It implements the KeyListener interface.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BounceApplet extends JApplet implements KeyListener {
private Thread ball;
/**
* init() gets the focus for key events and registers the applet
* as a KeyListener.
*/
public void init() {
setSize(200,200);
setBackground(Color.white);
requestFocus();
// Required to receive key events
addKeyListener(this);
} // init()
/**
* paint() paints a red rectangle for the bouncing region and creates the
*
first bouncing ball.
*/
public void paint (Graphics g ) {
g.setColor(Color.white);
415
g.fillRect(10,10,180,180);
g.setColor(Color.red);
// Draw the bouncing region
g.drawRect(10,10,180,180);
g.drawString("Hit space bar to start a new ball", 10, 10);
ball = new Thread(new Ball(this));
// Create and start the ball
ball.start();
} // paint()
/**
* keyTyped() is invoked every time a KeyEvent occurs. The getKeyChar()
* method gets the value of the key that was pressed. Whenever the
* spacebar is pressed, a new bouncing ball is introduced into the applet.
*/
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ) {
// If spacebar pressed
ball = new Thread(new Ball(this));
ball.start();
}
} // keyType()
public void keyReleased( KeyEvent e) {} // Unused part of KeyListener interface
public void keyPressed( KeyEvent e) {} // Unused
} // BounceApplet
16. Challenge: One type of producer/consumer problem is the reader/writer problem. Create a subclass of JTextField that can be shared by threads, one of
which writes a random number to the text field, and the other of which reads the
value in the text field. Coordinate the two threads so that the overall effect of
program will be that it will print the values from 0 to 100 in the proper order.
In other words, the reader thread shouldnt read a value from the text field until
theres a value to be read. The writer thread shouldnt write a value to the text
field until the reader has read the previous value.
Design: The shared resource is a subclass of JTextField, which it extends by
defining two new methods, getValue(), which returns the text fields value,
and setValue(), which assigns a value to the text field. Both of these methods
are synchronized, meaning that once a thread calls one of the methods it cannot
be preempted by another thread. This ensures that the reader and writer threads
will have mutually exclusive access to these methods (whenever they are running
and not sleeping.)
To further coordinate access to the shared text field, it contains a writeable
control variable, which is set to true initially. It is set to false only after the
writer thread has written a value to the field. It is set back to true only after the
reader thread has read a value from the field. In this way writing and reading of
the shared resource will occur in a alternating fashion, as the following figures
shows.
Figure 13.4: Cooperating reader and writer threads produce a sequence from 0 to 99.
/*
* File: SharedField.java
* Author: Java, Java, Java
* Description: This JTextField subclass synchronized the
* cooperation between a Reader and Writer thread. Its
* setValue() and getValue() methods are synchronized so
* that the reader thread can only read when a new value is
* available, and the writer can only write when the buffer
* is shared field is empty.
*/
import javax.swing.*;
public class SharedField extends JTextField {
private boolean writeable = true; // The field is initially empty
/**
* SharedField() creates a JTextFIeld with a given width
* @param width -- the text fields width
*/
public SharedField(int width) {
super(width);
}
/**
* setValue() assigns its parameter to the text field
416
417
418
419
buffer = b;
display = ta;
} // Reader()
/**
* run() repeatedly reads a value from the buffer. See
* the SharedField.getValue() method for details on how
* this thread is coordinated with the Writer thread.
*/
public void run() {
String value;
for (;;) {
try {
sleep((int) Math.random() * 2000);
}
catch (InterruptedException e) {
}
value = buffer.getValue();
int intValue = Integer.parseInt(value);
display.append(value + " ");
if (intValue % 20 == 0)
// Wrap around every 20 numbers
display.append("\n");
}
} // run
} // Reader
/*
* File: ReaderWriter.java
* Author: Java, Java, Java
* Description: Sets up reader/writer cooperation between two
* threads using a shared resource, in this case a JTextField.
* The writer thread repeatedly writes values to the textfield,
* and the reader thread repeatedly reads values from it. There
* actions are coordinated.
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ReaderWriter extends JFrame implements ActionListener {
public static final int WIDTH=425, HEIGHT=300;
private
private
private
private
17. Challenge: Create a streaming banner thread that moves a simple message
across a panel. The message should repeatedly enter at the left edge of the panel
420
and exit from the right edge. Design the banner as a subclass of JPanel and
have it implement the Runnable interface. That way it can be added to any
user interface. One of its constructors should take a String argument that lets
the user set the banners message.
Design: One consideration in designing this solution is you want to be able to
add the banner to any container, such as a JApplet or JFrame. Since you
cant add a Thread to a container a thread is not a Component you dont
want to define the banner as a Thread subclass or even as implementing the
runnable interface. Instead define the banner as a subclass of JPanel. Then
define a Timer thread subclass, which can be started by the banner object. The
Timer thread repeatedly calls the banners repaint() method, causing the
banner to be redrawn at a new location. By rapidly redrawing the banner, it
appears to move from right to left across the panel.
/*
* File: Banner.java
* Author: Java, Java, Java
* Description: This subclass of JPanel implements a
*
streaming banner in the panel. The Banner() constructor
*
takes a single string parameter giving the message that
*
will repeatedly stream through the panel. The Banner can
*
be added to any Container. To start streaming its start()
*
method should be called. The start() method creates a
*
separate Timer thread which repeatedly calls the Banners
*
repaint() method to paint the message at a new location.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Banner extends JPanel {
private String message;
421
422
/**
* Banner() constructor sets the panels message. The messages
* initial location is beyond the right edge of the panel.
*/
public Banner(String s) {
message = s;
xRef = getSize().width + 10;
// Initial message location
}
/**
* start() method creates and starts a timer thread. The
* timer repeatedly calls the panels repaint() method.
*/
public void start() {
Timer timer = new Timer(this);
timer.start();
} // start()
/**
* paintComponent() is invoked whenever the Banner is repainted.
* It erases the entire panel and then moves the message slightly
* to the left and repaints it.
*/
public void paintComponent(Graphics g) {
g.setColor(getBackground());
// Erase the panel
g.fillRect(0,0,getSize().width, getSize().height);
if (xRef > -100 )
// Move the message
xRef -= 5;
else
xRef = getSize().width + 10;
g.setColor(Color.black);
g.drawString(message, xRef, vRef);
} // paintComponent()
/**
* main() creates an instance of Banner and adds it to
*
a top-level JFrame. Note the use of the anonymous WindowAdapter
*
to serve as a listener for the window close event.
*/
public static void main(String args[]) {
JFrame f = new JFrame("Banner Panel");
Banner banner = new Banner("Eat at Joes");
f.getContentPane().add(banner);
f.setSize(200, 100);
f.setVisible(true);
423
banner.start();
f.addWindowListener(new WindowAdapter() {
// Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // Banner
/*
* File: Timer.java
* Author: Java, Java, Java
* Description: This timer thread is created by a JPanel
* and it repeatedly calls the JPanels repaint() method,
* sleeping for an instant between each call.
*/
import javax.swing.*;
public class Timer extends Thread {
private JPanel panel;
/**
* Timer() constructor sets a reference to the JPanel.
*/
public Timer(JPanel p) {
panel = p;
}
/**
* run() repeatedly calls repaint() forcing the panel to
* repaint its message.
*/
public void run() {
try {
while (true) {
panel.repaint();
sleep(100);
}
}
catch (InterruptedException e) {}
} // run
} // Timer
18. Challenge: Create a slide show applet, which repeatedly cycles through an
array of images. The displaying of the images should be a separate thread. The
applet thread should handle the user interface. Give the user some controls that
let it pause, stop, start, speed up, and slow down the images.
Design: We break up this problem into two classes: an applet, SlideShowAp-
plet, that serves as the user interface, and a thread subclass, SlideMachine,
that manages the displaying of the slides themselves. Note how the slide machine class uses an internal state variable to control the running of the slides. It
also contains several methods uses to control the machine.
/*
* File: SlideMachine.java
* Author: Java, Java, Java
* Description: The class simulates an online slide machine.
* It runs as a separate thread. The machines internal state
* is either ON, OFF, or PAUSED, although there is no real
424
425
JApplet app;
// Link to applet
Image[] slide = new Image[NIMGS];
Image currentImage = null;
int nextImg = 0;
int delay = 1000;
// The delay used by sleep()
int state = OFF;
/**
* SlideMachine() loads the images into an array.
*/
public SlideMachine(JApplet a) {
app = a;
for (int k=0; k < NIMGS; k++) {
slide[k] = a.getImage(a.getCodeBase(), "slide" + k + ".gif");
}
state = ON;
} // SlideMachine()
/**
* nextSlide() sets currentImage to the next slide
* in the array, wrapping around to 0 if necessary.
* It then draws the image on the applet.
*/
public void nextSlide( ) {
currentImage = slide[nextImg];
nextImg = (nextImg + 1) % NIMGS;
Graphics g = app.getGraphics();
if (currentImage != null)
g.drawImage(currentImage,50,60,app);
} // nextSlide()
/**
* setDelay() sets the delay between slides to d.
* Negative delays are not allowed.
* @param d -- an int giving the size of the delay.
*/
/*
* File: SlideShowApplet.java
426
427
// User in-
/**
* init() initializes the user interface and starts
*
the slide machine thread.
*/
public void init() {
setSize( WIDTH, HEIGHT );
controls.add(start);
controls.add(stop);
controls.add(pause);
controls.add(faster);
controls.add(slower);
start.addActionListener(this);
stop.addActionListener(this);
pause.addActionListener(this);
faster.addActionListener(this);
slower.addActionListener(this);
slidemachine = new SlideMachine(this);
slidemachine.start();
getContentPane().add("North", controls);
} //init()
/**
* actionPerformed() handles actions on the several buttons
*
that control the slide show. Note that the start button
*
causes a new thread to be created.
*/
public void actionPerformed(ActionEvent e) {
JButton b = (JButton) e.getSource();
if (b == slower)
slidemachine.setDelay(slidemachine.getDelay() + 300);
else if (b == faster)
slidemachine.setDelay(slidemachine.getDelay() - 300);
else if (b == stop)
slidemachine.stopSlides();
else if (b == pause)
slidemachine.pause();
else if (b == start) {
slidemachine = new SlideMachine(this);
slidemachine.start();
}
} // actionPerformed()
}//SlideShowApplet
19. Challenge: Create a horse race simulation, using separate threads for each of the
horses. The horses should race horizontally across the screen, with each horse
having a different vertical coordinate. If you dont have good horse images to
use, just make each horse a colored polygon or some other shape.
Design: The Horse class is modeled after the Ball class used in the bouncing ball applet. The horses image randomly moves from left to right across
the screen. The top-level frame, RaceTrack, serves as the user interface for
this application. It also manages the race by providing two callback methods:
raceOver(), a boolean method that is checked by each horse before moving
forward, and stopRace(), the method called by the first horse to reach the
finish line. These methods are synchronized to insure that they are executed by
one horse at a time.
/*
* File: Horse.java
* Author: Java, Java, Java
* Description: This class simulates a race horse. The horse
* is represented by a colored oval at a certain location
* on the JPanel. On each iteration of run() the horse moves
* ahead by a random amount. When it reaches the finish line
* it calls the frames stopRace() method. This causes the
* other horses to stop. Thus the top-level frame acts as
* an intermediary between the horses and controls the stopping
* and starting of the race.
*/
import javax.swing.*;
import java.awt.*;
428
// Boundary
// At finish line?
429
size = p.getSize();
color = c;
location = loc;
} // Horse()
430
/**
* draw() either draws or erases the horse. When XORmode is used
* it has the effect of drawing and erasing the horse on each successive
* call to draw().
*/
public void draw(Color color) {
Graphics g = panel.getGraphics();
g.setXORMode(color);
// Note use of XOR mode here
g.fillOval(location.x, location.y, SIZE, SIZE); // to either draw or erase
} // draw()
/**
* move() moves the horse forward by a random amount between 0 and MAXDX.
*/
public void move() {
int dx = (int)(Math.random() * MAXDX);
location.x = location.x + dx;
// Calculate a new location
finished = location.x >= size.width - SIZE;
if (finished) frame.stopRace();
} // move()
/**
* run() repeatedly draws, erases and moves the horse
*/
public void run() {
finished = false;
while (!finished && !frame.raceOver()) {
draw(color);
// Draw
try {
sleep(200);
}
catch (InterruptedException e) {}
draw(color);
// Erase = XOR Draw at same location
move();
// Move
} // while
if (finished) {
location.x = size.width - SIZE;
draw(Color.black);
// Single out the winner
}
else
draw(color);
} // run()
} // Horse
431
/*
* File: RaceTrack.java
* Author: Java, Java, Java
* Description: This class serves as the interface and controller
* for a simulated horse race. The user is provided buttons to
* start and reset the race. When started, five horse threads are created
* and started. The race is controlled by a pair of synchronized callback
* methods, raceOver() and stopRace(). The first is checked repeatedly by
* each horse before it can move ahead. The second is called by the horse
* that first reaches the finish line.
*/
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class RaceTrack extends JFrame implements ActionListener{
private JButton start = new JButton("Start");
private JButton reset = new JButton("Reset");
private JPanel controls = new JPanel();
private JPanel raceCourse = new JPanel();
private Border b = BorderFactory.createEtchedBorder();
private Horse stable[] = new Horse[5];
ences to the horses
private boolean raceIsOver = false;
// Stores refer-
/**
* RaceTrack() constructor sets up a simple interface for the horse
* race. Two buttons are provided and a border is drawn around the
* racing area.
*/
public RaceTrack() {
start.addActionListener(this);
reset.addActionListener(this);
controls.add(start);
controls.add(reset);
getContentPane().add(controls,"North");
getContentPane().add(raceCourse,"Center");
raceCourse.setBorder( BorderFactory.createTitledBorder(b,"Race Course",
TitledBorder.TOP, TitledBorder.CENTER));
} // RaceTrack
/**
* actionPerformed() handles clicks on the two buttons. When the start
* button is clicked, five horses are created and started. On re-
432
set,
433
20. Challenge: The game of Pong was the rage in the 1970s. It consists of a ball
that moves within a rectangular region, as in the previous exercise, and a single
paddle, which is located at the right boundary, which can be moved up and down
by the user. When the ball hits the paddle, it bounces off at a random angle.
When it hits the wall, it just reverses direction. The ball should be one thread
and the user interface (and paddle) should be the other.
Design: The Pong game can be created by making some minor modifications to
the bouncing ball applet. First, a Paddle class is needed. The paddle will just
be a vertical line segment located at the right boundary of the bouncing region.
Its motion will be controlled by the user via the up and down arrow keys. This
class should take care of drawing and moving the paddle.
Second, the ball must be able to detect when it hits the paddle. So it will need a
variable to keep track of the paddles location, which it can get from the applet.
Thus the applet mediates the interaction between the ball and the paddle. The
main change in this class occurs in its move() method, where it tests whether it
hit the paddle and sets the ricochet angle.
Finally, the applet itself is almost identical to the BounceApplet we used
above. The only change is that it must create a Paddle and it must implement
the hitPaddle() method. This is a call back method. Its called by the ball to
check whether the ball has hit the paddle. This method is the main way in which
the applet mediates between the ball and the paddle.
/*
* File: Paddle.java
* Author: Java, Java, Java
* Description: This class represents a paddle for the Pong game.
* The paddle is a vertical line segment located at the right boundary.
* Its motion is controlled by the user via up/down arrow keys. Therefore
* the paddle needs a reference to the applet. The Paddle class contains
* move() and draw() methods.
import java.awt.*;
// Size of Paddle
// Size of each move
// Reference to the applet
/**
* Paddle() constructor is passed a reference to the applet, which it
* uses to determine the dimensions of the game area.
*/
434
435
436
-4 to +4, giv-
437
438
just location
}
if (location.y
directionY
location.y
}
if (location.y
directionY
location.y
}
if (location.x
directionX
location.x
}
> bottomWall) {
= -directionY;
= bottomWall;
< topWall) {
= -directionY;
= topWall;
// If ricochet
// reverse direction
// Reverse direction
> rightWall ) {
= -directionX;
= rightWall;
439
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class PongApplet extends JApplet implements KeyListener {
private Thread ball;
private Paddle paddle;
/**
* init() creates the ball and paddle objects, and registers as the
* KeyListener. It also must requestFocus() so that it will receive
* key events.
*/
public void init() {
setSize(200,200);
setBackground(Color.white);
requestFocus();
// Required to receive key events
addKeyListener(this);
paddle = new Paddle(this);
// Create the paddle
ball = new Thread(new Ball(this));
// Create the ball
} // init()
/**
* paint() starts the ball (which causes it to draw) and draws the paddle.
*/
public void paint (Graphics g ) {
g.setColor(Color.white);
g.fillRect(10,10,180,180);
g.setColor(Color.red);
// Draw the bouncing region
g.drawRect(10,10,180,180);
ball.start();
paddle.draw();
// And draw the paddle
} // paint()
/**
* hitPaddle() is the callback routine called by ball to check whether it
* hit the paddle.
* @param p -- A Point giving the balls location
* @return -- a boolean set to true if the paddle and ball are touching
*/
public boolean hitPaddle(Point p) {
Point paddleLoc = paddle.getLocation();
if ( p.x + Ball.SIZE >= paddleLoc.x
&& p.y >= paddleLoc.y
&& p.y <= paddleLoc.y + Paddle.SIZE)
440
return true;
else
return false;
} // hitPaddle()
/**
* keyTyped() is invoked every time a KeyEvent occurs. It gets the keys code
* and checks whether the up or down arrow keys were pressed. If so it moves
* the paddle.
*/
public void keyReleased( KeyEvent e) { // Check for arrow keys
int keyCode = e.getKeyCode();
if (keyCode == e.VK_UP)
// Up arrow
paddle.moveUp();
else if (keyCode == e.VK_DOWN)
// Down arrow
paddle.moveDown();
} // keyReleased()
/**
* keyTyped() is invoked every time a KeyEvent occurs. The getKeyChar()
* method gets the value of the key that was pressed. Whenever the
* spacebar is pressed, a new bouncing ball is introduced into the applet.
*/
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ) {
// If spacebar pressed
ball = new Thread(new Ball(this));
ball.start();
}
} // keyType()
public void keyPressed( KeyEvent e) {} // Unused
} // PongApplet
21. Challenge: Create a multithreaded digital clock application. One thread should
keep time in an endless loop. The other thread should be responsible for updating
the screen each second.
MISSING SOLUTION
Exercise 13.9
441
Exercise 13.13
interface
Runnable
interface
Runnable
+run()
JApplet
+run()
Thread
RandomNumbers
+run()
BounceApplet
-ball : Thread
+paint(in g : Graphics)
Exercise 13.10
Ball
interface
Runnable
Uses
+SIZE : int = 5
-DY : int = 5
+BORDER : int = 10
-topWall : int
-bottomWall : int
-directionX : int = 1
-directionY : int = 1
-applet : JApplet
-location : Point
+run()
CyberPet
+EATING : int = 0
+SLEEPING : int = 1
+THINKING : int = 2
-petState : int
-name : String
+CyberPet()
+CyberPet(in name : String)
+CybertPet(in name : String, in inState : int)
+CyberPet(in name : String, in isSleeping : boolean)
+setName(in name : String)
+getName() : String
+eat()
+sleep()
+think()
+toString() : String
+getState() : String
+run()
Exercise 13.12
interface
Runnable
+run()
NumberPrinter
-num : int
+run()
Uses
Numbers
TestCyberPet
Uses
Uses
+main()
Uses
Uses
+main()
Thread
BufferedReader
Thread
Exercise
13.11
Bakery
Miscellaneous
Classes
1
Point
Uses
Clerk
1..*
Uses
Graphics
datatype
boolean
Customer
Uses
1
TakeANumber
1
442
JButton
datatype
Image[]
Graphics
+keyTyped(in e : KeyEvent)
+keyPressed(in e : KeyEvent)
+keyReleased(in e : KeyEvent)
KeyEvent
datatype
boolean
Image
Point
interface
Runnable
JApplet
+run()
Exercise 13.16
datatype
ActionListener
JFrame
Thread
BounceApplet
ReaderWriter
+actionPerformed()
-reset
-buffer : SharedField
-display : JTextArea
-reader : Reader
-writer : Writer
Uses
-ball : Thread
+run()
Thread
Ball
+run()
Uses
+SIZE : int = 5
-DY : int = 5
+BORDER : int = 10
-topWall : int
-bottomWall : int
-directionX : int = 1
-directionY : int = 1
-applet : JApplet
-location : Point
Reader
-buffer : SharedField
-display : JTextArea
+Reader(in b : SharedField, in ta : JTextArea)
+run()
Writer
-buffer : SharedField
Uses
+paint(in g : Graphics)
+keyTyped(in e : KeyEvent)
+init()
+Writer(in b : SharedField)
+run()
Uses
JTextField
Exercise 13.18
datatype
ActionListener
SharedField
Thread
+run()
+actionPerformed()
JApplet
SlideMachine
Exercise 13.17
Thread
JPanel
+run()
Timer
Banner
-panel : JPanel
+Timer(in p : JPanel)
+run()
-message : String
-xRef : int = 0
-yRef : int = 40
+Banner(in msg : String)
+start()
+paintComponent(in g : Graphics)
+main()
Uses
-NIMGS : int = 4
-OFF : int = 0
-ON : int = 1
-PAUSED : int = 2
-applet : JApplet
-attribute1 : Image
-slide : Image[]
-nextImg : int = 0
-delay : int = 1000
-state : int = OFF
+SlideMachine(in a : JApplet)
+nextSlide()
+setDelay(in delay : int)
+getDelay() : int
+stopSlides()
+pause()
+run()
SlideShowApplet
-start : JButton
-stop : JButton
-pause : JButton
-faster : JButton
-slower : JButton
-slideMachine : SlideMachine
+init()
+actionPerformed()
Uses
443
Miscellaneous
Classes
datatype
Horse[]
Graphics
KeyEvent
Exercise 13.20
datatype
boolean
Color
Paddle
Point
+run()
+SIZE : int = 20
-DELTA : int = 10
-BORDER : int = 10
-applet
-location : Point
Exercise 13.19
JFrame
interface
ActionListener
+actionPerformed()
Ball
+Paddle(in applet)
+getLocation() : Point
+draw()
+moveUp()
+moveDown()
Uses
Uses
RaceTrack
Thread
+run()
-start : JButton
-reset : JButton
-stable : Horse[]
-raceIsOver : boolean = false
+RaceTrack()
+actionPerformed()
+stopRace()
+raceOver() : boolean
+main()
PongApplet
-paddle : Paddle
-ball : Thread
+init()
+paint(in g : Graphics)
+hitPaddle(in p : Point) : boolean
+keyTyped(in e : KeyEvent)
+keyReleased(in e : KeyEvent)
Horse
+SIZE : int = 5
-MAXDX : int = 5
-finishLine : int
-finished : boolean
-size : Dimension
-location : Point
-color : Color = black
+Horse()
+Horse(in f, in p, in c : Color, in loc : Point)
+draw(in c : Color)
+move()
+run()
datatype
Runnable
Thread
JButton
Dimension
+SIZE : int = 5
-DX : int = 5
-DY : int = 5
-BORDER : int = 10
-MINDY : int = -4
-MAXDY : int = 9
-applet
-topWall : int
-bottomWall : int
-leftWall : int
-rightWall : int
-paddleLoc : Point
-directionX : int
-directionY : int
-deltaY : int
+Ball(in applet)
+draw()
+move()
+run()
Uses
interface
KeyListener
+keyTyped(in e : KeyEvent)
+keyReleased(in e : KeyEvent)
+keyPressed(in e : KeyEvent)
JApplet
Chapter 14
character. Answer:
(b) In Java, the String array parameter in the main() method is used of
. Answer: command line arguments
(c)
445
7. In reading a file, why is it necessary to attempt to read from the file before entering the read loop?
Answer: In reading a file, we must read from the file prior to entering the read
loop in order to handle the case where the file is empty.
8. When designing binary I/O, why is it especially important to design the input
and output routines together?
Answer: When designing binary I/O, the interpretation of the data is the most
important issue. The routines that write the data must use the same format at
the routines that read the data. In order to ensure this symmetry, both the input
and output routines should be designed together.
9. Whats the difference between ASCII code and UTF code?
Answer: The characters that can be represented in UTF code are a superset of
those that can be represented in ASCII code. UTF contains additional characters
which allow for internationalization. However, UTF also takes up 2 bytes per
character, as opposed to 1 byte per character for ASCII representation.
10. Could the following string of bits possibly be a Java object? Explain.
00010111000111101010101010000111001000100
11010010010101010010101001000001000000111
Answer: Yes, the string of bits could indeed represent a Java object. Java objects
can be serialized and written to a file, just like any other type of data. After all,
anything a computer can do is dependent on some interpretation of 0s and 1s!
11. Write a method, which could be added to the TextIO program, that reads a text
file and prints all lines containing a certain word. This should be a void method
that takes two parameters: the name of the file and the word to search for. Lines
not containing the word should not be printed.
- SOLUTION MISSING 12. Write a program that reads a text file and reports the number of characters and
lines contained in the file.
Design: The displayStats() method in the following FileLineCounter
class reads one line of the file at a time. After reading each line it increments a
line counter and it adds the length of the line to the character counter. It produces
the following output:
$ java FileLineCounter FileLineCounter.java
Lines: 49
Chars: 1572
446
447
/* File: FileLineCounter.java
* Author: Java, Java, Java
* Description: This program counts the lines and characters
* contained in a file named as a command line argument. To run the
* program type:
*
java FileLineCounter filename
*/
import java.io.*;
public class FileLineCounter {
/**
* displayStats() reads the named file and counts its lines and characters
* Results are printed to System.out
* @param filename -- a String giving the name of the file
*/
public void displayStats(String filename){
int lineCount = 0;
int charCount = 0;
try {
BufferedReader inStream =
new BufferedReader(new FileReader(filename));
String line = inStream.readLine();
while(line != null){
lineCount++;
charCount += line.length();
line = inStream.readLine();
}
inStream.close();
System.out.println("Lines: " + lineCount);
System.out.println("Chars: " + charCount);
}
catch (Exception e){
System.out.println("FILE ERROR");
e.printStackTrace();
}
} // displayStats()
/**
* main() creates an instance of this class and passes the first
* command line argument as the name of a file to be processed
* @param args -- an array of String giving the command line arguments
*/
public static void main(String args[]){
FileLineCounter app = new FileLineCounter();
app.displayStats(args[0]);
} // main()
} // FileLineCounter
13. Modify the program in the previous exercise so that it also counts the numbers
of words in the file. (Hint: The StringTokenizer class might be useful for
this task.)
Design: The solution to this exercise requires only minor additions to the displayStats() method. Declare an additional counter variable, wordCount.
Then for each line, create a StringTokenizer instance using the line as the
initial value. Then you can use the StringTokenizer.countTokens()
method to count the words in the line. In short, make the following modifications
to displayStats():
public void displayStats(String filename){
...
int wordCount = 0;
try {
...
while(line != null) {
StringTokenizer st = new StringTokenizer(line);
wordCount += st.countTokens();
...
}
...
System.out.println("Words: " + wordCount);
}
...
} // displayStats()
Given these changes the program would produce the following output:
$ java FileLineCounter FileLineCounter.java
Lines : 52
Words: 211
Chars : 1769
14. Modify the ObjectIO program so that it allows the user to designate a file and
then input Student data with the help of a GUI. As the user inputs data, each
record should be written to the file.
Design: The interface should give the user the ability both to write data to the
file and to read the file, if for no other reason than to verify that the program is
correctly writing the data. To simplify data entry, we allow the user to input one
complete student record as a delimited string Name,Year,GPA. The program
then uses a StringTokenizer to break the string into its individual fields.
The interface should enable to user to append multiple records to the file. This
means the files output stream must remain open through multiple write operations. To facilitate this we want to declare the output stream as a class variable.
Once the output stream is open, it should not be closed until the user elects to
read the file.
448
The Student class remains unchanged from the one defined in this chapter,
and is therefore not shown here.
/*
* File: ObjectIO.java
* Author: Java, Java, Java
* Description: This class provides a graphical user interface for
* data entry of Student records. The interface consists of two
* text fields, one for entering the name of the data file and
* the other for entering a student record. The student record
* is entered as a comma-delimited string -- Name,Year,GPA. One
* control button enables the user to append one record at a time
* to the named datafile. The other lets the user read all the
* records in the data file.
*
* Design Issue: Since we wish to append multiple records to the
* data file we cannot open and close the files output stream for
* each record. Instead, the output stream is open, then a bunch of
* records are written to the file. The stream is closed only when
* the user chooses to read the file, after with its output stream
* must be reopen again before appending new records. See the
* actionPerformed() method for details.
*/
import javax.swing.*;
// Swing components
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import java.util.*;
// String Tokenizer
449
450
451
finite loop
//
//
//
//
Name
Class year
GPA
Cre-
//
and dis-
//
/**
* actionPerformed() handles the users button actions. If the read
* button was clicked, it closes the output stream, if it was already
* open, and then invokes the readRecords() method to read the named file.
* If the write button was clicked, it opens the output stream, if nec-
452
essary,
* and invokes the appendRecord() method.
* @param evt -- the ActionEvent that led to this invocation
*/
public void actionPerformed(ActionEvent evt) {
try {
String fileName = fileNameField.getText(); // Get the file name
if (evt.getSource() == read) {
if (outStream != null) {
outStream.close();
outStream = null;
// Reset to null
}
readRecords(fileName);
}
else if (evt.getSource() == write) {
if (outStream == null)
outStream = new FileOutputStream( fileName, true ); // Open a stream
else
appendRecord(fileName);
}
} catch (IOException e) {}
} // actionPerformed()
/**
* main() creates and instance of this class and opens its window.
*/
public static void main(String args[]) {
ObjectIO io = new ObjectIO();
io.setSize( 425,200);
io.setVisible(true);
io.addWindowListener(new WindowAdapter() { // Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
}//ObjectIO
15. Write a program that will read a file of ints into memory, sort them in ascending
order, and output the sorted data to a second file.
Design: It is appropriate to use a Vector (rather than an array) to store the integer data in memory, because it is not known beforehand how many integers the
input file contains. Then using the Vector.insertElementAt() method,
the data can be inserted in the vector in their proper order.
/* File: IntFileSorter.java
* Author: Java, Java, Java
* Description: This program reads a file of integer data into an
453
* Vector, sorting it as it inserts it, and then outputs the data to a second file.
* A Vector is an appropriate data structure here because it is
* not known initially how many numbers the file will contain.
*
* Usage: java IntFileSorter sourcedata destinationfile
*/
import java.io.*;
import java.util.*;
public class IntFileSorter {
private Vector intList;
/**
* IntFileSorter() creates the Vector that will be used to store the numbers.
*/
public IntFileSorter(){
intList = new Vector();
}
/**
* insertInt() inserts its parameter, n, into the vector in its
* proper location. To do this it traverses the vector starting at 0
* until it finds a number greater than n, at which point it breaks
* out of the traversal and inserts the number.
* @param -- n the integer to be inserted in the vector
*/
private void insertInt(int n){
int pos;
for (pos = 0; pos < intList.size(); pos++) {
if (n < ((Integer)intList.elementAt(pos)).intValue())
break;
}
intList.insertElementAt(new Integer(n), pos);
} // insertInt()
/**
* writeInts() writes the data to the named file
* @param filename -- the name of the destination file
*/
private void writeInts(String fileName){
try {
DataOutputStream outStream = new DataOutputStream (new FileOutputStream(fileName)
for(int j=0; j < intList.size(); j++) {
int n = ((Integer)intList.elementAt(j)).intValue();
System.out.print(n + " ");
// Output to standard out
outStream.writeInt(n);
454
}
}
catch (IOException e){
System.out.println("IOERROR!");
e.printStackTrace();
}
} // writeInts()
/**
* readInts() reads the integers from the named file
* @param filename -- a string giving the name of a file
*/
private void readInts(String fileName){
try{
DataInputStream inStream = new DataInputStream(new FileInputStream(fileName));
try{
while(true) {
int n = inStream.readInt();
insertInt(n);
}
}
catch (EOFException e) {}
finally{
inStream.close();
}
}
catch (IOException e){
System.out.println("IOERROR!");
e.printStackTrace();
}
} // readInts()
/**
* main() creates and instance of this class and then uses it
* to read, sort and write a file of integer data. Command line
* arguments are used to name the input and output files.
* @param -- args, a String array containing the command line arguments.
*/
public static void main(String args[]){
IntFileSorter app = new IntFileSorter();
app.readInts(args[0]);
app.writeInts(args[1]);
System.out.println("IntFileSorter finished.");
} // main()
} // IntFileSorter
16. Write a program that will read two files of ints, which are already sorted into
ascending order, and merge their data. For example, if one file contains 1, 3, 5,
7, 9, and the other contains 2, 4, 6, 8, 10, then the merged file should contain 1,
455
2, 3, 4, 5, 6, 7, 8, 9, 10.
Design: Given the solution to the previous exercise, this problem can easily be
solved by simply calling the insertInts() method twice, once for each file.
Therefore, we only need make minor changes to the main() method:
/**
* main() creates an instance of this class and then uses it
* to read two integer files and merge their data into a third file.
* Command line arguments are used to name the input and output files.
* @param -- args, a String array containing the command line arguments.
*/
public static void main(String args[]){
IntFileMergeSorter app = new IntFileMergeSorter();
app.readInts(args[0]);
app.readInts(args[1]);
app.writeInts(args[2]);
System.out.println("IntFileMergeSorter finished.");
} // main()
17. Suppose you have file of data for a geological survey, such that each record
consists of a longitude, a latitude, and an amount of rainfall, all represented by
doubles. Write a method to read this files data and print them on the screen,
one record per line. The method should be void and it should take the name of
the file as its only parameter.
/*
* File: GeoData.java
* Author: Java, Java, Java
* Description: This program reads and writes a data file containing
* rainfall records at various geographical locations. Each record
* consists of a latitude, longitude and rainfall amount.
*/
import java.io.*;
public class GeoData {
/**
* getGeoData() reads data from the named file
* @param fileName -- the name of the data file
*/
private void getGeoData(String fileName){
try{
DataInputStream inStream = new DataInputStream(new FileInputStream(fileName));
try{
while(true){
double longitude = inStream.readDouble();
double latitude = inStream.readDouble();
456
/**
* writeGeoData() writes data to the named file.
* @param fileName -- the name of the output file
*/
private void writeGeoData(String fileName) {
java.util.Random gen = new java.util.Random();
try{
DataOutputStream outStream = new DataOutputStream (new FileOutputStream(fileName)
for(int j=0; j < 1000; j++){
double longitude = (gen.nextDouble() * 360) 180;
double latitude = (gen.nextDouble() * 360) 180;
double rainfall = gen.nextDouble() * 20;
outStream.writeDouble(longitude);
outStream.writeDouble(latitude);
outStream.writeDouble(rainfall);
}
}
catch (IOException e){
System.out.println("IOERROR!");
e.printStackTrace();
}
} // writeGeoData()
/**
* main() creates an instance of this class and then either
* reads or writes data from a datafile. If the first command
* line argument is "read", data are read from the file named in
* the second command line argument. Otherwise data are written
* to the named file.
457
18. Suppose you have the same data as in the previous exercise. Write a method that
will generate 1000 records of random data and write them to a file. The method
should be void and should take the files name as its parameter. Assume that
longitudes have values in the range += 0 to 180 degrees, latitudes have values
in the range += 0 to 90 degrees, and rainfalls have values in the range 0 to 20
inches.
Answer: See the solution to the previous exercise.
19. Design and write a file copy program that will work for either text files or binary
files. The program should prompt the user for the names of each file and copy
the data from the source file into the destination file. It should not overwrite an
existing file, however. (Hint: read and write the file as a file of byte.)
Design: Since bytes are more general than characters, a program that reads bytes
can be used to copy either type of file.
/*
* File: FileCopier.java
* Author: Java, Java, Java
* Description: This program copies a data file, byte by byte.
* Usage: java FileCopier sourceFile destFile
*/
import java.io.*;
public class FileCopier {
/**
* copyFile() creates the input and output streams from the given names
* and then reads bytes from the input and writes them to the output.
* @param src -- a String giving the name of the input file
* @param dest -- a String giving the name of the output file
*/
public void copyFile(String src, String dest){
try{
DataInputStream inStream = new DataInputStream(new FileInputStream(src));
DataOutputStream outStream = new DataOutputStream (new FileOutputStream(dest));
try{
while(true){
458
459
460
21. Using the class designed in the previous exercise, modify the Student class so
that it contains an Address field. Modify the ObjectIO program to accommodate this new definition of Student and test your program.
Answer: Very few modifications need to be made. Inside the class definition of
Student we must add:
private Address address;
inside the readFromFile method we must add:
this.address = (Address) s.address;
and the body of the toString() method becomes:
return name + "\t" + year + "\t" + gpr + "\n" + address;
The constructor method must also be changed to accommodate the addition of
the address field. Otherwise, since writeObject() and readObject()
will output or input an entire object, no changes need be made to the ObjectIO
class. The Serializable designation will take care of the details.
461
myfiles
modified
129098
129190
128001
129000
code
rw
rw
r--
Note that the File.lastModified() returns a long, which gives the modification time of the file. This number cant easily be converted into a date, so
just report its value.
Answer: The program shown here produced the following directory listing
when run in the directory containing the program itself:
NAME
Directory.java
Directory.java
Directory.class
LENGTH
2172
1366
1563
MODIFIED
937973197000
937972501000
937972831000
CODE
rw
rw
rw
/*
* File: Directory.java
* Author: Java, Java, Java
* Description: This program prints a directory listing given the
* name of a directory on the system.
*
* Usage: java Directory dirname
*/
import java.io.*;
public class Directory
462
/**
* getCode() constructs a rw code for the given file, showing whether
* the file is readable, writeable
* @param f -- the File that is being characterized
* @return a String of the form rw or r- or -w or -*/
public String getCode(File f){
String code = "";
if(f.canRead())
code += "r";
else
code += "-";
if(f.canWrite())
code += "w";
else
code += "-";
return code;
} // getCode()
/**
* listDirectory() gets the names of all the files in the named directory and
* prints their names, lengths, last modified dates, and read/write characterization.
* @param dirname -- a String giving the name of the directory
*/
public void listDirectory(String dirname){
File dir = new File(dirname);
String banner = "NAME\t\t\tLENGTH\t\t\tMODIFIED\t\t\tCODE";
System.out.println(banner);
String[] fileList = dir.list();
for(int j = 0; j < fileList.length; j++){
File f = new File(dir, fileList[j]);
System.out.print(f.getName() + "\t\t\t");
System.out.print(f.length() + "\t\t\t");
System.out.print(f.lastModified() + "\t\t\t");
System.out.print(getCode(f) + "\n");
}
} // listDirectory()
/**
* main() creates an instance of this class and then invokes the
* listDirectory() method. The directory name is passed as a command
* line argument.
* @param args -- a String array giving the command line argument
*/
public static void main(String args[]){
Directory app = new Directory();
463
if (args.length >= 1)
initialDir = args[0];
app.listDirectory(initialDir);
} // main()
} // Directory
23. Challenge: In Unix systems theres a program named grep that can be used
to list the lines in a text file that contain a certain string. It has the following
command line:
grep "search string" filename
Write a Java version of this program.
Design: The program must read each line of the file. It can then use the String.indexOf()
method to determine if the search string occurs in the file. Heres the output you
should receive if you run this program on the Grep.java source file searching
for the string class.
$ java Grep class Grep.java
12: public class Grep {
41:
* main() creates an instance of the Grep class and uses it to search
Matching Lines : 2
/*
* File: Grep.java
* Author: Java, Java, Java
* Description: This program searches a text file for a target string,
* printing every line containing the string. The target and the filename
* are supplied as command line arguments.
* Usage: java Grep target filename
*/
import java.io.*;
public class Grep {
/**
* displayMatches() searches line-by-line for a target string in a text file.
* Every line containing the target is printed, with its line number. The
* number of matching lines is also reported.
* @param target -- the String being searched for
* @param filename -- the file being searched
464
*/
public void displayMatches(String target, String filename){
int lineCount = 0, matchCount = 0;
try {
BufferedReader inStream = new BufferedReader(new FileReader(filename));
String line = inStream.readLine();
while (line != null) {
lineCount++;
if (line.indexOf(target) >= 0) {
// If line contains target
System.out.println(lineCount + ": " + line);
matchCount++;
}
line = inStream.readLine();
}
inStream.close();
System.out.println("Matching Lines : " + matchCount);
} catch (Exception e) {
e.printStackTrace();
}
} // displayMatches()
/**
* main() creates an instance of the Grep class and uses it to search
* a text file for a given target string. Both the target and filename
* are supplied as command line arguments.
* @param args -- a String array containing command line arguments
*/
public static void main(String args[]){
Grep app = new Grep();
app.displayMatches(args[0], args[1]);
} // main()
} // Grep
24. Challenge: Write the following command-line program in Java. The programs
name is Copy and its purpose is to copy one file into another. So its command
line will be as follows:
java Copy filename1 filename2
Both filename1 and filename2 must exist or the program should throw a
FileNotFoundException. Although filename1 must be the name of a
file (not a directory), filename2 may be either a file or a directory. If filename2 is a file, then the program should copy filename1 to filename2. If
filename2 is a directory, then the program should simply copy filename1
into filename2. That is, it should create a new file with the name filename1 inside the filename2 directory. Copy the old file to the new file, and
then delete the old file.
465
466
}
} // copyFile()
/**
* validateAndCopy() validates the supplied file names. If no exception
* is thrown, it performs the desired copy operation.
* @param source -- a String giving the name of the source file, which should be
* the name of an existing file
* @param dest -- a String giving the name of the destination file, which should be
* either an existing directory or the name of a nonexistent file
*/
public void validateAndCopy(String source, String dest) {
try {
File file1 = new File(source);
File file2 = new File(dest);
if (!(file1.exists()))
throw new FileNotFoundException(file1.getName() + " Not Found");
if (!(file1.isFile()))
throw new IOException(file1.getName() + " must be a file!");
if (file2.exists() && !file2.isDirectory())
throw new IOException(file2.getName() + " must be a directory");
if (!file2.exists())
copyFile(file1, file2);
else
copyFile(file1, new File(file2, source));
} catch (IOException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
} // validateAndCopy()
/**
* main() creates an instance of the Copy class and uses it to copy
* a source file to a destination file. The names of the files are
* supplied as command line arguments.
* @param args -- a String array containing command line arguments
*/
public static void main (String args[]) {
Copy copier = new Copy();
copier.validateAndCopy(args[0], args[1]);
} // main()
} // Copy
467
Exercise 14.13
interface
ActionListener
Exercise 14.12
Miscellaneous
JFrame
FileLineCounter
JTextArea
+actionPerformed()
JButton
File
datatype
String[]
ObjectIO
-display : JTextArea
-read : JButton
-write : JButton
-fileNameField : JTextField
-studentRecord : JTextField
-inStream : FileInputStream
-outStream : FileOutputStream
JTextField
Uses
Uses
Uses
DataInputStream
Vector
Student
DataOutputStream
Uses
+readInt() : int
+writeInt(in n : int)
Uses
Uses
+ObjectIO()
-readRecords(in filename : String)
-appendRecord(in filename : String)
+actionPerformed()
+main()
Uses
Uses
FileInputStream
FileOutputStream
FileOutputStream
FileInputStream
+FileOutputStream(in filename : String)
+FileInputStream(in filename : String)
Serializable
Exercise 14.19
Exercise 14.18
Address
FileCopier
+Address()
+Address(in Street : String, in City : String, in State : String, in Zip : String)
+writeToFile(in outStream : FileOutputStream)
+readFromFile(in inStream : FileInputStream)
+toString() : String
+main(in args : String[])
Directory
Uses
Uses
FileOutputStream
FileInputStream
Exercise 14.22
Exercise 14.23
Grep
Copy
Chapter 15
469
470
/**
* paint() is invoked automatically to draw
*
the applet whenever necessary. It displays
*
the current image.
*/
public void paint(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, WIDTH, HEIGHT);
if (currentImage != null) {
g.drawImage(currentImage, 10, 10, this);
//
play(soundURL[currentImgNumber]);
play(getCodeBase(), currentImgNumber + ".au");
}
} //paint()
/**
* nextSlide() picks the next slide in the array by
*
advancing the nextImg variable mode NIMGS
*/
public void nextSlide() {
currentImage = slide[nextImg];
currentImgNumber = nextImg;
nextImg = (nextImg + 1) % NIMGS;
repaint();
} // nextSlide()
/**
* init() sets up the applets interface and downloads
*
the images from GIF files. It also creates and
*
starts a separate Timer thread.
*/
public void init() {
471
java.awt.*;
java.awt.event.*;
java.net.*;
java.io.*;
javax.swing.*;
java.util.Random;
472
Figure 15.1: A Java application for displaying and solving simple cryptograms.
473
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private
/**
* CryptoViwer() sets up the user interface and downloads
* and displays the cryptogram.
*/
public CryptoViewer () {
super("Cryptogram Viewer Application");
// Set the window title
getCrypto.addActionListener(this);
go.addActionListener(this);
initLetterChoices();
p6.add("North", label0);
p6.add("South", getCrypto);
p7.add("North",p6);
p5.add("North", display);
p5.add("South", display2);
p7.add("South",p5);
this.getContentPane().add("North",p7);
p1.add("East",label1);
p1.add("West",oldLetter);
p2.add("East",label2);
p2.add("West",newLetter);
p3.add("East",p1);
p3.add("West",p2);
p4.add("East",p3);
p4.add("West",go);
this.getContentPane().add("South",p4);
display.setLineWrap(true);
showCurrentCrypto();
// Display the cryptogram
} // CryptoViewer()
474
475
/**
* initLetterChoices() initializes the JCryptoBoxes.
*/
private void initLetterChoices() {
for(int i=0; i < ALPHABET.length(); i++)
{
oldLetter.addItem(ALPHABET.substring(i,i+1));
newLetter.addItem(ALPHABET.substring(i,i+1));
}
}
// initLetterChoices()
/**
* readTextIntoDisplay() downloads the cryptogram given its URL
* and displays it in a TextField.
* @param url -- the URL of the cryptogram
*/
private void readTextIntoDisplay(URL url) throws IOException {
BufferedReader data
= new BufferedReader(new InputStreamReader(url.openStream()));
display.setText("");
// Reset the text area
String line = data.readLine();
while (line != null) {
// Read each line
display.append(line + "\n");
// And add it to the display
line = data.readLine();
}
data.close();
} // readTextIntoDisplay()
/**
* getSolution() downloads the solved cryptogram given its URL
* @param url -- the URL of the cryptogram
*/
private void getSolution(URL url) throws IOException {
BufferedReader data
= new BufferedReader(new InputStreamReader(url.openStream()));
String line = data.readLine();
while (line != null) {
// Read each line
solution += line + "\n";
// And add it to the display
line = data.readLine();
}
data.close();
} // getSolution()
/**
* showCurrentCrypto() selects a random cryptogram.
*/
private void showCurrentCrypto() { // throws IOException {
label0.setText("Try to Solve the Cryptogram!");
ReplacementAlphabet = ALPHABET;
476
// Cre-
477
catch(Exception ex)
{
newCrypto += c;
}
}
display2.setText(newCrypto);
if(newCrypto.equals(solution))
label0.setText("Youve Solved The Cryptogram!");
}
/**
* actionPerformed() handles all user actions.
*/
public void actionPerformed(ActionEvent evt) {
if(evt.getSource() == getCrypto)
showCurrentCrypto();
else if(evt.getSource() == go)
updateDisplay2();
}
/**
* main() creates an instance and displays it. An anonymous
* WindowAdapter is used to handle window close events.
*/
public static void main(String args[]) {
CryptoViewer viewer = new CryptoViewer();
viewer.setSize(viewer.WIDTH,viewer.HEIGHT);
viewer.setVisible(true);
viewer.addWindowListener(new WindowAdapter() {
// Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // CryptoViewer
10. Design and implement a Java applet that displays a random message (or a random
joke) each time the user clicks a GetMessage button. The messages should be
stored in a set of files in the same directory as the applet itself. Each time the
button is clicked, the applet should download one of the message files.
Design: This implementation is designed as a Java application. It assumes that
the messages are stored on some publicly available web site, whose address is
set as the value programs baseURL variable. It is assumed that the messages
are named message0.text, message1.text, and so on.
The interface consists of a single control button and a display text area. Each
time the button is clicked, a new message is displayed. The program constructs
the URL of the message file and then reads it into memory and displays it.
/*
Figure 15.2: A Java application for viewing messages stored on the Internet.
* File: MessageViewer.java
* Author: Java, Java, Java
* Description: This application displays messages that are
* downloaded over the Internet. To install on your system,
* load a set of files named "message0.text", "message1.txt"
* and so on, into some publicly available web site. Then
* change the baseURL and recompile.
*/
import
import
import
import
import
java.awt.*;
java.awt.event.*;
java.net.*;
java.io.*;
javax.swing.*;
import java.util.Random;
public class MessageViewer extends JFrame implements ActionListener {
public static final int WIDTH=500,HEIGHT=300,MESSAGES=3;
private final String
baseURL = "http://troy.trincoll.edu/jjjava/messages/";
private JTextArea display = new JTextArea(20,20);
private JButton getMessage = new JButton("Get Message!");
/**
* MessageViewer() constructor sets up the user interface and
* displays the first message.
478
479
*/
public MessageViewer () {
super("Message Viewer Application");
// Set the window title
getMessage.addActionListener(this);
this.getContentPane().add("North",getMessage);
this.getContentPane().add("Center",display);
display.setLineWrap(true);
showCurrentMessage();
// Display the current home
} // MessageViewer()
/**
* readTextIntoDisplay() reads text from the supplied URL into
* a TextArea.
* @param url -- the URL giving the location of a text file.
*/
private void readTextIntoDisplay(URL url) throws IOException {
BufferedReader data
= new BufferedReader(new InputStreamReader(url.openStream()));
display.setText("");
// Reset the text area
String line = data.readLine();
while (line != null) {
// Read each line
display.append(line + "\n");
// And add it to the display
line = data.readLine();
}
data.close();
} // readTextIntoDisplay()
/**
* showCurrentMessage() cycles through 0, 1, ... MESSAGES,
* displaying each message on successive calls.
*/
private void showCurrentMessage() { // throws IOException {
URL url = null;
Random rand = new Random();
// Get random message file
int choice = (Math.abs(rand.nextInt()) % MESSAGES);
try {
url = new URL(baseURL + "message" + choice + ".txt"); // Create url
readTextIntoDisplay(url);
// Download and display text file
repaint();
} catch (MalformedURLException e) {
System.out.println( "ERROR: " + e.getMessage()) ;
} catch (IOException e) {
System.out.println("ERROR: " + e.getMessage()) ;
}
480
} // showCurrentMessage()
/**
* actionPerformed() shows the next message each time the
* button is clicked.
*/
public void actionPerformed(ActionEvent evt) {
showCurrentMessage();
}
/**
* main() creates an instance of this class and uses it
* to display some messages across the Internet.
*/
public static void main(String args[]) {
MessageViewer viewer = new MessageViewer();
viewer.setSize(viewer.WIDTH,viewer.HEIGHT);
viewer.setVisible(true);
viewer.addWindowListener(new WindowAdapter() {
// Quit the application
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
} // main()
} // MessageViewer
481
482
do {
userStr = readFromKeyboard();
// Get in-
// Send it to server
// Read the servers response
// Re// Un-
/**
* main() creates a client instance and starts it. You may need to change
*
the URL for the server.
*/
public static void main(String args[]) {
MessageClient client = new MessageClient("troy.trincoll.edu",10001);
client.start();
} // main()
} // MessageClient
/*
* File: MessageServer.java
* Author: Java, Java, Java
* Description: This Server subclass provides a message service, which
* consists of displaying lines of the files named message0.txt,
* message1.txt and message2.txt to clients.
*
* Usage: recompile this file and its superclasses after changing
* the path name of the baseURL. Place the message files in the
* directory specified for the baseURL. Then run it with: java MessageServer
*/
import java.net.*;
import java.io.*;
import java.util.Random;
public class MessageServer extends Server {
private static final int MESSAGES = 3;
483
/**
* provideService() implements the message service. It is defined abstractly
*
in the Server superclass. It defines the protocol that must be observed
*
by clients that wish to use this service.
* @param socket -- the Socket by which the client is connected
*/
protected void provideService (Socket socket) {
String str="";
try {
writeToSocket(socket, "Hello, how may I help you?\n");
do {
str = readFromSocket(socket);
if (str.toUpperCase().equals("EXIT"))
writeToSocket(socket, "Goodbye\n");
else
writeToSocket(socket, getNextMessage());
} while (!str.toUpperCase().equals("EXIT"));
} catch (IOException e) {
e.printStackTrace();
}
} // provideService()
/**
* getFileText() reads one line of the message from the designated file.
* @param url -- the files URL
* @return a String containing one line of the message
*/
private String getFileText(URL url) throws IOException {
String msg = "";
BufferedReader data
= new BufferedReader(new InputStreamReader(url.openStream()));
String line = data.readLine();
while (line != null) {
// Read each line
msg += line + "\n";
// And add it to the display
line = data.readLine();
}
data.close();
return msg;
} // getFileText()
/**
* getNextMessage() gets the next line of the message from a file whose
*
URL is constructed here.
* @return a String containing one line of the message
*/
private String getNextMessage() {
URL url = null;
484
12. Write an implementation of the scramble service. Given a word, the scramble
service will return a string containing all possible permutations of the letters in
the word. For example, given man, the scramble service will return amn, anm,
man, mna, nam, nma. Use the Server and Client classes in your design.
(See the Self-Study Exercises for a description of the design.)
Design: The solution should follow the same design as in the previous exercise.
The functionality for this service should be placed in the requestService()
and provideService() methods. A challenging part of this exercise is designing an algorithm to compute all the permutations of the letters of a string.
See the documentation in the code for details.
The program should produce something like the following output on the client
side:
CLIENT: connected to troy:10001
MESSAGE FROM SERVER: Hello, how may I help you?
Type EXIT to Quit, or type a word to send to the Scramble Server
INPUT: ajax
SERVER:
ajax ajxa aajx aaxj axja axaj jaax jaxa jaax jaxa jxaa jxaa aajx
aaxj ajax ajxa axaj axja xaja xaaj xjaa xjaa xaaj xaja
INPUT: exit
SERVER: Goodbye
CLIENT: connection closed
/*
485
* File: ScrambleServer.java
* Author: Java, Java, Java
* Description: This Server subclass provides a word scrambling service, which
* consists of calculating all the permutations of a word that is supplied by
* a client.
*
* Usage: java ScrambleServer
*
* Algorithm: The permutations are calculated recursively. For a given string,
* say "act", the algorithm takes all possible singleton prefixes -- "a", "c", "t" -* and then combines them with all permutations of the suffixes -- "ct", "at", "ac".
* The algorithm recurses on the suffixes. When the suffix is a single letter, the
* recursion stops. Heres a trace of the recursive calls for permuting "act". Note
* how the third parameter, list, carries along the list of permutations. Note
* also how the prefix is used to produce all possible permutations starting with
* one of the characters of the second parameter.
*
*
getPermutations("", "act", " ")
*
getPermutations("a", "ct", " ")
*
getPermutations("ac", "t", " ") --> "act"
*
getPermutations("at", "c", "act") --> "act atc"
*
getPermutations("c", "at", "act atc")
*
getPermutations("ca", "t", "act atc") --> "act atc cat"
*
getPermutations("ct", "a", "act atc cat") --> "act atc cat cta"
*
getPermutations("t", "ac", "act atc cat cta")
*
getPermutations("ta", "c", "act atc cat cta") -> "act atc cat cta tac"
*
getPermutations("tc", "a", "act atc cat cta") -> "act atc cat cta tac tca"
*/
import java.net.*;
import java.io.*;
import java.util.Random;
public class ScrambleServer extends Server {
public ScrambleServer( int portNum, int nBacklog)
super(portNum, nBacklog);
}
/**
486
/**
* getPermutations() recursively computes all the permutations of a string s,
*
returning the result as a string containing a list of substrings.
* @param prefix -- a substring to be combined with s to give a permutation
* @param s -- the string or substring being permuted
* @param list -- a String containing the list of permutations
*/
private String getPermutations(String prefix, String s, String list) {
if (s.length() <= 1) {
return list + " " + prefix + s;
// Base case
} else {
for (int i=0; i < s.length(); i++) {
// For each letter in s
String newPrefix = prefix + s.charAt(i); // Add it to prefix, giving new prefix
String newString = "";
if (i > 0 && i < s.length())
newString = s.substring(0,i) + s.substring(i+1); // Set string to rest of
else if (i <= 0)
newString = s.substring(1);
if (newString == "")
// Base case:
return list;
else
list = getPermutations(newPrefix, newString, list);
}
return list;
}
487
} // getPermutations()
/**
* main() creates an instance of the server and starts it.
*/
public static void main(String args[]) {
ScrambleServer server = new ScrambleServer(10001,3);
server.start();
} // main()
} // ScrambleServer
/*
* File: ScrambleClient.java
* Author: Java, Java, Java
* Description: This Client subclass provides an interface to the scramble service, which
* permutes the letters of a string passed to the service by the client. The user is
* prompted to input strings to be permuted. The servers URL is given on the command line.
*
* Usage: java ScambleClient serverURL
*/
import java.net.*;
import java.io.*;
public class ScrambleClient extends Client {
488
// Send it to server
// Read the servers response
// Re// Un-
/**
* main() creates an instance of the client and starts it. Note that
* the servers URL is given as a command line argument.
*/
public static void main(String args[]) {
ScrambleClient client = new ScrambleClient(args[0],10001);
client.start();
} // main()
} // ScrambleClient
13. Challenge: Design a Nim server that plays a two-person game of Nim. There
are many versions of Nim but heres a simple one. The game starts with 21 sticks
being thrown on the table. The players take turns picking up sticks. On each turn
the player must pick 1, 2, or 3 sticks. The player who picks up the last stick wins
the game. The server should start the game and then let the client have the first
move. The server should also announce who won the game. (The server should
be a good sport and shouldnt gloat too much when it wins!)
Design: The solution should follow the same design as in the previous exercise.
The functionality for this service should be placed in the requestService()
and provideService() methods. A challenging part of this exercise is designing an algorithm to play the game of Nim. See the documentation in the
code for details. This version of the server plays an optimal game, meaning it
will force a win if the user leaves it with a situation that is winnable. See the
documentation of the serverMove() method for details.
The program should produce something like the following output on the client
side:
CLIENT: connected to troy:10001
MESSAGE FROM SERVER: Lets Play NIM! There are 21 sticks left.
Whoever picks up the last stick wins. How many sticks do you take?
INPUT: 3
SERVER: That leaves 18 sticks. I pick up 2. 16 sticks remain.
How many sticks do you take?
INPUT: 1
SERVER: That leaves 15 sticks. I pick up 3. 12 sticks remain.
How many sticks do you take?
INPUT: 2
SERVER: That leaves 10 sticks. I pick up 2. 8 sticks remain.
489
490
/**
* main() creates an instance of the client and starts it. Note that
* the servers URL is given as a command line argument.
*/
public static void main(String args[]) {
NimClient client = new NimClient(args[0],10001);
client.start();
} // main()
} // NimClient
/*
* File: NimServer.java
* Author: Java, Java, Java
* Description: This Server subclass plays Nim with its clients.
*
* Usage: java NimServer
*
* Nim Rules: In this version the game starts with 21 sticks and whoever
* picks up the last stick loses. A player must pick up between 1 and 3
* sticks on each move. To figure its move, the server picks a random number
* between 1 and 3.
*/
import java.net.*;
import java.io.*;
import java.util.Random;
public class NimServer extends Server {
private static final int STICKS=21, MAXSTICKS=3, MINSTICKS=1;
private int sticksLeft = STICKS;
private boolean gameOver = false;
public NimServer(int portNum, int nBacklog)
super(portNum, nBacklog);
}
/**
* provideService() implements the Nim service. It is defined abstractly
*
in the Server superclass. It defines the protocol that must be observed
*
by clients that wish to use this service.
* @param socket -- the Socket by which the client is connected
*/
protected void provideService (Socket socket) {
sticksLeft = STICKS;
// Initialize the game
gameOver = false;
491
String str="";
try {
writeToSocket(socket, "Lets Play NIM! There are " + sticksLeft + " sticks left."
+ " Whoever picks up the last stick wins.\n");
do {
if (!gameOver)
str = readFromSocket(socket);
if (str.toUpperCase().equals("EXIT"))
writeToSocket(socket, "Goodbye\n");
else
writeToSocket(socket, doMove(str));
} while (!gameOver);
} catch (IOException e) {
e.printStackTrace();
}
} // provideServer()
/**
* doMove() makes a single move in the Nim game, where the
* clients move is given as the parameter.
* @param str -- a String giving the clients move, which must be between MIN and MAX
* @return a String giving the servers move
*/
private String doMove(String str) throws IOException {
int clientMove = Integer.parseInt(str);
if ((clientMove <= MAXSTICKS) && (clientMove >= MINSTICKS)
&& (clientMove <= sticksLeft)) {
sticksLeft -= clientMove;
if (sticksLeft <= 0) {
gameOver = true;
return("You picked up the last stick. You win!");
} else {
String retMsg = "That leaves " + sticksLeft + " sticks. ";
int serverMove = serverMove(sticksLeft);
sticksLeft -= serverMove;
if (sticksLeft <= 0) {
gameOver = true;
return(retMsg + "I pick up " + serverMove
+ ". Theres no more sticks. I win!");
} else
return (retMsg + "I pick up " + serverMove + ". "
+ sticksLeft + " sticks remain.");
}
} else
return("Illegal Move. Please Try Again.");
} // doMove()
492
/**
* serverMove() finds the best move for the server given the
* number of remaining sticks. Assuming that the player who picks up
* the last stick wins, the server wants to leave the client with
* 0, 4, 8, 12, 16, 20 sticks. If the server can make such a move, it
* does. Otherwise it just takes between MIN and MAX sticks.
* @param nSticks -- an int giving the number of sticks left
* @return an int giving the servers move
*/
private int serverMove(int nSticks) {
int take = MINSTICKS
+ (int)(Math.random() * Math.min(sticksLeft, MAXSTICKS)); // Default move
for (int k = MINSTICKS; k <= MAXSTICKS; k++)
if ((nSticks - k) % (MAXSTICKS+1) == 0) { // true if (nSticksk) is 0,4,8, ...
take = k;
break;
}
return take;
}
/**
* main() creates an instance of the server and starts it.
*/
public static void main(String args[]) {
NimServer server = new NimServer(10001,3);
server.start();
} // main()
} // NimServer
14. Challenge: Modify the previous program so that the client and server can negotiate the rules of the game, including how many sticks, how many pick-ups per
turn, and who goes first.
Design: The solution should follow the same design as in the previous exercise. Whats different here is that the protocol between client and server must be
extended in order to negotiate the rules of the game.
The program should produce something like the following output on the client
side:
CLIENT: connected to troy:10001
MESSAGE FROM SERVER: Lets play NIM. Whoever picks up the last stick wins.
Lets decide the rules. How many sticks do you want to play with?
INPUT: 15
SERVER: How many sticks can we pick up per turn?
INPUT: 3
SERVER: Who should go first? (YOU or ME)
493
INPUT: me
SERVER: The rules are 15 sticks, 3 max sticks per move. You first. Okay?
INPUT: okay
SERVER: Your move first. How many sticks do you take?
INPUT: 2
SERVER: That leaves 13 sticks. I pick up 1. 12 sticks remain. How many sticks do you take?
INPUT: 1
SERVER: That leaves 11 sticks. I pick up 3. 8 sticks remain. How many sticks do you take?
INPUT: 2
SERVER: That leaves 6 sticks. I pick up 2. 4 sticks remain. How many sticks do you take?
INPUT: 1
SERVER: That leaves 3 sticks. I pick up 3. Theres no more sticks. I win!
CLIENT: connection closed
/*
* File: NimServer.java
* Author: Java, Java, Java
* Description: This Server subclass plays Nim with its clients. In this version
* the client is invited to set the rules of the game, including how many sticks,
* the number of sticks per turn, and who goes first.
*
* Usage: java NimServer
*
* Nim Rules: In this version the game starts with STICKS sticks and whoever
* picks up the last stick wins. A player must pick up between 1 and MAXSTICKS
* sticks on each move.
*/
import java.net.*;
import java.io.*;
import java.util.Random;
public class NimServer extends Server {
private int STICKS=21, MAXSTICKS=3, MINSTICKS=1; // These will be set by client
private int sticksLeft = STICKS;
private boolean serverFirst = false;
// Will be set by client
private boolean gameOver = false;
public NimServer(int portNum, int nBacklog)
super(portNum, nBacklog);
}
494
495
} while (!gameOver);
} catch (IOException e) {
e.printStackTrace();
}
} // provideServer()
/**
* doMove() makes a single move in the Nim game, where the
* clients move is given as the parameter. If an empty string is passed,
* then the server just does its own move.
* @param str -- a String giving the clients move, which must be between MIN and MAX
* @return a String giving the servers move
*/
private String doMove(String str) throws IOException {
if (str.equals(""))
return doServerMove();
int clientMove = Integer.parseInt(str);
if ((clientMove <= MAXSTICKS) && (clientMove >= MINSTICKS)
&& (clientMove <= sticksLeft)) {
sticksLeft -= clientMove;
if (sticksLeft <= 0) {
gameOver = true;
return("You picked up the last stick. You win!");
} else
return doServerMove();
} else
return("Illegal Move. Please Try Again.");
} // doMove()
/**
* doServerMove() constructs the message that must be returned after a server move.
* @return a String describing the servers move
*/
private String doServerMove() throws IOException {
String retMsg = "That leaves " + sticksLeft + " sticks. ";
int serverMove = serverMove(sticksLeft);
sticksLeft -= serverMove;
if (sticksLeft <= 0) {
gameOver = true;
return(retMsg + "I pick up " + serverMove
+ ". Theres no more sticks. I win!");
} else
return (retMsg + "I pick up " + serverMove
+ ". " + sticksLeft + " sticks remain.");
} // doServerMove()
496
/**
* serverMove() finds the best move for the server given the
* number of remaining sticks. Assuming that the player who picks up
* the last stick wins, the server wants to leave the client with
* 0, 4, 8, 12, 16, 20 sticks. If the server can make such a move, it
* does. Otherwise it just takes between MIN and MAX sticks.
* @param nSticks -- an int giving the number of sticks left
* @return an int giving the servers move
*/
private int serverMove(int nSticks) {
int take = MINSTICKS
+ (int)(Math.random() * Math.min(sticksLeft, MAXSTICKS)); // Default move
for (int k = MINSTICKS; k <= MAXSTICKS; k++)
if ((nSticks - k) % (MAXSTICKS+1) == 0) { // true if (nSticksk) is 0,4,8, ...
take = k;
break;
}
return take;
}
/**
* main() creates an instance of the server and starts it.
*/
public static void main(String args[]) {
NimServer server = new NimServer(10001,3);
server.start();
} // main()
} // NimServer
/*
* File: NimClient.java
* Author: Java, Java, Java
* Description: This Client subclass provides an interface to the Nim service, which
* plays a game of Nim with the user. The servers URL is supplied on the command line.
*
* Usage: java NimClient serverURL
*/
import java.net.*;
import java.io.*;
public class NimClient extends Client {
public NimClient(String url, int port) {
super(url, port);
}
497
/**
* requestService() defines the protocol that must be observed to interact
* with ScrambleServer. It is defined abstractly in the Client superclass.
* @param socket -- the Socket used to connect to the server.
*/
protected void requestService(Socket socket) throws IOException {
String servStr = readFromSocket(socket);
// Check for "Hello"
System.out.println("MESSAGE FROM SERVER: " + servStr); // Report the servers response
String userStr = "";
do {
userStr = readFromKeyboard();
// Get input from user
writeToSocket(socket, userStr + "\n");
// Send it to server
servStr = readFromSocket(socket);
// Read the servers response
System.out.println("SERVER: " + servStr);
// Report the servers response
} while (servStr.indexOf("win") == -1);
// Until game over
} // requestService()
/**
* main() creates an instance of the client and starts it. Note that
* the servers URL is given as a command line argument.
*/
public static void main(String args[]) {
NimClient client = new NimClient(args[0],10001);
client.start();
} // main()
} // NimClient
15. Challenge: Design a CyberPet protocol and use it to establish a two-way conversation between two CyberPets. One pet will have to play the role of the server
and the other the role of the client. Use the protocol to let two CyberPets carry
on a simple exchange of information what is their favorite food.
Design: We create a CyberPetSever subclass of Server and a CyberPetClient subclass of Client to manage the protocols. This means we
implement the requestService() and provideService() methods in
these classes to carry on a scripted conversation between two CyberPets.
One unique feature of the CyberPetServer and CyberPetClient classes
is that each contains a reference to a CyberPet and a constructor which lets a
server or client be created by a cyber pet. In turn, CyberPet class is modified
so that a pet has a reference to either a server or a client. We add a constructor
method that lets a pet be created as either a client or server. To test this design we
add a main() method to CyberPet which lets the user create either a server
pet or a client pet by supplying the appropriate command line arguments.
The program produces the following type of output from the client side:
$ java CyberPet client troy
CLIENT: connected to troy:10001
Me: Whats Your Name, CyberPet?
Plato: Why, its Plato, Thanks for asking! Whats yours?
Me: Its Socrates. Hey -- what is your favorite food?
Plato: Oh, I absolutely LOVE apples! You?!
Me: That sounds good, but my favorite is gummy bears. See ya!
CLIENT: connection closed
/*
* File: CyberPet.java
* Author: Java, Java, Java
* Description: This version of the CyberPet class contains a
* reference to a CyberPetClient and a CyberPetServer which enables
* two CyberPets to communicate across a network. A new constructor
* is added to enable a CyberPets name and food to be specified.
* Finally, startClient() and startServer() methods have been added
* which are used to set up a channel between two CyberPets.
* Usage: java CyberPet client serverURL
* Usage: java CyberPet server
*/
public class CyberPet {
public static final int EATING = 0;
// Class constants
public static final int SLEEPING = 1;
public static final int THINKING = 2;
private int petState;
private String name;
private String food;
// Instance variables
498
499
*
a reference to this CyberPet is passed to the CyberPetClient.
*
This enables the server to communicate with this CyberPet via
*
callback methods.
* @param url -- a string giving the servers URL
* @param port -- an int giving the servers port number
*/
public void startClient(String url, int port) {
client = new CyberPetClient(url, port, this);
client.start();
}
/**
* startServer( port) starts a CyberPetServer at a given port.
*
A reference to this CyberPet is passed to the CyberPetServer.
*
to enable the server to communicate with this CyberPet via
*
callback methods.
* @param port -- an int giving the servers port number
*/
public void startServer(int port) {
server = new CyberPetServer(port, 3, this); // 3 is number of backlogs
server.start();
}
/**
* setName() sets the CyberPets name.
* @param str -- a string giving the pets name
*/
public void setName(String str) {
name = str;
} // setName()
/**
* getName() returns the CyberPets name.
* @return -- a string giving the CyberPets name
*/
public String getName() {
return name;
} // getName()
/**
* setFood() sets the CyberPets food
* @param str -- a string giving the pets food
*/
public void setFood(String str) {
food = str;
} // setFood()
500
/**
* getFood() returns the CyberPets food.
* @return -- a string giving the CyberPets food
*/
public String getFood() {
return food;
} // getFood()
/**
* eat() sets the pets state to EATING
*/
public void eat() {
petState = EATING;
} // eat()
/**
* sleep() sets the pets state to SLEEPING
*/
public void sleep() {
petState = SLEEPING;
} // sleep()
/**
* think() sets the pets state to THINKING
*/
public void think() {
petState = THINKING;
} // think()
/**
* toString() returns a string representation of CyberPet
*/
public String toString() {
return "I am a CyberPet named " + name;
}
/**
* getState() returns the pets state
* @return a String representing the pets state
*/
public String getState() {
if (petState == EATING)
return "Eating";
// Exit the method
if (petState == SLEEPING)
return "Sleeping";
// Exit the method
if (petState == THINKING)
return "Thinking";
return "Error in State";
// Exit the method
} // getState()
501
502
/**
* main() creates an instance of the CyberPet and sets it up as
* either a client or server depending on the command line argument.
*/
public static void main(String args[]) {
if (args[0].equals("client")) {
CyberPet pet = new CyberPet("Socrates", "gummy bears");
pet.startClient(args[1], 10001);
} else {
CyberPet pet = new CyberPet("Plato", "apples");
pet.startServer(10001);
}
} // main()
} // CyberPet
/*
* File: CyberPetClient.java
* Author: Java, Java, Java
* Description: This Client subclass carries on a simple conversation with a CyberPetserver.
*
*/
import java.net.*;
import java.io.*;
public class CyberPetClient extends Client {
private CyberPet myPet; // The CyberPet who started the client session
/**
* CyberPetClient() creates a Client session and makes a connection to the
*
CyberPetServer at a given url and port.
* @param url -- a String giving the servers URL
* @param port -- an int giving the servers port
* @param pet -- a reference to the CyberPet who started the server
*/
public CyberPetClient(String url, int port, CyberPet pet) {
super(url, port);
myPet = pet;
} // CyberPetClient()
/**
* requestService() defines the protocol that must be observed to interact
* with CyberPetServer.
* Callback methods (myPet.getName(), myPet.getFood()) are used to get
*
information from the associated CyberPet.
* @param socket -- the Socket used to connect to the server.
503
*/
protected void requestService(Socket socket) throws IOException {
String friendName;
System.out.println("Me: Whats Your Name, CyberPet?");
String servStr = readFromSocket(socket);
System.out.println(servStr + ": Why, its " + servStr + ", Thanks for asking! Whats yours?");
friendName = servStr;
writeToSocket(socket, myPet.getName() + "\n");
System.out.println("Me: Its " + myPet.getName() + ". Hey - what is your favorite food?");
servStr = readFromSocket(socket);
System.out.println(friendName + ": Oh, I absolutely LOVE " + servStr + "! You?!");
writeToSocket(socket, myPet.getFood() + "\n");
System.out.println("Me: That sounds good, but my favorite is " + myPet.getFood() + ". See ya!");
socket.close();
} // requestService()
} // CyberPetClient
/*
* File: CyberPetServer.java
* Author: Java, Java, Java
* Description: This Server establishes a protocol for conversing between
* two CyberPets.
*/
import java.net.*;
import java.io.*;
import java.util.Random;
public class CyberPetServer extends Server {
private CyberPet myPet;
ated the service.
/**
* CyberPetServer() creates a Server and listens for connections on port.
* @param port -- an int giving the servers port
* @param nBacklog -- an int giving the number of clients that can be backlogged
* @param pet -- a reference to the CyberPet who started the server
*/
public CyberPetServer( int portNum, int nBacklog, CyberPet pet) {
super(portNum, nBacklog);
myPet = pet;
}
504
/**
* provideService() implements the CyberPet protocol. Note the use
*
use of callback methods (myPet.getName(), myPet.getFood()) to get
*
information from the associated CyberPet.
* @param socket -- the Socket by which the client is connected
*/
protected void provideService (Socket socket) {
String str="";
try {
String friendName;
System.out.println("Stranger: Whats Your Name, CyberPet?");
writeToSocket(socket, Name + "\n");
System.out.println("Me: Why, its " + myPet.getName() + ", Thanks for asking! Whats yours?");
str = readFromSocket(socket);
friendName = str;
System.out.println(str + ": Its " + str + ". Hey - what is your favorite food?");
writeToSocket(socket, myPet.getFood() + "\n");
System.out.println("Me: Oh, I absolutely LOVE " + myPet.getFood() + "! You?!");
str = readFromSocket(socket);
System.out.println(friendName + ": That sounds good, but my favorite is " + str + ". See ya!");
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // provideService()
} // CyberPetServer
16. Challenge: CyberPets need a registry to help them select food gifts for each
other. Design and implement a registry service. The service should let a CyberPet register itself by giving its name and its favorite food. A CyberPet can
also request the server to tell it another CyberPets favorite food. Design a client
program that acts as an interface to the registry server.
Design: This program uses the same basic design described in the previous exercise. What changes here are the details of the requestService() and
provideService() methods. The former now provides a menu to the user
which lets the user register a gift or lookup a gift in the registry. The server
responds to requests to register or look up gifts in the registry, and keeps a list
of the current gifts. In this version the server keeps the registry as an internal
data structure. A more sophisticated design would store the registry in an external file, so that the registry would survive multiple server sessions. The registry
does however survive multiple client sessions.
The program produces the following type of output from the client side. In this
example the CyberPet that is making the request is named Socrates. The exam-
ple shows three separate client sessions. The server (whose output is not shown)
persists through the three sections.
$ java CyberPet client troy
CLIENT: connected to troy:10001
Connected to Cyberpet Registry Service.
1) Register a CyberPet
2) Lookup a CyberPet
INPUT: 1
Name INPUT: Plato
Food INPUT: banana
Thank you Socrates
CLIENT: connection closed
$ java CyberPet client troy
CLIENT: connected to troy:10001
Connected to Cyberpet Registry Service.
1) Register a CyberPet
2) Lookup a CyberPet
INPUT: 1
Name INPUT: Socrates
Food INPUT: apple
Thank you Socrates
CLIENT: connection closed
$ java CyberPet client troy
CLIENT: connected to troy:10001
Connected to Cyberpet Registry Service.
1) Register a CyberPet
2) Lookup a CyberPet
INPUT: 2
Name INPUT: Plato
Platos Registered Food Is banana
Thank you Socrates
CLIENT: connection closed
/*
* File: CyberPetServer.java
* Author: Java, Java, Java
* Description: This Server establishes a registry for keeping track of
* CyberPets. It handles two commands -- REGISTER and LOOKUP. It keeps
* track of a pets name and favorite food in two parallel arrays.
*
* It is intended to be used as an instance variable of a CyberPet.
*/
import java.net.*;
import java.io.*;
public class CyberPetServer extends Server {
505
506
/**
* CyberPetServer() creates a Server and listens for connections on port.
* @param port -- an int giving the servers port
* @param nBacklog -- an int giving the number of clients that can be backlogged
* @param pet -- a reference to the CyberPet who started the server
*/
public CyberPetServer( int portNum, int nBacklog, CyberPet pet) {
super(portNum, nBacklog);
myPet = pet;
}
/**
* provideService() implements the CyberPet accepts requests from the client
*
through a socket and calls the appropriate handler.
* @param socket -- the Socket by which the client is connected
*/
protected void provideService (Socket socket) {
String RequestType="";
try {
RequestType = readFromSocket(socket);
if (RequestType.equals("LOOKUP"))
handleLookup(socket);
else if (RequestType.equals("REGISTER"))
handleRegister(socket);
} catch (IOException e) {
e.printStackTrace();
}
} // provideService()
/**
* handleRegister() makes an entry into the pet registry.
* @param socket -- the Socket by which the client is connected
*/
protected void handleRegister (Socket socket) {
String name = "", food = "";
try {
name = readFromSocket(socket);
507
food = readFromSocket(socket);
registryPutEntry(name, food);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // handleRegister()
/**
* handleLookup() looks up a pets favorite food given its name.
* @param socket -- the Socket by which the client is connected
*/
protected void handleLookup (Socket socket) {
String name = "", food = "";
try {
name = readFromSocket(socket);
food = registryGetFood(name);
writeToSocket(socket, food);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // handleLookup()
/**
* registryPutEntry() inserts its parameters in the registry
* @param name -- a String that goes into the regNames array
* @param food -- a String that goes into the regFoods array
*/
private void registryPutEntry(String name, String food) {
if (nEntries < MAXPETS) {
regNames[nEntries] = name;
regFoods[nEntries] = food;
++nEntries;
}
} // registryPutNames()
/**
* registryGetFood() looks up a food in the registry given a name
* @param name -- a String that gives the name to search for
* @return a String that gives the food associated with the name
*/
private String registryGetFood(String name) {
for (int k = 0; k < nEntries; k++)
// For each name entry
if (regNames[k].equals(name))
// If it matches the given name
return regFoods[k];
//
Return it
return "Sorry. Name not found.";
} // registryGetFood()
} // CyberPetServer
508
/*
* File: CyberPetClient.java
* Author: Java, Java, Java
* Description: This Client can be used by a CyberPet to make an entry
* in the registry maintained by the CyberPetServer. It is intended to be
* used as an instance variable of a CyberPet. It provides a simple menu
* that lets the user either REGISTER or LOOKUP this CyberPets data.
* This particular implementation just illustrates the potential of the
* client. A more useful client would be able to register any CyberPet.
*
*/
import java.net.*;
import java.io.*;
public class CyberPetClient extends Client {
private CyberPet myPet; // The CyberPet who started the client session
/**
* CyberPetClient() creates a Client session and makes a connection to the
*
CyberPetServer at a given url and port.
* @param url -- a String giving the servers URL
* @param port -- an int giving the servers port
* @param pet -- a reference to the CyberPet who started the server
*/
public CyberPetClient(String url, int port, CyberPet pet) {
super(url, port);
myPet = pet;
} // CyberPetClient()
/**
* requestService() defines the protocol that must be observed to interact
* with CyberPetServer.
* @param socket -- the Socket used to connect to the server.
*/
protected void requestService(Socket socket) throws IOException {
int choice = 0;
System.out.println("Connected to Cyberpet Registry Service.");
System.out.println("
1) Register a CyberPet");
System.out.println("
2) Lookup a CyberPet");
choice = Integer.parseInt(readFromKeyboard());
if (choice == 1)
handleRegister(socket);
else if(choice == 2)
handleLookup(socket);
} // requestService()
/**
* handleRegister() registers a pet with the registry. The user
* inputs the pets name and food.
* A Callback method (myPet.getName()) is used to get the
*
name of the pet that is making the request.
* @param socket -- the Socket used to connect to the server.
*/
protected void handleRegister (Socket socket) {
String name = "", food = "";
try {
writeToSocket(socket, "REGISTER");
System.out.print("Name ");
name = readFromKeyboard();
writeToSocket(socket, name);
System.out.print("Food ");
food = readFromKeyboard();
writeToSocket(socket, food);
System.out.println("Thank you " + myPet.getName());
} catch (IOException e) {
e.printStackTrace();
}
} // handleRegister()
/**
* handleLookup() looks up this pets favorite food in the registry.
* A Callback method (myPet.getName()) is used to get the
*
name of the pet that is making the request.
* @param socket -- the Socket used to connect to the server.
*/
protected void handleLookup (Socket socket) {
String name = "", food = "";
try {
writeToSocket(socket, "LOOKUP");
System.out.print("Name ");
name = readFromKeyboard();
writeToSocket(socket, name);
food = readFromSocket(socket);
System.out.println(name + "s Registered Food Is " + food);
System.out.println("Thank you " + myPet.getName());
} catch (IOException e) {
e.printStackTrace();
}
} // handleLookup()
} // CyberPetClient
509
510
Exercise 15.8
Exercise 15.10
interface
Runnable
JApplet
interface
ActionListener
JFrame
SlideShowApplet
MessageViewer
Timer
+messageViewer(in g : Graphics)
-readTextIntoDisplay(in url : URL)
-showCurrentMessage()
+actionPerformed(in evt : ActionEvent)
+main(in args : String[])
+paint(in g : Graphics)
+nextSlide()
+init()
Uses
Exercise 15.9
JFrame
Exercise 15.11
interface
ActionListener
CryptoViewer
+WIDTH : int = 500
+HEIGHT : int = 400
+MESSAGES : int = 1
-ReplacementAlphabet : String
-ALPHABET : String
-p1 : JPanel
-p2 : JPanel
-p3 : JPanel
-p4 : JPanel
-p5 : JPanel
-p6 : JPanel
-p7 : JPanel
-label0 : JLabel
-label1 : JLabel
-label2 : JLabel
-oldLetter : JComboBox
-newLetter : JComboBox
-go : JButton
-display : JTextArea
-display2 : JTextArea
-getCrypto : JButton
+CyrptoViewer()
-initLetterChoices()
-readTextIntoDisplay(in url : URL)
-getSolution(in url : URL)
-showCurrentCrypto()
-updateDisplay2()
+actionPerformed(in evt : ActionEvent)
+main(in args : String[])
Server
Client
MessageServer
MessageClient
-MESSAGES : int = 3
-baseURL : String = 3
+MessageServer(in portNum : int, in nBackLog : int)
#provideService(in socket : Socket)
-getFileText(in url : URL) : String
-getNextMessage() : String
+main(in args : String[])
Communicates
datatype
Image[]
Miscellaneous Types
JTextArea
datatype
String[]
datatype
URL[]
JComboBox
Image
JButton
URL
Socket
ActionEvent
JLabel
Graphics
JPanel
511
Exercise 15.12
Client
Server
ScrambleClient
ScrambledServer
Communicates
Miscellaneous
Types
Socket
datatype
String[]
Exercise 15.13
Server
Client
MessageServer
NimClient
-STICKS : int = 21
-MAXSTICKS : int = 3
-MINSTICKS : int = 1
-sticksLeft : int = STICKS
-gameOver : boolean = false
+NimServer(in portNum : int, in nBackLog : int)
#provideService(in socket : Socket)
-doMove(in str : String) : String
-serverMove(in nSticks : int) : int
+main(in args : String[])
Communicates
Exercise 15.14
Server
Client
MessageServer
NimClient
-STICKS : int = 21
-MAXSTICKS : int = 3
-MINSTICKS : int = 1
-sticksLeft : int = STICKS
-serverFirst : boolean = false
-gameOver : boolean = false
+NimServer(in portNum : int, in nBackLog : int)
-negotiateRules(in socket : Socket)
#provideService(in socket : Socket)
-doMove(in str : String) : String
-doServerMove() : String
-serverMove(in nSticks : int) : int
+main(in args : String[])
Communicates
512
Exercise 15.15
Client
CyberPet
CyberPetClient
-myPet : CyberPet
Server
Uses
Miscellaneous Types
datatype
String[]
Socket
+EATING : int = 0
+SLEEPING : int = 1
+THINKING : int = 2
-petState : int
-name : String
-food : String
-server
-client
+CyberPet(in str : String)
+CyberPet(in str1 : String, in str2 : String)
+CyberPet(in str : String, in state : int)
+CyberPet(in str : String, in sleeping : Boolean)
+startClient(in url : String, in port : int)
+startServer(in port : int)
+setName(in str : String)
+getName() : String
+setFood(in str : String)
+getFood() : String
+eat()
+sleep()
+think()
+toString() : String
+getState() : String
+main(in args : String)
Exercise 15.16
Client
CyberPet
Server
CyberPetClient
-myPet : CyberPet
+CyberPetClient(in url : String, in port : int, in pet : CyberPet)
#requestService(in socket : Socket)
#handleRegister(in socket : Socket)
#handleLookup(in socket : Socket)
CyberPetServer
+MAXPETS : int = 20
-nEntries : int = 0
-myPet : CyberPet
-regNames : String[]
-regFoods : String[]
+CyberPetServer(in portNum : int, in nBackLog : int, in pet : CyberPet)
#provideService(in socket : Socket)
#handleRegister(in socket : Socket)
#handleLookup(in socket : Socket)
-registryPutEntry(in name : String, in food : String)
-getFood(in name : String) : String
+EATING : int = 0
+SLEEPING : int = 1
+THINKING : int = 2
-petState : int
-name : String
-food : String
-server
-client
+CyberPet(in str : String)
+CyberPet(in str1 : String, in str2 : String)
+CyberPet(in str : String, in state : int)
+CyberPet(in str : String, in sleeping : boolean)
+startClient(in url : String, in port : int)
+startServer(in port : int)
+setName(in str : String)
+getName() : String
+setFood(in str : String)
+getFood() : String
+eat()
+sleep()
+think()
+toString() : String
+getState() : String
+main(in args : String)
Communicates
Uses
Uses
Chapter 16
513
and
. Answer:
514
(b) An object that contains a variable that refers to an object of the same class
is a
. Answer: self-referential object
(c) One application for a
is to manage the method call and returns in a
computer program. Answer: stack
(d) One application for a
is to balance the parentheses in an arithmetic
expression. Answer: stack
(e) A
operation is one that starts at the beginning of a list and processes
each element. Answer: traversal
(f) A vector is an example of a
. Answer: null
3. Add a removeAt() method to the List class to return the object at a certain
index location in the list. This method should take an int parameter, specifying
the objects position in the list, and it should return an Object.
/**
* removeAt() destructively removes the node at a given
sition. The
*
algorithm requires that the list be traversed until
*
position is reached.
* @param position -- an int giving the nodes position
* @return a reference to the Object removed
*/
public Object removeAt (int position) {
if (isEmpty())
// Special case:
return null;
Node current = head;
// Special case:
gleton list
if (current.getNext() == null) {
head = null;
return current;
}
pothe desired
empty list
sin-
515
4. Add an insertAt() method to the List class that will insert an object at a
position in the list. This method should take two parameters, the Object to be
inserted, and an int to designate where to insert it. It should return a boolean
to indicate whether the insertion was successful.
/**
* insertAt() inserts a new node at a certain position within the list
* @param newNode -- the Object to be inserted
* @param position -- the location to insert at
* @return -- a boolean indicating whether the insertion was successful
*/
public boolean insertAt (Object newNode, int position) {
if (isEmpty()) {
// For empty list
Node newHead = new Node(newNode); //
just insert at head
head = newHead;
return true;
}
Node current = head;
if (position == 0) {
// Insert at the front
Node newHead = new Node(newNode);
newHead.setNext(current);
return true;
}
Node previous = null;
// Traverse the list
int counter = 0;
while ((current.getNext() != null) && (counter < position)) {
previous = current;
current = current.getNext();
counter++;
}
if (counter == position) {
// If desired position is reached
Node temp = new Node(newNode);
//
insert the new node.
previous.setNext(temp);
temp.setNext(current);
return true;
}
return false;
} // insertAt()
5. Add a removeAll() method to the List class. This void method should
remove all the members of the list.
/**
* removeAll() removes all elements of the list by simply setting its
*
head to null. Javas automatic garbage collector takes care of
*
reclaiming the memory occupied by the lists objects.
*/
public void removeAll() {
head = null;
} // removeAll()
6. Write an int method named size() that returns the number of elements in a
List
/**
* size() returns the number of elements in the list
* @return an int giving the number of elements
*/
public int size() {
int counter = 0;
Node current = head;
while (current != null) {
current = current.getNext();
counter++;
}
return counter;
} // size()
8. The head of a list is the first element in the list. The tail of a list consists of
all the elements except the head. Write a method named tail() that returns a
reference to the tail of the list. Its return value should be Node.
/**
516
9. Write a program that uses the List ADT to store a list of 100 random floatingpoint numbers. Write methods to calculate the average of the numbers.
Design: A good object-oriented design for this solution is to create a subclass
of List called NumberList, which is designed to store numbers. Its main
feature is a method, getAverage(), to compute the average of the numbers
stored in the list. (Of course, it could easily be extended to contain other useful
number-processing methods.)
The getAverage() method will traverse the list, beginning at its head, adding
each value to a running total. In order to effect this design, the head variable
must be made protected (instead of private) so it can be referenced in the
subclass. So we make the following revision to the List class:
protected Node head;
517
518
10. Write a program that uses the List ADT to store a list of Student records,
using a variation of the Student class defined in Chapter 14. Write a method
to calculate the average grade point average for all students in the list.
Design: As in the previous exercise, the StudentList class extends the
List class. It contains a method, calcAvgGPA() to calculate the average
grade-point average. The head variable must be declared protected in order
to extend the List class in this way.
/*
* File: StudentList.java
* Author: Java, Java, Java
* Description: This subclass of List implements a list
* of student records. Each Student record consists of
* a name, year and gpa field. (The Student class defined
* in Chapter 14 is used. The only change to that class is
* to add a getGPA() access method.
*
* Note that this class depends on the version of List and Node
* that were defined in the previous exercise. The List class
* must contain a public instance variable named head.
*/
public class StudentList extends List {
/**
* calcAvgGPA() calculates the average GPA of all students
* in the list. Note that it is necessary to convert the
* Nodes data to (Student) before getGPA() can be called.
* @return a double giving the average GPA
*/
public double calcAvgGPA() {
int counter = 0;
double sum = 0;
Node current = head;
while (current != null) {
sum += ((Student)current.getData()).getGPA();
counter++;
current = current.getNext();
}
return sum / counter;
}
/**
* main() creates a linked list of students and then tests
*
the calcGPA() method.
*/
public static void main( String argv[] ) {
519
520
11. Write a program that creates a copy of a List. It is necessary to copy each
node of the list. This will require that you create new nodes that are copies of
the nodes in the original list. To simplify this task, define a copy constructor for
your node class and then use that to make copies of each node of the list.
Design: In the Node class we want to add a constructor method that makes a
new node from a copy of an existing node:
/**
* Node() copy constructor makes a new node as a copy of
* an existing node.
* @param obj -- a reference to an Object
*/
public Node(Node node) { // Constructor
data = node.data;
next = node.next;
}
Then in the List class, we want to add a method that returns a reference to a
List which is made by copying each of the nodes of an existing list. By placing
this method in the List class, you are giving objects of that class the ability to
clone themselves:
521
/**
* getCopy() creates a copy of each node of the list
* and links them together into a duplicate of the original
* list. It then returns a pointer to the head of the new list.
* @return a reference to the head of new list
*/
public List getCopy() {
List newList = new List();
Node current = head;
while(current != null) {
// For each node in the list
newList.insertAtRear(new Node(current)); // make a copy of it
current = current.getNext();
}
return newList;
// Return a reference to the new list
} // getCopy()
Given these changes to Node and List, we can now obtain a copy of any list
using the following command:
List copyOfOldList = oldList.getCopy();
The following program tests our copy making ability by creating a list, making
a copy of it, destroying the original list, and then printing the copy. This shows
that the copy survived the destruction of the original list.
/* File: TestCopy.java
* Author: Java, Java, Java
* Description: This class uses an instance of the List ADT
* to create a list of floating point numbers. It then makes
* a copy of the list and prints the copy.
*
* This program requires that the Node class be modified to
* include a copy constructor of the form Node(Node). And that
* the List class is modified to include a getCopy() method.
*/
public class TestCopy {
private java.util.Random generator = new java.util.Random();
private List list = new List(); // The internal list
/**
* fillList() creates 10 random doubles and inserts them.
* into the list. It uses an instance of the java.util.Random
* class to generate random doubles.
*/
public void fillList() {
for(int x = 0; x < 10; x++) {
double n = generator.nextDouble() * 100;
list.insertAtRear(new Double(n));
}
} // fillList()
/**
* printCopy() creates a copy of the original list. Then it
* removes all the nodes from the original list. Finally it prints
* the copy of the original list, showing that the nodes in the
* original list were indeed copied, not merely doubly referenced.
*/
public void printCopy() {
List copy = list.getCopy();
System.out.println("Printing the original list");
list.print();
while (!list.isEmpty()) {
list.removeFirst();
// Remove each node
}
System.out.println("Printing the original list after removing all its nodes");
list.print();
System.out.println("Now printing the copy of the original list");
copy.print();
} // printCopy()
/**
* main() creates an instance of this class and tests its methods.
*/
public static void main(String args[]) {
TestCopy app = new TestCopy();
app.fillList();
app.printCopy();
} // main()
} // TestCopy
12. Write a program that uses a Stack ADT to determine if a string is a palindrome
spelled the same way backwards and forwards.
Design: A stack is ideally suited for this task because it is ideally suited for
reversing a string. isPalindrome() algorithm simply pushes each letter of
the string onto the stack, then it repeatedly pops the stack, comparing the characters with the letters in the original string. Having stored the characters in a stack
means that it is comparing the last letter with the first, the second-to-last with the
second, and so on.
/*
* File: PalindromeTester.java
* Author: Java, Java, Java
* Description: This class tests the isPalindrome() method,
* which uses a Stack to test whether a string is a palindrome.
522
523
13. Design and write a program that uses a Stack to determine whether a parenthesized expression is well formed. Such an expression is well formed only if there
is a closing parenthesis for each opening parenthesis.
Design: A stack is ideally suited for this task because parentheses follow a last-
524
in-first-out protocol. Processing the string left to right, each time a left parenthesis is encountered, it is pushed onto the stack. Each time a right parenthesis is
encountered the stack is popped. In a balanced expression, the stack should be
empty when you run out of letters in the string and not before.
/*
* File: ParenthesisChecker.java
* Author: Java, Java, Java
* Description: This program uses a Stack ADT to determine if expressions
* entered on the command line contained balanced parentheses. The algorithm
* makes use of the Stacks LIFO behavior.
*
* Usage: java ParenthesisChecker expression
*/
public class ParenthesisChecker {
/**
* isBalanced() returns true if its parameter contains balanced
* parentheses. The string is processed from left to right, char
* by char. Each time a left parens is found, it is pushed on the
* stack. Each time a right parens is found, the stack is popped.
* If an attempt to pop is made on an empty stack, thats an error
* caused by too many right parens. If the stack is not empty at
* the end, the string contains too many left parens.
* Note how data popped from the stack must be coerced from Object to Node
* and then from Node to Character.
* @param s -- the String to be tested
* @return true if s has balanced parentheses
*/
public boolean isBalanced(String s) {
Stack stack = new Stack();
for(int k = 0; k < s.length(); k++) {
if (s.charAt(k) == ()
// Push each left parens
stack.push(new Object());
else if (s.charAt(k) == )) {
if (stack.isEmpty())
return false; // Too many right parens
else
stack.pop();
}
}
return (stack.isEmpty()); // Stack should be empty
} // isBalanced()
/**
* main() creates an instance of this class and tests its
* isBalanced() method. The expression to be tested is input
* as a command-line argument.
525
*/
public static void main (String args[]) {
ParenthesisChecker app = new ParenthesisChecker();
String exp = args[0];
System.out.println("isBalanced (" + exp + ") returned " + app.isBalanced(exp));
} // main()
} // ParenthesisChecker
14. Design and write a program that uses Stacks to determine whether an expression involving both parentheses and square brackets is well formed.
Design: This exercise requires that we modify the isBalanced() method
from the solution to the previous exercise. In this case not only must there be
one right parenthesis (or bracket) for each left, right brackets must match up with
left brackets, and right parentheses must match up with left parentheses. So in
this case, whenever we encounter a left parenthesis (or bracket) we store a right
parenthesis (or bracket) on the stack. Then when we encounter a right parenthesis we pop the stack. The top character should match the right parenthesis (or
bracket).
/*
* File: ParenthesisChecker2.java
* Author: Java, Java, Java
* Description: This program uses a Stack ADT to determine if expressions
* entered on the command line contained balanced parentheses and brackets.
* The algorithm makes use of the Stacks LIFO behavior.
*
* Usage: java ParenthesisChecker2 expression
*/
public class ParenthesisChecker2 {
/**
* isBalanced() returns true if its parameter contains balanced
* parentheses. The string is processed from left to right, char
* by char. Each time a left parens or bracket is found, a right parens
* or bracket is pushed on the stack. Each time a right parens or bracket is found,
* the stack is popped. The character popped must match either parens or bracket. If an
* attempt to pop is made on an empty stack, thats an error
* caused by too many right parens. If the stack is not empty at
* the end, the string contains too many left parens.
* Note how data popped from the stack must be coerced from Object to Node
* and then from Node to Character.
* @param s -- the String to be tested
* @return true if s has balanced parentheses
*/
public boolean isBalanced(String s) {
526
15. Write a program that links two lists together, appending the second list to the tail
of the first list.
Design: The solution to this exercise is simple: Just insert the head of the second
list as the last element in the first list.
/*
* File: ListLinker.java
16. Design a Stack class that uses a Vector instead of a linked list to store its
elements. This is the way Javas Stack class is defined.
Design: We extend the Vector class, using its insertElementAt(obj,
0) and removeElementAt(0) methods to implement push and pop. The
main() method is used to test that the implementation indeed functions like a
stack.
/*
527
528
* File: Stack.java
* Author: Java, Java, Java
* Description: This implementation of a Stack ADT extends the Java Vector
* class.
*/
import java.util.*;
public class Stack extends Vector {
/**
* Stack() creates an empty Vector by invoking the superclass constructor.
*/
public Stack() {
super();
} // Stack()
/**
* push() inserts an object on the top of the stack (location 0)
* @param Object -- the object inserted
*/
public void push (Object obj) {
insertElementAt(obj, 0);
} // push()
/**
* pop() removes and returns the object at the top of the stack
* @return the Object at location 0
*/
public Object pop() {
Object obj = peek();
removeElementAt(0);
return obj;
} // pop()
/**
* peek() returns the top object without removing it
* @return the Object at location 0
*/
public Object peek() {
return elementAt(0);
} // peek()
/**
* main() creates a Stack and tests its behavior by
*
inserting and then removing a string of characters.
*
The result is that the string will be reversed, since
*
the last character inserted will be the first removed.
529
*
Note how the Character wrapper class is used to create
*
Character objects.
*/
public static void main( String argv[] ) {
Stack stack = new Stack();
String string = "Hello this is a test string";
System.out.println("String: " + string);
for (int k = 0; k < string.length(); k++)
stack.push(new Character( string.charAt(k)));
Object o = null;
String reversed = "";
while (!stack.isEmpty()) {
o = stack.pop();
reversed = reversed + o.toString();
}
System.out.println("Reversed String: " + reversed);
} // main()
} // Stack
17. Design a Queue class that uses a Vector instead of a linked list to store its
elements.
Design: The design here is similar to that used in the previous exercise, except
that hear we use insertElementAt() to insert elements at the rear of the
list. The Vector.size() method can be used to get the index of the last
element in the list.
/*
* File: Queue.java
* Author: Java, Java, Java
* Description: This Queue ADT is designed as an extension of the Vector class.
*/
import java.util.*;
public class Queue extends Vector {
/**
* Queue() creates an instance by involving the superclass constructor.
*/
public Queue() {
super();
} // Queue()
/**
* enqueue() inserts its parameter at the rear of the vector.
18. Challenge: Design a List class, similar in functionality to the one we designed
in this chapter, that uses an array to store the lists elements. Set it up so that the
middle of the array is where the first element is put. That way you can still insert
at both the front and rear of the list. One limitation of this approach is that unlike
a linked list, an array has a fixed size. Allow the user to set the initial size of
the array in a constructor, but if the array becomes full, dont allow any further
insertions.
Design: The most difficult part of this exercise is designing a protocol to define
530
531
when the list is empty and when it is full. This must be done in a consistent
manner. The design we use here is described in the comments provided for
the List class. An important feature of our design is that is starts inserting
elements at the arrays midpoint. This allows insertions at both the front and
rear, as we had in our linked list implementation. Thus we get a list with the
same functionality as in the linked-list version, but with a completely different
implementation. This is a good example of information hiding.
/*
* File: List.java
* Author: Java, Java, Java
* Description: This class implements a list using a static array
* to store the lists elements. Integer indices are used to
* determine the front and rear of the list. Initially the
* front and rear start out equal and set (roughly) to the midpoint
* of the array. Insertions at the front are made at frontIndex.
* Insertions at the rear are made at rearIndex + 1. Removals
* from the front occur at frontIndex +1. Removals at the rear
* occur at rearIndex. The rearIndex is bound by the arrays length.
* The frontIndex is bound by 0. An empty list is defined as
*
frontIndex == rearIndex, which of course is the initial state.
* The insertion and removal algorithms must insure that this
* empty list condition holds when the last element is removed
* regardless of where it is removed from.
* One limitation of using
* is static. Plus theres
* go wasted. For example,
* insertions always occur
* elements will be used.
*/
public class List {
private
private
private
private
Object data[];
int startIndex;
int frontIndex;
int rearIndex;
//
//
//
//
//
/**
* List() initializes the list by creating an array of initialSize
* elements and setting the initial values of the indices.
* @param initialSize -- an int giving the arrays initial size
*/
public List(int initialSize) {
data = new Object[initialSize];
int startIndex = (initialSize / 2) - 1; // Set start to midpoint
frontIndex = startIndex;
// Empty: rearIndex == frontIndex
rearIndex = startIndex;
532
} // List()
/**
* isEmpty() returns true when rearIndex == frontIndex.
*/
public boolean isEmpty() {
return frontIndex == rearIndex;
} // isEmpty()
/**
* print() prints each element of the list. Note that
* frontIndex +1 gives the location of first element in a nonempty list
* PRE: frontIndex <= rearIndex
*/
public void print() {
if (isEmpty()) {
System.out.println("List is empty");
return;
}
for (int j = frontIndex+1; j <= rearIndex; j++)
System.out.println(data[j].toString() + " ");
} // print()
/**
* insertAtFront() inserts an object at frontIndex as
* long as frontIndex is not < 0 (indicating a full list)
* @param obj -- the Object to be inserted
* @return true iff the insertion was successful
*/
public boolean insertAtFront(Object obj) {
if(frontIndex >= 0) {
data[frontIndex] = obj;
frontIndex--;
return true;
}
return false;
} // insertAtFront()
/**
* insertAtRear() inserts an object at rearIndex +1 as
* long as the list is not full (rearIndex >= length-1
* @param obj -- the object to be inserted
* @return true iff the insertion was successful
*/
public boolean insertAtRear(Object obj) {
if (rearIndex < data.length - 1) {
rearIndex++;
data[rearIndex] = obj;
return true;
}
return false;
} // insertAtRear()
/**
* removeFirst() removes the element at frontIndex+1
* provided the list is not empty
* @return the Object removed or null
*/
public Object removeFirst() {
Object obj = null;
if (!isEmpty()) {
obj = data[frontIndex + 1];
frontIndex++;
}
return obj;
} // removeFirst()
/**
* removeLast() removes the object at rearIndex, provided
* the list is not empty
* @return the Object removed or null
*/
public Object removeLast() {
Object obj = null;
if (!isEmpty()) {
obj = data[rearIndex];
rearIndex--;
}
return obj;
} // removeLast()
/**
* main() creates a list of different types of objects
*
and tests this classs methods. This example shows that
*
a array of 4 slots can store 4 different objects.
*/
public static void main( String argv[] ) {
// Create list and insert heterogeneous objects
List list = new List(4);
list.print();
list.insertAtFront(new Character(h));
list.insertAtFront(new Integer(8647));
list.insertAtRear(new Double(8647.05));
list.insertAtRear(new String("Hello World"));
// Print the list
System.out.println("Generic List");
list.print();
// Remove objects and print the resulting list
533
Object o;
o = list.removeFirst();
System.out.println(" Removed " + o.toString());
System.out.println("Generic List:");
list.print();
o = list.removeFirst();
System.out.println(" Removed " + o.toString());
System.out.println("Generic List:");
list.print();
o = list.removeFirst();
System.out.println(" Removed " + o.toString());
System.out.println("Generic List:");
list.print();
list.insertAtFront(new Integer(1234)); // Insert another object
o = list.removeFirst();
System.out.println(" Removed " + o.toString());
System.out.println("Generic List:");
list.print();
o = list.removeFirst();
System.out.println(" Removed " + o.toString());
System.out.println("Generic List:");
list.print();
} // main()
} // List
19. Challenge: Add a method to the program in the previous exercise that lets the
user increase the size of the array used to store the list. You may want to review
the In the Laboratory section of Chapter 11.
Design: The setSize() method increases the size of the array and then
copies all of the existing elements into the new array. In this case we extend the
array by growing it out from the middle. This takes some additional work, but it
is an important design consideration given the fact that in our original design the
midpoint of an empty array served as the location of the first insertion.
/**
* setSize() increases the size of the array by creating
* a new array and copying the elements from the old array
* to the new. Note that old elements are copied into the
* new array from the middle to the back and from the middle
* to the front, thereby allowing it to expand in both directions.
* @param size -- an int giving the new size
* @return true iff the size was increased
*/
534
20. Challenge: Recursion is a useful technique for list processing. Write recursive versions of the print() method and the lookup by name method for the
PhoneList. (Hint: The base case in processing a list is the empty list. The
recursive case should handle the head of the list and then recurse on the tail of
the list. The tail of the list is everything but the first element.)
Design: Treating the list as a head and a tail, we can process the list recursively
by repeatedly passing the tail of the original list to our processing method. The
methods defined here illustate the details of how this is done.
/**
* getPhoneRecursive() recursively searches for a phone number
* @param name -- a String giving name of person whose number is desired
* @param node -- a reference to the current node
*/
private String getPhoneRecursive(String name, PhoneListNode node) {
if (node == null)
// Base case
return ("Sorry. No entry for " + name);
else if (node.getName().equals(name))
// Base case
return node.getData();
535
536
// Re-
/**
* getPhone() returns the phone number given a persons name
* @param name -- a String giving a persons name
* Algorithm: Traverse the list until the node containing the
*
given name is found. Return the corresponding phone number.
*/
public String getPhone(String name) {
if (isEmpty())
// Case 1: empty list
return "Phone list is empty";
else
return getPhoneRecursive(name, head);
} // getPhone()
/**
* recursivePrint() recursively prints the list given
* a reference to the current node
* @param current -- a reference to a node.
*/
public void recursivePrint(PhoneListNode current) {
if (current != null) {
System.out.println(current.toString());
recursivePrint(current.getNext());
}
} // recursivePrint()
/**
* print() prints the entire by calling recursivePrint()
*/
public void print() {
if (isEmpty())
System.out.println("Phone list is empty");
else
recursivePrint(head);
} // print()
21. Challenge: Design an OrderedList class. An ordered list is one that keeps
its elements in order. For example, if its an ordered list of integers, then the
first integer is less than or equal to the second, the second is less than or equal
to the third, and so on. If its an ordered list of employees, then perhaps the
employees are stored in order according to their social security numbers. The
OrderedList class should contain an insert(Object o) method that
inserts its object in the proper order. One major challenge in this project is
designing your class so that it will work for any kind of object. (Hint: Define an Orderable interface that defines an abstract precedes() method.
Then define a subclass of Node that implements Orderable. This will let you
compare any two Nodes to see which one comes before the other.)
Design: Our design to this solution follows the design of the polymorphic
sorting algorithm described in Chapter 8. It defines an Orderable interface,
which contains an abstract precedes() method. Any objects to be stored
in an ordered list must implement the Orderable interface. For example, an
OrderedInt (defined below) is an integer that defines the Orderable interface. An OrderedList is a list that uses the precedes() method to put its
elements in the correct order when they are inserted into the list. So it always
maintains the list in the proper order. See the insert() method for the details.
As evident there, what makes this type of polymorphism somewhat difficult is
the awkward syntax needed to compare two objects stored in the list using the
precedes() method.
/*
* File: Orderable.java
* Author: Java, Java, Java
* Description: An abstract interface that defines the
* precedes() method.
*/
public interface Orderable {
public boolean precedes(Object obj);
} // Orderable
/*
* File: OrderedInt.java
* Author: Java, Java, Java
* Description: An OrderedInt is an integer that implements the
* Orderable interface. This requires an implementation of the
* precedes method for integer data.
*
* Note that we use an Integer instance variable to store the
* number. It is not possible to subclass the Integer class because
* it is declared final.
*/
public class OrderedInt implements Orderable {
private Integer number;
/**
* OrderedInt() creates an instance with its parameter value
* @param n -- an int that gives the value for this instance
*/
public OrderedInt (int n) {
number = new Integer(n);
} // OrderedInt()
537
/**
* intValue() returns the integer value of this instance
* @return an int representing this instances value
*/
public int intValue() {
return number.intValue();
}
/**
* precedes() is part of the Orderable interface. It defines
* what it means for one OrderedInt to precede another.
* @param obj -- an Object to compare to this instance
* @return true iff this instance is less than the parameter
*/
public boolean precedes(Object obj) {
return number.intValue() < ((OrderedInt)obj).intValue();
} // precedes()
} // OrderedInt
/*
* File: OrderedList.java
* Author: Java, Java, Java
* Description: This subclass of Vector implements an ordered
* list. For this example only OrderedInts (integer values)
* may be stored in the list, because thats the parameter of
* the insert() methods. To generalize this, create insert()
* methods for the other data types.
*
* What makes this work is that an OrderedInt implements the
* the precedes method, which defines what it means for one
* OrderedInt to preceded another.
*/
import java.util.Vector;
public class OrderedList extends Vector {
/**
* OrderList() constructor invokes the superclass constructor
*/
public OrderedList () {
super();
}
/**
* print() prints the datum of each element of the list. Since
* the list stores Nodes, it is necessary to get the data out
* of the node and then to convert it to OrderedInt and then
* to an integer value.
538
539
*/
public void print() {
for (int k = 0; k < size(); k++) {
Node node = (Node)elementAt(k);
// Get Node
OrderedInt ordInt = (OrderedInt)node.getData(); // Get data
int num = ordInt.intValue();
// Get int
System.out.println(num);
}
} // print()
/**
* insert() inserts an OrderedInt into the list in its proper order,
* where proper order is determined by the precedes() method. The
* algorithm traverses the list until it finds the proper insertion point.
* Note again that it is necessary to get the OrderedInt out of the Node
* before precedes() can be invoked.
* @param obj -- the OrderedInt to be inserted
*/
public void insert(OrderedInt obj) {
int currentIndex = 0;
boolean foundPosition = false;
Node node = null;
Node newNode = new Node(obj);
int j = 0;
while (! foundPosition && j < size()) {
Node temp = (Node) elementAt(j);
if (((OrderedInt)newNode.getData()).precedes((OrderedInt)temp.getData()))
foundPosition = true;
else j++;
}
insertElementAt(newNode, j);
} // insert()
/**
* main() creates an instance of this class and then tests it by
* inserting 20 random integer values into the list.
*/
public static void main(String argv[]) {
OrderedList list = new OrderedList();
System.out.print("Inserting: ");
for (int k = 0; k < 20; k++) {
int n = (int)(Math.random() * 25);
System.out.print(" " + n);
list.insert( new OrderedInt(n));
}
System.out.println();
System.out.println("The resulting list");
list.print();
} // main()
} // OrderedList
540
Exercise 16.9
Exercise 16.11
Exercise 16.10
List
541
Node
List
List
NumberList
+getCopy() : List
Uses
StudentList
-generator : Random
+fillList()
+getAverage() : double
+main(in args : String[])
+calcAvgGPA() : double
+main(in argv : String[])
TestCopy
-generator : Random
-list : List
+fillList()
+printCopy()
+main(in args : String[])
Exercise 16.12
Stack
Exercise 16.15
Stack
ListLinker
Uses
Uses
PalindromeTester
ParenthesisChecker
Exercise 16.16
Exercise 16.18
Exercise 16.17
Vector
Vector
Stack
List
Queue
+Stack()
+push(in obj : Object)
+pop() : Object
+peek() : Object
+main(in argv : String[])
datatype
Object[]
-data : Object[]
-startIndex : int
-frontIndex : int
-rearIndex : int
+Queue()
+enqueue(in obj : Object)
+dequeue() : Object
+main(in argv : String[])
Random
+isEmpty() : boolean
+print()
+insertAtFront(in obj : Object) : boolean
+insertAtRear(in obj : Object) : boolean
+removeFirst() : Object
+removeLast() : Object
+main(in argv : String)
datatype
String[]
Exercise 16.21
Exercise 16.19
interface
Orderable
List
-data : Object[]
-startIndex : int
-frontIndex : int
-rearIndex : int
Vector
+isEmpty() : boolean
+print()
+insertAtFront(in obj : Object) : boolean
+insertAtRear(in obj : Object) : boolean
+removeFirst() : Object
+removeLast() : Object
+setSize(in size : int) : boolean
+main(in argv : String)
OrderedInt
+OrderedInt(in n : int)
+intValue() : int
+precedes(in obj : Object) : boolean
+OrderedList()
+print()
+insert(in obj : OrderedInt)
+main(in argv : String[])
Uses