CS 124, Fall 2011
Lab 8: Subroutines and APIs, with Mosaic

In today's lab, you will write a class containing certain subroutines. There will be no main routine in that class; the subroutines are meant for use in other classes. The class that you write will, in turn, use Mosaic.java, which was discussed in class and which is covered in Section 4.6. (Actually, you will be using a slightly improved version. To see the JavaDoc for the improved version, click here.)

In addition to subroutines and APIs, the lab gives you some experience with working with a two-dimensional grid. You have already used one-dimensional sequences in the form of strings. The individual characters in a string, s, are numbered, and the i-th character can be accessed as s.charAt(i). Similarly, the rectangles in a Mosaic are arranged in numbered rows and columns, and you need to use two numbers to pick out an individual rectangle. We have not yet covered arrays, but the idea of numbered positions is the essential concept behind arrays, and you are getting some experience with that basic concept.

This lab is due at the beginning of lab next Thursday. You should copy your work into your homework folder by that time.

The due date for Project 2 has been postponed for one week, until Friday, October 28.


Implementing an API

To begin the lab, create a new project named lab8. Open the directory /classes/cs120/lab8-files, and copy the three files from that project into your lab8 src folder. (The files are Mosaic.java, MosaicCanvas.java, and ShapeTest.java.)

There will be some errors in the project, since many of the subroutines used by ShapeTest.java don't exist yet. Your first job is to write those subroutines. Once the subroutines are correctly implemented, then running ShapeTest.java will create a mosaic window containing this picture:

First, create a new Java class named MosaicShape. The name must be exact, since that's the name that is used in ShapeTest. You have to create the following subroutines in MosaicShape. All the subroutines are void, and all the parameters are of type int.

I strongly suggest that you start by defining four empty subroutines. This will eliminate the errors from ShapeTest.java and allow you to run that program. You can then work on the subroutines one at a time, and test each one as you work on it, by running ShapeTest.


When "drawing" things in these subroutines, the only basic operation that you have is setting the color of one square in the mosaic window, using the subroutine Mosaic.setColor(row,column,red,green,blue). You have to implement the drawing subroutines by calling this subroutine for every individual square whose color you want to set. Of course, you can really only draw approximations of the geometric shapes.

rect is pretty easy. It would be difficult to draw a disk efficiently, but it is easy to do it inefficiently: To implement disk(x,y,r), go through every row and column in the mosaic and color the squares that satisfy

(x−column)2+(y−row)2 <= r2

Note that Mosaic.getRows() returns the number of rows in the mosaic, and Mosaic.getCols() returns the number of columns. As for lines, they are rather difficult and require some mathematics. You can implement line(x1,y1,x2,y2) using the following pseudocode algorithm:

    if x1 == x2 and y1 == y2:
        color the square at row y1, column x1
    else if Math.abs( x1 - x2 ) > Math.abs( y1 - y2 ):
        slope = (double)(y2 - y1) / (x2 - x1)
        Let a be the smaller of x1,x2
        Let b be the larger of x1,x2
        for x from a to b:
            y = slope * (x - x1) + y1, rounded to the nearest integer
            color the square at row y, column x
    else:
        slope = (double)(x2 - x1) / (y2 - y1)
        Let a be the smaller of y1,y2
        Let b be the larger of y1,y2
        for y from a to b:
            x = slope * (y - y1) + x1, rounded to the nearest integer
            color the square at row y, column x

Don't forget to provide JavaDoc-style comments, suitable for documenting a reusable API!


Using an API

Once you have ShapeDraw working, your second exercise is to write a program that uses it and Mosaic. For this program, you will need TextIO, so you should add TextIO.java to your project.

The program that you will write will let the user type in "commands", which will be executed in the Mosaic window. The idea is that they user can draw shapes in a mosaic window by typing in commands (a strange interface for a drawing program!).

The program should simply run in a while(true) loop. In the loop, you will read and execute one command. Each command will start with a word, which you can read using TextIO.getWord(). After the word there can be some integers that are used by the command. Some possible input lines are:

    open 40 40 10
    rect 10 20 50 15
    exit

The number of integers will depend on the command. You should read the command and its parameters, if it needs them. You should then carry out the command by calling an appropriate subroutine in either Mosaic or MosaicShape (except for the exit command). Here is the complete list of commands, with letters representing the integer parameters:


David Eck, for CPSC 225