Session 17

More on Graphical Applications in Java


810:062
Computer Science II
Object-Oriented Programming


On Homework 6

What kind of instance variable should I choose to implement the Bag class?

You may choose. Arrays are easy to work with, but you may run out of slots -- which requires allocating a new, larger array and copying the old values into it. ArrayLists and Vectors are a bit harder to work with, but they grow on their own, as needed.

I have decided to use ArrayLists (or Vectors). How can I store an int in collection?

ArrayLists and Vectors hold objects, and ints aren't objects. But an Integer is. An Integer is a wrapper for an int. The class offers several services, including parseInt(), but for this assignment you might use:

Notice that there is no way to change the value wrapped by an Integer. You simply have to create a new Integer and store it in place of the old one.

May I create a new kind of object, not specified in the assignment?

Yes. That is one reason I explained a bit about how Arrays.sort() works for object. If I were doing this assignment, I'd probably create an Association-like object that relates a word to its count, with a suitable interface for incrementing the count -- and make it implement the Comparable interface, so that I could sort an array of the objects.

In any case, I have enabled the submission system to accept extra classes. Just be sure that your header documentation makes clear the purpose of each class. And staple your extra classes at the back of the print-out you turn in.

Any other questions?


Growing a Simple Graphical Program

In Session 15, we built a simple "ball world", the final version of which we saw last time. Today, we will add some new features to make the world more interesting: multiple balls, walls that deflect balls, and (if we have time) some user interaction.


A Little Exercise

Write the code we would need to create convert BallWorldFrame into a MultiBallWorldFrame, with any number of balls. The number of balls is passed to the object at the time it is created. Bonus points if the balls start off going in slightly different directions!

This is also a good time to be sure you understand the code so far -- ask questions about parts of the code that are new or confusing.


A Solution

We do not need to right much new code:

How can we vary the directions? Use different inital values for the deltaX and deltaY parameters. I used Math.random() to scale a value between 0 and 20, or 0 and 10. The class method Math.random() returns a value in the range [0..1).


Those Graphics Objects

We don't create them ourselves. The run-time system hands our frames a Graphics each time it asks the frames to paint() themselves. So far, we have seen two of the messages to which Graphics objects respond:

But they respond to many useful messages, including:

Here is a simple demo frame for these basic messages. If you are curious, you can read more about the Graphics class and its interface in the javadoc for the Graphics class.

How do we test messages sent to a Graphics object?


Balls that Bounce Off Walls

Our worlds are a bit uninteresting, as the Balls fly out of the frame pretty quickly. Shouldn't the balls bounce off the walls?

Only if we tell them how to!

Notice I how phrased that: Only if we tell them how to! Balls themselves should know how to bounce.

Why not have the Frame detect collisions and tell the Balls to change direction? To do so, the Frame would have to...

This requires the Frame to know a lot about the Ball's implementation. If we decide to change the Ball's implementation, then we will have to change the corresponding code in Frame. But if the Ball class reveals its implementation to the Frame class, it reveals it to all objects, and so we may have to change those classes, too.

Back at the top of Session 13, we ran into a design principle that we should follow here:

Any code that manipulates an object's instance variables should be in the object's own class.

The Ball class should be responsible for all operations on its instance variables. So Balls should take care of detecting collisions and changing directions.

So, with that settled, we encounter a more mundane concern. How can a Ball change its direction? Multiply the delta value by -1. Try it out -- this simulates a reflection just fine.

Then we encounter a more serious issue. In order to know if it has gone out of bounds, a Ball must know the width and height of the Frame in which it resides. But the Ball class does not keep track of this information. That's not a major problem, because we can create a new kind of Ball that does!

Take a look at my solution. Notice:

Those protected access methods reinforce the principle we discussed: Every class should be responsible for its own stuff. That includes superclasses.

Someone in class suggested a nice improvement: "The Ball should detect the collision at radius pixels from the boundary." Actually, it should detect right and bottom collisions at 2*radius pixels from the edge (why?), and left and top collisions right at the boundary (why?). This makes a nice practice exercise at home!


Reviewing the Exam

Principle of Continuity: in Session 2 the first time

interface method: in Session 7 the first time

Anagram doesn't have to find anagrams, or sort words or characters. Our pipe of Sign|sort|Squish already groups anagrams for us. The only problem is that too many of the groups have only one word in them, meaning that the word has no anagrams. Anagram's job is to detect one-word groups and not print them.


Wrap Up


Eugene Wallingford ..... wallingf@cs.uni.edu ..... March 8, 2005