# Thread: Stepwise refinement,, any suggestions?

1. ## Stepwise refinement,, any suggestions?

i'm still just beginning and teaching myself via online courses,
ive sorta got my head around control statements and i've just done some reading on methods :confused: and stepwise refinement.
i would be most grateful for any feedback on the following code examples
(which all work :D and are hopefully self explanatory) particularly on ways of refining or improving them.

Sonny

pyramid program
Java Code:
```/*File pyramid.java
* this program draws a pyramid
* Programming exercise 1 cs106a stanford:
* Assignment #2: Simple Java Programs
*  Write a GraphicsProgram subclass that draws a pyramid consisting of bricks
arranged in horizontal rows, so that the number of bricks in each row decreases by
one as you move up the pyramid
The pyramid should be centered at the bottom of the window and should use
constants for the following parameters:
BRICK_WIDTH The width of each brick (30 pixels)
BRICK_HEIGHT The height of each brick (12 pixels)
BRICKS_IN_BASE The number of bricks in the base (14)
The numbers in parentheses show the values for this diagram, but you must be able
to change those values in your program.
*/

import acm.program.*;
import acm.graphics.*;

public class pyramid extends GraphicsProgram {

private static final int BRICK_WIDTH = 30; //The width of each brick (30 pixels)
private static final int BRICK_HEIGHT = 12; //The height of each brick (12 pixels)
private static final int BRICKS_IN_BASE = 14;  //The number of bricks in the base (14)

public void run(){
int w = getWidth();
int h = getHeight();
int bricksInCourse = BRICKS_IN_BASE;
add(new GLabel(""+(w)+"w "+(h)+"h ", 10,20));// just to help me along
for(int j=0;j<BRICKS_IN_BASE;j++){
for (int i = 0; i<bricksInCourse;i++){
int x = ((w/2)-(bricksInCourse*BRICK_WIDTH/2))+(i*BRICK_WIDTH);
int y = (h-BRICK_HEIGHT-1)-(j*BRICK_HEIGHT);
GRect brick = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
pause(15);
}
bricksInCourse--;
}
}
}```

i realised after my first attempt at drawing a target(below)which used a method to calculate the radii
that relationship of the radii of circles provided a simpler solution if you count down variable i from 3 to 1, hopefully you can see my both my initial and ultimate method of doing it. (what is the plural of radius && how do you spell it ! :))

Java Code:
```/*File target.java
* this program draws a target
* Assignment #2: Simple Java Programs
* Programming exercise 2 draw a target
* The outer circle should have a radius of one inch (72 pixels), the white circle
* has a radius of 0.65 inches, and the inner red circle has a radius of 0.3 inches. The
*figure should be centered in the window of a GraphicsProgram subclass.
*
*/

import java.awt.Color;

import acm.program.*;
import acm.graphics.*;

public class target extends GraphicsProgram {
private static final int PPI = 72; //pixel per inch/outer circle rad pixels
private static final int ICR = 30*PPI/100; // centre circle radius pixel ratio
private static final int WCR = 65*PPI/100; // white circle radius pixel ratio

public void run(){
int w = getWidth()/2;
int h = getHeight()/2;
for(int i=3;i>0;i--){// using i to determine (int r)
int r = i*(WCR-ICR)-5;
//int r = setRad(i);  // if calling setRad then set for loop to:(int i=0;i<3;i++)
GOval target = filledCircle(w,h,r);
target.setFillColor(Color.RED);
target.setColor(Color.RED);
}else{
target.setFillColor(Color.WHITE);
target.setColor(Color.WHITE);
}
pause(1000);
}
}

if (r==0)return PPI;
if (r==1)return WCR;
if (r==2)return ICR;
return r;

}
private GOval filledCircle (int x, int y, int r){
GOval circle = new GOval(x-r,y-r ,r*2,r*2);
circle.setFilled(true);
return circle;

}
}```
Last edited by sonny; 02-27-2010 at 07:50 AM.

2. Senior Member
Join Date
Mar 2010
Posts
952
Rep Power
7
Hi Sonny,

I think you're missing the point a bit on these two exercises by putting all of your code directly into the run() method. Try these strategies and see if they don't give you simpler, more readable code:

Pyramid:

Write a drawBrick(double x, double y) method. The brick's width and height should come from constants in your Pyramid class. Test your method by putting something like drawBrick(10, 10) in your run() method.

Next, write a drawRowOfBricks(double x, double y, int n) method that uses a for loop and the drawBrick(x, y) you wrote in the first step. Test it by changing your run() method to call drawRowOfBricks(10, 10, 5).

Now write drawCenteredRowOfBricks(double y, int n) that figures out where the first x should be and then calls drawRowOfBricks(x, y, n). Test it with something like drawCenteredRowOfBricks(10, 5) in your run() method.

Once you've implemented those three methods, you can do your run() method with one call to find the bottom of the window, and then one for loop to draw the whole pyramid. (Hint: your for loop won't start with "for (int i = 0; ..." but rather with "for (int i = BRICKS_IN_BASE; ...".) Arguably, it's still better style to put that code in a separate drawPyramid() method, and call that from run().

Target:

Using a similar approach to above, write a method that draws a filled circle based on its center point, radius in inches, and color. Do the inches to pixels conversion in a separate method.

The whole idea is to try to think in terms of each method doing one simple thing. I know it seems silly now -- why put code in a separate method if you're only calling it from one place, right? But trust me and go through the motions of doing it, and then take a look at your finished program and tell me if it isn't cleaner and easier to read. After all, these are exercises. The point isn't to draw a pyramid or a target but to internalize the concepts.

-Gary-

3. ## sorry for delayed response but haven't been on for a over a week

