CS 124, Spring 2014
Lab 5: Introduction to Subroutines

We are about to begin Chapter 4, which is mostly about subroutines. You have already used subroutines, such as System.out.println() and g.drawRect(). Now, you need to learn how to write them and to design programs that use them. In this lab, you will use another set of subroutines—ones that implement "turtle graphics"—and you will write a few subroutines of your own. Since we haven't talked about writing subroutines in class yet, the lab is more tutorial in nature than most of the labs. There is not a lot of algorithm design work.

You will need copies of two files, TurtleGraphics.java, and OnScreenTurtle.java. You should make a lab5 directory and copy the two files into it. You can find them in /classes/cs124/lab5-files.

This lab is due next Tuesday at the beginning of the next lab. Copy your lab5 folder into your homework folder in /classes/cs124/homework as usual.

About the Turtle

This program uses turtle graphics. You should imagine a turtle moving around in a window on the screen, dragging a pen that draws a line as the turtle moves. In the program, the turtle is represented by an object named turtle. This object contains subroutines that represents commands to the turtle, telling it how to move. For example, turtle.forward(5) makes the turtle move forward along a line for a distance of 5 units.

In this program, the turtle appears in the window as a gray triangle, which is somewhat transparent so that any drawing behind it will show through. The turtle moves around in a square area that is 20-by-20 units on a side, with the point (0,0) at the center. So, the turtle's position inside the window can range from -10 to 10. There is nothing to stop the turtle from moving beyond this range, out of the window. These are not pixel coordinates; the turtle uses real number coordinates. For example, in an 800-by-800 rectangle, each unit will be equivalent to 40 pixels.

The turtle is always facing in some direction. The gray triangle points in that direction. Initially, the turtle faces to the right. There are commands for changing the direction. Initially, the turtle is set up to draw using a one-pixel-wide red line as it moves. However, both the width and the color of the lines can be changed by appropriate commands. Also, the turtle's pen can be raised so that it can move without drawing any line.

Here are brief descriptions of the commands that are available for use with the turtle object:

Exercise 1: First Turtle Drawing

For this lab, you will only work on TurtleGraphics.java. You should not make changes to OnScreenTurtle.java, which defines all the turtle graphics commands; it just has to be in the same directory as TurtleGraphics.java.

To begin, compile TurtleGraphics.java and run it to see what it does. You will have to close the window to end the program (or type CONTROL-C in the Terminal).

