CS46A Lab

Drawing Shapes

Copyright © Cay S. Horstmann, Kathleen O’Brien 2009-2014 Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

See lab2 for reporting instructions.

 

  1. Instance Variables vs. Local Variables
    1. This is a paper-and-pencil exercise that you do with your buddy. You will turn the sheet of paper into your lab instructor.

      If you have found yourself trying to solve homework problems by random tinkering, you may appreciate that there must be a better way. Research shows that students do best in programming when they develop a mental model how the computer works. This exercise will give you a reliable mental model for instance variables and local variables.

      In this exercise, you and your buddy will simulate this Student class. Today's scribe will “be” the Student object. Today's driver will “be” the addQuiz method.


      Be one with the computer

      Scribe: Get out a sheet of paper and draw a diagram of the Student object:

      Make a table that lists the instance variables of a Student object, like this:

      name totalScore quizCount
      Fred 0 0
       
       
       
       
       
       

      Driver: Get out a sheet of paper and draw a table of the parameter and local variables of the addQuiz method.

      score newTotalScore newQuizCount
       
       
       
       
       
       
       
    2. Scribe: Keep these instructions on the screen so that you can give directions to the driver.

      Driver: Have the code of the Student class on the screen so that you can refer to it.

      Scribe: Pick a number between 1 and 10.

      Driver: The addQuiz method is called with that number. Do the following:

      • Fill the number into the score column
      • Look at the first line of code in the method
      • When you want to compute the right hand side score + totalScore, you know what score is. But you don't know what totalScore is—it is not one of your local variables. It is an instance variable. So you need to ask the object. Ask the scribe: What is totalScore?

      Scribe: Tell the driver what totalScore is.

      Driver: Compute score + totalScore and write the value into the newTotalScore column.

      Driver: Fill in newQuizCount in the same way. Remember to ask the scribe for any value that is not a local variable of your method.

      Driver: Move on to the next statement in the method. It asks to update an instance variable. You need to tell the object. Tell the scribe: Update totalScore to ... (whatever value is in your newTotalScore box.)

      Scribe: Update the instance variable as instructed. Cross out the old value and write the new value below it.

      Driver: Move to the last statement in the method and tell the object (the scribe) to update the other instance variable.

      Driver: (very important). The method now exits. All local variables are gone. Cross out all values in the boxes. Or, if you really want to simulate the behavior perfectly, rip up the local variables sheet and draw another one for the next method call.

      Scribe: The object still exists. DO NOT cross out any values.

    3. Repeat step 2.
    4. Driver: Look at the code of getAverageScore. It has no parameters. It uses two instance variables. Ask the scribe for their values. Compute the value that the method returns and tell the scribe.

      Scribe: Record that answer in the lab report. Was it the average of the quiz scores?

    5. From your observations, both of you should formulate a rule when a variable should be a local variable and when it should be an instance variable. (For example, why is totalScore not a local variable? Why is newTotalScore not an instance variable?) Write that rule into your lab report.
  2. Drawing Circles
    1. Make a new BlueJ project. Call it twoShapes. Import the graphics library. Make a class RectangleViewer and copy in this code.
    2. Compile all the classes. Run the program by right-clicking on the RectangleViewer class and selecting main from the menu. Scribe: What happens?
    3. Now replace the Rectangle constructor and data type with the Ellipse constructor and data type. Run the program.

    4. Now turn both ellipses into circles with diameter of 30. Driver: How did you do this? (No, there is no Circle class...)

    5. Now make the second circle twice as large. Driver: What is your code?

    6. Now move the smaller circle inside the larger one, so that they have the same center. This is pretty nasty because you need to specify the top left corner of the circle and not the center. I had to (gasp) get out a piece of paper and figure it out.
      figuring coordinates of center
      1. Scribe: What is the center of the big circle?
      2. Scribe: If I want that point as the center of the little circle, what is its top left corner of the smal circle?
        calculate corner from center

        Figure out the right coordinates. Don't just guess. That may work this time but will not benefit you in the long run. If you can not figure out the algorithm after giving it a good try, ask for help.

        Driver: What is your code now?

  3. Drawing a Bulls Eye
    1. We want to draw a “bulls eye” target, such as this one:

      Make a copy of your twoShapes project and name it bullsEye.

      You can do this by selecting Save As from the Project menu when the workbench has the focus. Or you can make a copy in your file system in the lab4 folder.

      Open the bullsEye project. Close the twoShapes project if it is open. Rename RectangleViewer class to BullsEyeViewer by changing the class name in the code. Compile and run to see that you did this right. Of course, you won't get a bulls eye quite yet—the drawing is still the same.

      Driver: What is the code of your BullsEyeViewer class?

    2. Change the draw method call to fill in the smaller circle, so that you get this output:

    3. Change the color of both circles to red. (Use the setColor method of the Ellipse class.)Driver: What is the code in BullsEyeViewer now?

    4. There is no class Ring for drawing the blue ring. So we need a plan. You will follow this psuedocode in a minute.
       Fill a big blue circle
      Fill a smaller white circle inside the blue one
      Fill the red circle inside the white circle

      Okay now let's get started. First draw a red circle inside a white circle filling them both. Be sure to draw (using the fill method) the bigger circle first

      Oops - we can not see the white circle on our white background!

      bullseye

      Change the color of the larger circle to black for now. Driver: What is the code of your BullsEyeViewer's main method now?

    5. Now add the blue circle. You will have to figure out the x,y coordinates of the upper-left hand corner of the bounding rectangle (Hint: The center is at (50, 65) and the diameter should be 90 which means the radius is 45).

      Change the color of the middle circle back to white.Driver: What is your code now?

  4. Drawing Many Bulls Eyes
    1. If it is good to have one bullseye, it is even better to have lots of them. But we do not want to have to do all that math for each new bullseye. What we need to do is make a class BullsEye that has x, y coordinates and a draw method . Then we will do all the calculations using x and y. And by object-oriented magic, we can easily make as many bullseyes as we want. This is what we are shooting for.

      Start by making a new class BullsEye and adding this code.

      public class BullsEye
      {
         private int x;
         private int y;
      
         /**
          * Constructs a bulls eye with a given center.
          * @param centerX the x coordinate of the center
          * @param centerY the y coordinate of the center
          */
         public BullsEye(int centerX, int centerY)
         {
             x = centerX;
             y = centerY;
         }
         
         /**
          * Draws the bulls eye
          */
         public void draw()
         {              
            
         }
      }     
    2. To draw our bullseye we need to draw circles with a center of (x,y) and different diameters (We will use 30, 60, 90). But we have to know the coordinates of the upper left-hand corner. You made that calculation repeatedly for a specific center in the original bullseye program. Now you need to generalize the algorithm to work for a center (x, y) and a diameter of d. Here is the code to make a circle object with center (x,y) and diameter d and assign it to a object reference.
      Ellipse biggestCircle = new Ellipse(x - d / 2, y - d / 2, d, d);

      You will need to define a local variable for d before this will work. Like this

      int d = 90;

      Use the formula above to change the draw method of the BullsEye class to create and fill the largest circle - the one with a diameter of 90. Make it blue. Driver: What is the code for the draw method?

    3. Replace the code in your BullsEyeViewer's main method with this code which will draw a BullsEyes at three different locations. You will not create Ellipses directly in the BullsEyeViewer. Only add these 6 lines of code.
      BullsEye eye1 = new BullsEye(100, 100);
      eye1.draw();
      BullsEye eye2 = new BullsEye(200, 200);
      eye2.draw();
      BullsEye eye3 = new BullsEye(50, 300);
      eye3.draw();
              

      Run the program. Scribe: Why does it just display three blue circles?

      beginning of three bullseyes

    4. To the draw method of the BullsEye class, add the code to create and fill a white circle with diameter 60. You will need to set d equal to 60 first. Run BullsEyeViewer again.

      second step bulleseye

      We are getting there. Driver: What is the code in the draw method of the BullsEye now?

    5. Add the code to create and draw a red circle with diameter of 30. (Set d = 30 first) Viola! Three bullseyes.

      last bullseye

      Driver: What is the code for the draw method now?