The whole idea is to try to think in terms of each method doing one simple thing. I know it seems silly now -- why put code in a separate method if you're only calling it from one place, right?
After all, these are exercises. The point isn't to draw a pyramid or a target but to internalize the concepts.

I see what you mean many thanks Gary a really great help,
my last programming experience was back in the 1980's when i was kid and i was pretty adept back then at using BASIC. Its difficult getting my head around methods, i keep thinking "subroutine" but its not the same thing.

I have rewritten pyramid (below) and it did take me much longer to do it this way than the first way however i have been re writing some of the other exercises and I think the penny is starting to drop.

Would it be fair to say that as a general rule of thumb I should try to avoid using control statements within run() and create a method

heres my rewrite which IS much easier follow:D

Java Code:
```import acm.program.*;
import acm.graphics.*;

public class pyramid2 extends GraphicsProgram {

private static final int BRICK_WIDTH = 30; //The width of each brick (30 pixels)
private static final int BRICK_HEIGHT = 12; //The height of each brick (12 pixels)
private static final int BRICKS_IN_BASE = 14;  //The number of bricks in the base (14)

public void run(){
beginPyramid();
}

/*determine y coordinates to start each row of bricks calls rowOfBricks*/
private void beginPyramid(){
int h = getHeight();
int rows=0;
for(int i=BRICKS_IN_BASE;i>0;i--){
int y = (h-BRICK_HEIGHT-1)-(rows*BRICK_HEIGHT);
rowOfBricks(y,i);
rows++;
}
}

/* determines x coordinates for all the bricks in the row(n)and calls draw brick n times*/
private void rowOfBricks(double y, int n){
int x = (getWidth()/2)-(n*BRICK_WIDTH/2);
for (int i=0;i<n;i++){
drawBrick(x+(i*BRICK_WIDTH),y);
}
}

/*  draws a brick at coordinates x and y */
private GRect drawBrick(double x, double y){
GRect brick = new GRect(x,y,BRICK_WIDTH,BRICK_HEIGHT);
pause(15);
return brick;
}
}```

4. Senior Member
Join Date
Mar 2010
Posts
952
Rep Power
7
Nice work, Sonny. I came up learning BASIC as well, on very low-memory machines (TI-99/4a -- a whole 16K of RAM!) and while we learned some things that are very valuable, we were also forced to learn some bad habits.

One of the big advantages of methods is variable scoping. If you keep your methods down to one loop, for example, and call a method for the inner loop, then you can always use 'i' as your index variable, and reduce the complexity you're carrying around in your head. Of course it doesn't always make sense to do it this way, but quite often it does. In BASIC we didn't have that luxury. Even if we used a GOSUB, we were still dealing with the same global variables, and had to keep track of all of them program-wide.

By the way, your beginPyramid() can still be a little simpler:
Java Code:
```	/*determine y coordinates to start each row of bricks calls rowOfBricks*/
private void beginPyramid(){
int y = getHeight();
for(int i=BRICKS_IN_BASE; i > 0; i--){
y -= BRICK_HEIGHT;
rowOfBricks(y, i);
}
}```
Cheers!

-Gary-

5. ## Snap!

WOW! TI99/4a , SNAP! I had one of those! :D
probably the best machine of its day, i think it was the first 16bit home computer, All my mates had specy's and vic 20's, which had loads of games. but the TI outstripped em all, you just had to be prepared to type in games from magazines and stuff then save them. oh man! good times indeed!
i intend trying to do carwars in Java once i progress a bit, i loved that game

y -= BRICK_HEIGHT;
Brilliant, much simpler, that hadnt occured to me, but seems so obvious

many thanks
Sonny

6. Member
Join Date
May 2011
Posts
2
Rep Power
0

## Question...

"private void rowOfBricks(double y, int n)"

This is coming from a serious newbie, so I hope you will bear with me if the answer to this question should be obvious.

Why set the type for 'y' to double since the value passed on to this method for 'y' is from a variable that was type int? All that does is just tack ".0" to the end of it, right?

Thanks.

7. Senior Member
Join Date
Mar 2010
Posts
952
Rep Power
7
Originally Posted by hoosiertechguy
Why set the type for 'y' to double since the value passed on to this method for 'y' is from a variable that was type int? All that does is just tack ".0" to the end of it, right?
That's an excellent question. Basically, we specify a double because the drawBrick() method we're going to call wants a double. And we specified doubles in drawBrick() because the GRect() constructor provided by the library we're using wants doubles. That may seem strange as well (pixels on the screen are discrete, right? you can't really put a dot at 22.3, 57.8 on the screen, can you?) but it turns out that in lots of situations, using doubles for screen coordinates makes sense. I'll let you discover those situations on your own -- take my word for it for now. You're right that in this program it wouldn't make any difference, but it's generally a good habit to use the same types used by the methods you're calling.

-Gary-

8. Member
Join Date
May 2011
Posts
2
Rep Power
0
Thank you, Gary. That makes sense now that I actually take a closer look at the drawBrick method. Does it matter when you cast the int as a double? The variable 'y' is cast as a double in the rowOfBricks method, but 'x' is not cast as a double until the drawBrick method, I'm not trying to nitpick, I'm just trying to wrap my mind around the best practices, so I hope no one takes offense. My current profession is as a Small Business Network Engineer, so I'm a little bit Obsessive/Compulsive about these kind of things, I guess.

9. Senior Member
Join Date
Mar 2010
Posts
952
Rep Power
7
You're right that the x in the body of rowOfBricks() should probably be a double too, as should the h and y in beginPyramid(). Again, for this exercise, it didn't make any real difference.

-Gary-

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•