Then open TurtleGraphics.java with gedit for editing. You will see a main() routine near the top of the program. You will add some code to the main routine, and you will add some new subroutine definitions outside the main routine. There are already two examples of drawing with the turtle in main(), and there is space for each exercise that you will do for the lab. (You can keep the examples or delete them; I don't care.) Note that you do not have to put as many comments in your code as I did in the examples.

For your first exercise, you should draw a blue triangle inside a red triangle, as shown at the right. Use only turtle.forward, turtle.back, turtle.turn, and commands for setting color and maybe line width. The size and position of the triangle are up to you. Put your code under the comment that says "Exercise 1: First Turtle Drawing". Hints: All turns that you need to make are 120 degrees or 60 degrees, and the side length for the blue triangle is half of the side length for the red triangle.

Exercise 2: Using a Subroutine

If you look below the main() routine in TurtleGraphics.java, you will see the definition of a subroutine named square. It has a "parameter list" given by (double size), which means that when you use the subroutine, you must provide a parameter of type double. (The type of value that you provide can also be int, because an int value can be assigned to a double variable, and that's essentially what is done with parameters). So, for example, you can say square(10) to draw a square of size 10, or square(Math.sqrt(2)) to draw a square with size given by the square root of 2. Note that because square is defined in the same class as the code that you are writing, you will call it using a simple name: square(x) rather than something.square(x).

For your second exercise, you should draw a set of at least three nested squares, as shown in the picture. This time, you can use any turtle commands that you want, but you must use the square subroutine to draw the actual squares. The size, colors, and position of the drawing are up to you. Use random colors if you like. You will need to use turtle.penUp() and turtle.penDown() to make it possible to move the turtle without drawing a line. (You might try drawing a larger number of squares using a for loop, but you are not required to use a loop.)

The code that you write should be added to main(), under the comment that says, "Exercise 2: Using a Subroutine."

Exercise 3: Writing a Subroutine

For the third exercise, you will write your first complete subroutine definition. The definition of a subroutine cannot be placed inside another subroutine. Other than that, it can be anywhere inside the class. The order in which subroutines are defined doesn't matter, and it doesn't matter if the definition comes before or after the places in the code where the subroutine is called. To begin the exercise, copy this empty subroutine definition into your code:

private static void burst() {

}

The name of the subroutine is burst. It has no parameters, so it can be called by saying burst(), with nothing in the parentheses. The exact meaning of "private static void" will be explained in class. The code that defines what the subroutine does goes between the braces. You should add code to the subroutine to draw a "burst" of lines coming out of the current turtle position, similar to the one shown in the picture. Use a for loop to draw a large number of lines. Note that you can say "turtle.forward(length); turtle.back(length);" to a draw line of a given length along the direction in which the turtle is pointing and then return to the starting point of the line (ready to change the direction and draw the next line). The length should be chosen at random. You can either use turtle.face to point the turtle in random directions, or use turtle.turn to turn a small amount between each line and the next.

For a subroutine to do anything, the subroutine has to be called. You need a call to burst() under "Exercise 3" in main(). The subroutine call is already there. You just have to uncomment it. You don't have to make any other changes to main() for this exercise. (However, you could add a call to turtle.setDelay(0) if you don't want to watch the slow process of drawing the burst.)

Add a comment for your subroutine! The comment should go before the subroutine. Follow the style that is used for other subroutines in the file.

Exercise 4: Subroutine with Parameters

Most subroutines require parameters. The required parameters are specified in the parameter list that is part of the definition, such as the (double size) in the definition of square(). The important thing to understand is that the value of a parameter is unknown when you are writing the code inside the parameter. The actual value will come from elsewhere in the program, when the subroutine is called. It is not input from the user of the program; it is a value from another part of the program itself. When square is called as square(10), the value 10 is assigned to the parameter size before the subroutine's code is executed.

For the fourth exercise, you will make a subroutine that has a parameter. It will be a simple variation on the square subroutine. In fact, you can simply copy the definition of square and make some minor modifications. (Don't forget to modify the comment, too!)

Your subroutine should be named star instead of square. It will draw a five-pointed star with a specified size. You have to change the name of the copied routine, so that the first line reads:

private static void star(double size) {

In the definition, the number of sides should be 5 instead of 4, and the angle through which the turtle turns should be −144 instead of 90. Other than that, the two subroutines are the same.

After writing the subroutine, uncomment the call to star(5) under "Exercise 4" in main(). And don't forget to add comment for your subroutine definition.

Exercise 5: Subroutine Calling Subroutine

An important aspect of subroutines is that one subroutine can call another subroutine. This makes it possible to create complex programs out of subroutines, where the individual subroutines are not very long or complex.

For this exercise, write a subroutine that draws a "spiral of shapes" similar to the one shown above. The spiral is drawn using a for loop. Each time through the loop, one shape is drawn. The shapes start out small, and a small amount is added to the size after drawing each shape. And the turtle is turned by a small amount after drawing each shape. My picture uses square shapes, but you can use stars instead if you want. You must draw the individual squares or stars by calling one of the subroutines, square() or star(). My picture uses random colors, but you can use a single color if you want. The name of the subroutine should be spiral, and it should have no parameters. So, the first line will be

private static void spiral() {

To run the subroutine, uncomment the line in main() that calls it. I suggest calling turtle.setDelay(0); otherwise, it can take quite a long time to draw the spiral.

Exercise 6: Random Walk

As a final exercise, write a subroutine that sends the turtle on a random walk. The idea is to do the following over and over: Select one of the directions 0, 90, 180, or 290 at random; face in that direction; then move forward by a small, constant amount (say 0.25). Here is a loop that does this:

while (true) {
    int direction;
    direction = 90 * (int)(4*Math.random());
    turtle.face(direction);
    turtle.forward(0.25);
}

A sample random walk created by this code is shown in the picture on the right. One could just put the code into a subroutine. However, you should write a random walk subroutine that has a parameter. The parameter could be the distance that the turtle moves forward in each step. Or the parameter could specify the number of steps that the turtle will take, instead of letting it walk forever. Another idea is to implement two different kinds of random walk, and use a boolean parameter to tell the subroutine which kind of walk to do. You can get a nice pattern by selecting the direction randomly from 0, 60, 120, 180, 240, 300 instead of from 0, 90, 180, 270. A different sort of random walk is obtained by facing in a completely random direction and moving forward a random amount each time. Another idea is to use a random color for each step in the random walk.

You should also add a call to your random walk subroutine at the end of main(), just under the comment that says "Exercise 6: Random Walk."

(Note: If the random walk uses an infinite loop, then the turtle will eventually wander off the screen. If you want to detect when that happens, note that there are functions turtle.getTurtleX() and turtle.getTurtleY() that return the current x- and y-coordinates of the turtle.)