CPSC 124: Lab 3
Introduction to Subroutines
A SUBROUTINE IS A SET OF INSTRUCTIONS for performing some task, chunked together into a "black box" and given a name. A programming language can have some built-in subroutines, like Math.random(), that are a part of the basic language and are always available. A programmer can also write new subroutines and then use them in the same way that built-in subroutines can be used. Of course, one programmer can also use subroutines written by another programmer. For example, you have already used subroutines defined in the Console class, which is not a standard part of Java but was provided to you to perform certain kinds of input/output tasks.
In Java, every subroutine must be defined in some class. In some other languages, subroutines defined in a class are called methods. In Java, all subroutines are methods.
There are two different kinds of methods: static methods, which are also called class methods, and instance methods. A static method belongs to the class itself. An example would be Math.random(), which is a static method defined in the class Math. An instance method belongs to objects created from the class. An instance method doesn't really exist until an object has been created. For example, the instance method putln() defined in the class Console can only be used through a Console object created with the new operator:Console console = new Console(); // create a Console object
Once the console object has been created, you can call console.putln() to output a carriage return to that console. The method putln() doesn't even make sense unless there is a particular console object for it to operate on.
If you define a static subroutine in a class, then you can call that subroutine from inside other subroutines defined in that class, just by giving its name. (If the static subroutine is defined in a different class, you have to give the class name in addition to the subroutine name, as in Math.random().)
In this lab, you will write several programs that use subroutines. You will also get more practice with different kinds of control statements such as for and switch. You won't be writing new subroutines in this lab. (We'll save that for next week.) For more information on subroutines, read Chapter 3.
For this lab, you will be using two folders from Math/CS Server, "Java Console Ap Starter" and "Mosaic Starter". I suggest that you copy both of these folders onto your workstation's desktop.
Before starting the work of the lab, I suggest that you take a little time to become more familiar with CodeWarrior. Open the Java Console Ap Starter folder and double-click on the project file, javaConsoleAp.proj, to start up the CodeWarrior IDE. Recall that the project window that appears lists the files that are part of the project. If a file does not appear here, you can't compile it, even if you can see it in another window on the screen. If the project window is not open, then you can't do anything with any file (except edit it). If you forget this and open a program file instead of a project file, or if you accidently close the project window, you'll have to go back to the project file, and double-click on it to open it before you can compile or run your program.
You should be familiar with the ways to get files into and out of the list that appears in the project window. Removing a file is easy: Just click on the file's name in the project window to hilite it, and then choose the "Remove Files" command from the Project menu. (You can hilite multiple file names by holding down the shift key while you click.) There are several ways to add a file to the project window, but before you can apply any of them, you must make sure that the file is saved, and that it has a name that ends with ".java". If that is true, then the easiest way to add the file to the project window is to find the file icon and drag it onto the project window. You can also open the file, and when it is the frontmost Window on the screen you can use the "Add Window" command from the Project Menu. Finally, there is the "Add Files" command, which allows you to select one or more files to add to the project window. If you want to start a file from scratch, you can do so with the "New" command from CodeWarrior's File menu.
As an example, copy the file "RollTheDice.java" from the file server into the Java Console Ap Starter folder that you have already copied onto your workstation. If you have not already opened the project file in that folder, do so now. Remove the file "Application.java" from the project window and add the file "RollTheDice.java" in its place.
Notice that the name of the class defined in this file is RollTheDice. The project, however, is set up to use a class named Application as its main program. Before you can compile and run the program, you'll have to change the set up. To do this, choose the "Preferences" command from CodeWarrior's Edit menu. The dialog box that appears includes a list of topics (on the left side of the window). Click on "Java Project" in this list, if it is not already selected. When you do this, you'll see a space on the right for configuring the project:
For the type of project you are working on now -- one that produces a double-clickable application file -- the Project Type is set to "Droplet". Under Droplet Info, the File Name is the name of the double-clickable application file that is produced when you Link (or Run or Make) your project. This can be any name you would like to use for that file. The Main Class must be set to the name of the class that contains the main() routine for the program.
Set the Main Class for your project to RollTheDice. (You might want to change the File Name to RollTheDice as well.) Click on the OK button of the Preferences dialog box. You should now be able to compile and run the RollTheDice program. (Finally!)
For your first exercise of the lab, you should do Exercise 4 from Lab 2, which was eliminated from last week's lab report. Now, however, you should do this using the subroutine tryToRoll() which is defined in the file RollTheDice.java. To repeat the assignment:
We could ask, "What is the average number of rolls that it takes to get a 12?" -- or some other desired roll. To answer this question, you would repeat the experiment a large number of times, add up all the results, and divide by the number of experiments to get the average. Write a program to do this. The program should ask the user for the desired roll of the dice, which must be a number between 2 or 12. It should also ask the user to specify how many experiments are to be performed. The program should then perform the experiments and print out the average number of rolls that it took to get the desired roll.
One warning: If you divide two integers, N and M, by taking the quotient M/N, the result is an integer. For example, 987/100 is 9 rather than 9.87. To get a real number as an answer, you have to convert at least one of the numbers that you are dividing into a real number. You can do this with a type cast. For example:
double avg = (double)N / (double)M;
The next two exercises use the Mosaic Starter folder. Open this folder and open the project file, "Mosaic.proj". This project uses a class named MosaicFrame, which is similar to the example discussed in Section 4.6 of the notes. A MosaicFrame is a window that shows a grid of colored rectangles. If you compile and run the project, you'll see a small red square wandering at random in a black window. You'll find several other compiled sample programs using MosaicFrames in the Mosaic Starter Folder. You can run any of the sample programs just by double-clicking on it.
A new MosaicFrame can be created by declaring a variable of type MosaicFrame and initializing that variable using the new operator:MosaicFrame mosaic = new MosaicFrame(title, rows, columns, height, width);
where title is a string giving the title to be displayed in the title bar of the window, rows is the number of rows of rectangles, columns is the number of columns of rectangles, height is the height of the window, and width is the width of the window. (The height of the window should be a multiple of the number of rows, and the width should be a multiple of the number of columns). See the file MosaicAp.java for a specific example.
A particular rectangle in the window can be specified by giving its row number and its column number. The rows are actually numbered from 0 to rows-1, and the columns are numbered from 0 to column-1. Rows are numbered from top to bottom; columns from left to right. The top left rectangle has row number 0 and column number 0.
To use a MosaicFrame, you have to know a little bit about the way colors are specified on a computer. Any color that can be displayed on a computer is made up of some combination of the "primary colors," red, green, and blue. In MosaicFrame, the level of each primary color is given as a double number in the range 0.0 to 1.0. A color is specified by three numbers giving the levels of red, green, and blue in the color. Colors specified in this way are referred to as "RGB colors." A color with a red component equal to 0.0 contains no red at all; a color with a red component equal to 1.0 contains the maximum possible amount of red. Black is given by red, blue, and green components all equal to 0.0. White is given by all components equal to 1.0.
If mosaic is a variable of type MosaicFrame, you can call the following methods, where row and column are integers specifying one of the rectangles in the mosaic:
- mosaic.setColor(row, column, r, g, b) sets the color of the specified rectangle, where r, g, and b are the red, green, and blue components of the color (in the range 0.0 to 1.0)
- mosaic.clear() sets the color of all the rectangles to the default background color, black
- mosaic.setAll(r, g, b) sets the color of all the rectangles to the color with red, blue, and green components given by r, g, and b
- mosaic.getRed(row, column) returns a number in the range from 0.0 to 1.0 giving the red component of the current color of the rectangle in the specified row and column
- mosaic.getGreen(row, column) returns a number in the range from 0.0 to 1.0 giving the green component of the current color of the rectangle in the specified row and column
- mosaic.getBlue(row, column) returns a number in the range from 0.0 to 1.0 giving the blue component of the current color of the rectangle in the specified row and column
- mosaic.hasClosed() returns a boolean value indicating whether or not the MosaicFrame window has been closed (See the sample program MosaicAp.java for an example of how this function can be used in a while loop that will continue just as long as the window is open.)
- mosaic.delay(n), where n is an integers, will cause the program to wait, without doing anything, for n milliseconds
You will do two exercises using MosaicFrames. The exercises are to write programs that work just like the sample programs RedGreenGradient and Brighten. You will find these sample programs in the Mosaic Starter folder.
For Exercise 2, create a MosaicFrame that shows a grid of squares like that in the program RedGreenGradient. In this grid, the red component increases from 0.0 to 1.0 as you move from left to right across the window. The green component increases from 0.0 to 1.0 as you move from the top of the window to the bottom of the window.
This color grid can be made by a program that is only a few lines long. It will use one for loop nested inside another for loop.
Exercise 3 is to modify the sample program, MosaicAp.java, so that it works like the sample program Brighten.
The Brighten program is a variation on the RandomWalk program in MosaicAp.java. In the random walk program, a red square wanders around the window. In the Brighten program, an invisible square wanders around the window. Every time this invisible square visits a square, that square becomes a little bit more red. This is done by getting the current red component of the square, adding 0.1 to it, and then resetting the square's color with the increased red component. (Obviously, you could use the green or blue component instead -- or even make all three of them the same if you want the squares to become white instead of bright red.)
This exercise really does not require a huge change from the sample program. If you want to do something more exciting, you might want to make three invisible, wandering squares and have one of them increase the red component of the squares it visits, one the green component, and one the blue component. I haven't tried this, but I did write a program with three wandering squares, TripleWalk.
Exercise 4 is not a programming exercise. It is an "essay-type" question which is a preview of object-oriented programming. You have now seen at least two classes -- Console and MosaicFrame -- which allow you to create objects and to call methods such as console.putln() or mosaic.setColor(). The methods are the behaviors of the objects. In object-oriented programming, you design classes to represent objects that you want to use in your programs. And you define methods for the class that represent the behaviors of those objects. For this exercise, choose one of the objects listed below, and think about the class that you would write to represent objects of that type. The assignment is to describe at least three different methods that you would want to include in that class. If a method has parameters or a return value, describe them as well. Finally, give one or two examples of how each of your methods might be used in a program.
Here are the possible object types:
- a deck of playing cards
- a chess board
- an event (such as a baseball game)
- a mathematical expression (such as x2 - sin(x))
- a window on a computer screen
[ Lab Index | Online Notes ]