Sunday, November 15, 2009

Work in Progress: Program To Draw A Pyramid

Problem: 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 in the window and should use named constants for the following parameters:

BRICK_WIDTH: The width of each brick
BRICK_HEIGHT: The height of each brick
BRICKS_IN_BASE: The nuber of bricks in the base

(Roberts Ch 4, exercise 11).

What's making this difficult:

1) Centering the pyramid. I can use getWidth/2 and getHeight/2 methods to find the center of the screen, and add or subtract to place the brick at a location in reference to the center. However, the bricks are sometimes above the center, sometimes below, sometimes to the right of the center, sometimes to the left. Either I'm missing something (quite likely), or it requires a clunky solution (ie, if four sepeate nested loops for each quadrant of the pyramid).

2) Variables inside the nested "for" statement: The outer "i" loop draws all of the rows, and the inner loop "j" draws all of the bricks inside the rows. The first row has 1 brick, the second row has two bricks, and so on, so I make the inner loop condition sound like this: "From j equals 1 to j equals i, draw a brick", making "i" the endpoint since "i" is the nth row that we're on. However, Eclipse seems to get mad when I reference "i" inside the "j" loop; I don't know why, but it has an angry red line under my i's within the inner loop.

(Click to enlarge)

Stanford Editor - - Eclipse SDK - _Applications_eclipse_Eclipse.app_Contents_MacOS_cs106a_workspace
Uploaded with plasq's Skitch!

I ignored these problems for the time being and tried to see whether I could *just draw* the first brick of the first row. Below is the code for that part; I think it's in the right place. How can I modify it to get to the rest of the pyramid?

* File:
* Name:
* Section Leader:
* ------------------

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

public class Pyramid extends GraphicsProgram {

public void run() {

//Starting from the bottom, build rows
for (int i = BRICKS_IN_BASE; i > 1; i --); {

//For each row; starting from the left, lay bricks
for (int j = 1; j <= 14; j++); {
double x = getWidth()/2 - BRICK_WIDTH * 14/2;
double y = getHeight()/2 + BRICK_HEIGHT * 14/2;
GRect brick = new GRect(x, y, BRICK_WIDTH, BRICK_HEIGHT);
/** Width of each brick in pixels */
private static final int BRICK_WIDTH = 30;

/** Width of each brick in pixels */
private static final int BRICK_HEIGHT = 12;

/** Number of bricks in the base of the pyramid */
private static final int BRICKS_IN_BASE = 14;


What it looks like? One sad brick :(


  1. Looks like the first problem might come from using the program's dimension information (height and width) without also using its location information (x and y coordinates) to determine the placement of the bricks, especially if the window doesn't have a consistent position & size when you run the program -- refer to getX() and getY(), which will give you the coordinates of the upper-left corner of the program window (I think).

    The second problem looks like a "scope" issue. That is, it appears that the "inner" loop doesn't know about i in the "outer" loop because there's not really any nesting happening here -- you have a renegade semicolon after each of your for loops' control expressions. Instead of "for (...) ; {" (renegade semicolon!), try putting them back in the form of "for (...) {" -- otherwise all you have is an empty "for" loop, followed by an explicitly bracketed block of code, which contains another empty "for" loop.

    Also, another handy tip: to see the specific error Eclipse is complaining about, you can hover over the red squiggle or click the red X in the margin of the editor.

    Hope this helps!

  2. This comment has been removed by the author.

  3. Where is the sequel? I came to see the pyramid!