Tuesday, January 4, 2011

2 Programs to Draw a Target Graphic

Problem: "Rewrite the Target program given in Ch2 so that it uses the createFilledCircle method that appears in Figure 5.3. In addition, change the program so that the target is always centered in the window and so that the number and dimensions of the circles are controlled y the following named constants:

private static final int N_CIRCLES = 5;
private static final double OUTER_RADIUS = 75;
private static final double INNER_RADIUS = 10;

(Roberts ch 5, problem 5)

What it looks like:


What the code looks like: New Version:

/*

/*
 * File: TargetWithMethod.java
 * Name: 
 * Section Leader: 
 * -----------------
  * This is the new and improved version of the Target program. As with the old version, we draw 
  * the graphic by laying a bunch of concentric circles on top of each other. However, unlike the 
  *  old version, we draw the program with a "while" loop and a method to create the circles. The
  *  static contants give us number of circles, the outer radius, and the inner radius. Once those are established, 
  *  we derive the x and y coordinates to center our target graphic and the width of each ring. Then we go into a 
  *  "while" loop to keep adding new concentric circles on top of each other until the innermost circle is too small 
  *  (the radius is smaller than the target's rings). At the end of each loop, we change the "radius" 
  *  varible to make the next, smaller circle and we switch the boolean so that the colors can switch from red
  *  to white and back.
 */


package ch6_practice;

import acm.graphics.*;
import acm.program.*;
import java.awt.*;



public class TargetWithMethod extends GraphicsProgram {
    private static final int N_CIRCLES = 5;
    private static final double OUTER_RADIUS = 75;
    private static final double INNER_RADIUS = 10;
 
 
    public void run() {
  
        int center_x = getWidth()/2;
        int center_y = getHeight()/2;
        double band_width = OUTER_RADIUS/N_CIRCLES;
  
        double radius = OUTER_RADIUS;
        boolean is_colored_band = true;
  
        while (radius >= band_width) {
            if(is_colored_band) {
                add(createFilledCircle(center_x, center_y, radius, Color.RED));
            }
            else {
                add(createFilledCircle(center_x, center_y, radius, Color.WHITE));
            }   
            is_colored_band = !is_colored_band;
            radius -= band_width;
       }
 
   }
 
    private GOval createFilledCircle (int x, int y, double r, Color color) {
  
        GOval circle = new GOval (x-r, y-r, 2*r, 2*r); //The method input becomes the center
        circle.setColor(color);
        circle.setFilled(true);
        return circle;
  
    }
}





Old Version:

/*
/*
 * File: Target.java
 * Name: 
 * Section Leader: 
 * -----------------
 * This is the old, static version of the target program. It makes three red concentric circles, named
 * "outer," "white," and "center." It uses the GOval method and the arguments for position and size are
 * explicitly hard-coded in.
 */

import acm.graphics.*;
import acm.program.*;
import java.awt.*;

public class Target extends GraphicsProgram { 
    public void run() {
    GOval outer = new GOval(75, 50, 100, 100);
    outer.setColor(Color.RED);
    outer.setFilled(true);
    outer.setFillColor(Color.RED);
    add (outer);
 
    GOval white = new GOval(95, 70, 60, 60);
    white.setColor(Color.white);
    white.setFilled(true);
    white.setFillColor(Color.white);
    add (white);
 
    GOval center = new GOval(115, 90, 20, 20);
    center.setColor(Color.red);
    center.setFilled(true);
    center.setFillColor(Color.red);
    add (center);
    }
}



How long it took: 40 min

What makes the old version not-so-good: We had to hard-code in the coordinates for each of the rings, which is a pain to figure out. If we miscalculate, or if later on we want each of the rings to be a bit bigger/smaller, we have to redo a bunch of annoying arithmetic over again.

Later on I redid this code making the x and y coordinates variables that used the getHeight() and getWidth() methods, so the position of the board depended on the graphics window we were in. This was a bit better. However, the version that uses the createFilledCircle method is even better because besides always being sure the target is centered, we can be flexible with the number of rings, the overall size of the target, and the width of each ring.

What made it difficult: Nothing too difficult here; I did get stumped at the part where you switch the color from red to white. I knew that I wanted to make it the last step in my loop to switch the boolean, but I didn't know that you can switch booleans with the "!" operator (like this: "is_colored_band = !is_colored_band;" ), thanks Jane/Jason for the tip. I was going to go about it with 1 and -1, but this is much better.

2 comments:

  1. You've never used constant INNER_RADIUS.

    ReplyDelete
  2. if you look at the picture in the book outer(red) circle thinner than inside(white)

    ReplyDelete