CS 149: Introduction to Programming
James Madison University, Spring 2018 Semester

Lab15: Recursive 2D graphics

Background

This lab will show you what it means to make a recursive method call. You will also learn a bit about random numbers and graphics programming.

Download Drawing.java as a starting point, and submit your modified file via Canvas by the end of the day.

Part 1: Random Numbers

The Math.random() method generates a double value greater than or equal to 0.0 and strictly less than 1.0. Whenever you call this method, you should get a different result. Each floating-point value in the range [0, 1) is equally likely to be returned over time. Here are two common examples of how to use random numbers in algorithms.

  1. Run code about x percent of the time. Since we know that the return values of Math.random() are equally likely, we can use an if statement and the less than operator. In other words, is the random number less than x?

  2. Program: In the hello method of Drawing, write an if statement that prints "Hello, world!" about half of the time and "Howdy, world!" the other half. Test your method interactively (type Drawing.hello() in jGRASP Interactions instead of clicking on Run). Make sure it displays each value about half of the time.

  3. Generate a random integer between x and y. Let's say we need a number between 5 and 15 inclusive. Notice how there are 11 possible results [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]. We can use Math.random() to get a number in the range [0, 1). If we multiply that number by 11, we now have a number in the range [0, 11). Now we just have to add 5 to that number to shift the range to [5, 16). Finally, we cast the value to an int, which throws away any decimal places.

  4. Program: Complete the method in Drawing named randInt. It should take two integer parameters, x and y, and return a random integer in that range. Test your method interactively (type Drawing.randInt(5, 15) in jGRASP Interactions instead of clicking on Run). Make sure it returns the numbers 5 and 15 at some point.

Part 2: Java 2D Graphics

We're only going to scratch the surface of graphics programming today. You can read a lot more about it in the official Java Tutorials (see Trail: 2D Graphics). We will mainly use the Abstract Window Toolkit, which is Java's old school library for drawing graphics.

  1. Take two minutes to become vaguely familiar with the following classes. Just read the class descriptions and see what methods they have.

  2. The main method of Drawing has been provided for you; do NOT change any of that code. But take a look at it and figure out how it works. Basically it creates a window, adds a canvas to it, and makes it visible. At that point the main method ends, but the window lives on until you close it. The paint method is where all the magic happens.

  3. You are probably used to Cartesian coordinates, where x and y values can be either positive or negative. In contrast, Java uses a coordinate system where the origin is in the upper-left corner. That way, x and y are always positive integers. Coordinates are measured in pixels; each pixel corresponds to a dot on the screen.

  4. Program: The Drawing class comes with methods for drawing diamonds and triangles at specific locations. Modify the vee method so that it draws a diamond on top of the left branch and a triangle on top of the right branch (by calling the provided methods). The size of each shape should be 10.

  5. Notice that when you run the program, it prints each method call to System.out. Use this information to trace the behavior of your code and debug as necessary.

Part 3: More Recursion

What if, instead of drawing a diamond or triangle at the top of each branch of the vee, we draw a vee instead?

  1. Modify the vee method to call itself at the top of each branch. Use depth + 1 for the depth argument. What happens when you run the program at this point?

  2. Add an if statement at the top of vee that returns (from the current method call) if the depth is greater than 6. Now what happens when you run the program?

  3. Change your code so that, at the top of each branch, there's a 50/50 chance whether it will do a recursive call. In other words, at the top of the left branch, it should draw a diamond about half of the time and a vee the other half. On the top of the right branch, it should draw a triangle half of the time and a vee the other half.

  4. At this point, your drawing should look different every time you run the program. Now let's add some fancy colors. In the vee method, change the lines that call g.setColor() to use a random color each time. Replace Color.magenta and Color.blue with new Color(red, green, blue) where red, green, and blue are random integers between 0 and 255. Use the randInt method you made at the beginning of the lab.

Additional References

To learn more about drawing graphics, see the Java 2D tutorial on ZetCode's website.

To learn more about user interfaces (GUIs), see the Swing tutorial on Oracle's website.