CS106a Checkerboard optimization - java

I'm learning Java out of The Art & Science of Java by Roberts (Stanford's CS106a text). I'm using NetBeans as my IDE.
Chapter 4, exercise 14 asks you to expand on a Checkerboard program introduced earlier. Specifically, it asks you to center the checkerboard and draw a set of red & white checks corresponding to the initial state of the game.
I've accomplished as much as requested, but have two issues-
The board is not completely centered in the window. It is closer to the left side of the window than the right side. I am not sure how to center it more. Am I doing this right? Is there a setting in NetBeans I can/should change?
The checkers are supposed to take up a large portion of the tiles they sit on. I assigned the size of my checkers to be dependent on the size of tiles so that the setup would be simple and proportionate. Is there a better way to do this to make the checkers bigger?
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Checkerboard extends GraphicsProgram{
public void run(){
double sqSize = (double)getHeight() / N_ROWS;
for (int i = 0; i < N_ROWS; i++){
for(int j = 0; j < N_COLUMNS; j++){
double x = ((j * sqSize) + (getWidth() / N_COLUMNS)); //centers square??
double y = (i * sqSize);
GRect sq = new GRect( x, y, sqSize, sqSize );
sq.setFilled((i + j) % 2 != 0);
sq.setFillColor(Color.GRAY);
add(sq);
double circleCoord = (sqSize * .33);
double xx = ((j * sqSize) + (getWidth() / N_COLUMNS) + circleCoord);
double yy = ((i * sqSize) + circleCoord);
if((i + j) % 2 != 0 && i < 3 ){
GOval red = new GOval( xx, yy, circleCoord, circleCoord);
red.setFilled(true);
red.setFillColor(Color.RED);
add(red);
} else if((i + j) % 2 != 0 && i > 4 ){
GOval black = new GOval( xx, yy, circleCoord, circleCoord);
black.setFilled(true);
black.setFillColor(Color.BLACK);
add(black);
}
}
}
}
private static final int N_ROWS = 8;
private static final int N_COLUMNS = 8;
}

For 1. The center of the board should be in the center of the width, too. So we know that
The left edge of tile N_COLUMNS/2 = getWidth()/2 e.g. tile 4 in 0 indexing has its left edge in the center
And every tile left or right of that will have a movement of sqSize, so:
double x = getWidth()/2 + (j-N_COLUMNS/2)*sqSize

Related

How would I implement a display showing points within a triangle in java?

So I am trying to make an iterative program to show the chaos game with sierpinski's triangle. You start at (0,0) and randomly go half-way to either (0, 0), (1, sqrt(3)) or (2, 0). Repeating leaves a fractal pattern. My code in java would roughly be:
public class Sierpinski {
public static void main(String[] args) {
double x = 0;
double y = 0;
int n = 0;
while(true) {
// point on at (x,y) - this is what I need help with
// generates random number from 0 to 2
n = (int)(3 * Math.random())
// x and y randomly go halfway to one point
x += ((n == 1) ? 1 : 0) + ((n == 2) ? 2: 0);
y += ((n == 1) ? Math.sqrt(3) : 0);
x /= 2;
y /= 2;
}
}
}
How would I implement a graph with bounds 0 to 2 in x and y direction that displays these points at each iteration?
Thanks
By the way, it's a nice project ;)
To make a window in Java and draw graphics, you need two things: A JFrame and a Canvas.
JFrame is the frame of your app, just like when you are opening a a Windows app.
Canvas is a surface where we can draw graphics on it. It has a width and an height
in pixels.
To simplify things, I made a Window class that manage both of them. Here is the code:
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.Canvas;
import java.awt.Color;
public class Window
{
//width and height of the canvas
private static final int WIDTH = 600;
private static final int HEIGHT = 600;
JFrame frame;
Canvas canvas;
public Window()
{
JFrame frame = new JFrame();
canvas = new Canvas();
canvas.setSize(WIDTH, HEIGHT);
//We add the canvas inside of the frame
frame.add(canvas);
//make the frame to fit the size of the canvas
frame.pack();
//click on the X button to close the app
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//set the app in the middle of the screen
frame.setLocationRelativeTo(null);
frame.setTitle("Sierpinski");
frame.setVisible(true);
}
//We call this method from your code
public void paint(double x, double y)
{
/*
Since your numbers range is between 0 and 2,
We need to adapt it to the size of the canvas.
The result would be random coordinates on the canvas.
*/
int coordX = (int)(x / 2 * WIDTH);
/*
Because in Java Y axe is reversed, we need to convert into its reversed value on the screen. Ex:
pixel (0,0) => pixel (0,599)
pixel (0,10) => pixel (0,589)
*/
int coordY = HEIGHT - ((int)(y / 2 * HEIGHT) + 1);
/*
Graphics is like a paintbrush for a specific object.
We are asking the canvas to give us his paintbrush.
*/
Graphics g = canvas.getGraphics();
//Try to execute the line below!
//g.setColor(Color.BLUE);
/*
Draw a rectangle of width and height of 1 pixel.
*/
g.fillRect(coordX, coordY, 1, 1);
}
}
finally, we need to create this Window object within your code, and call the paint method:
public class Sierpinski {
public static void main(String[] args) {
Window window = new Window();
double x = 0;
double y = 0;
int n = 0;
while(true) {
// point on at (x,y) - this is what I need help with
// generates random number from 0 to 2
n = (int)(3 * Math.random());
// x and y randomly go halfway to one point
x += ((n == 1) ? 1 : 0) + ((n == 2) ? 2: 0);
y += ((n == 1) ? Math.sqrt(3) : 0);
x /= 2;
y /= 2;
window.paint(x, y);
}
}
}
You should get a result like this:
The result expected
There is much you can do with it. You can check official documentation on Oracle web site or look at some tutorials on Youtube.
Canvas documentation
Graphics documentation
JFrame documentation
Have fun!

Cannot work out how to compare 2 dimensional arrays of different sizes

So I am building a project in order to build a tetris style game, and I want to be able to test whether the shape will be able to be added to a 5 x 5 grid. The shape is modelled by a 2D array, where a 1 is considered to be a single block of the shape (the shapes are made of a few blocks). The shapes are modelled with a 3 x 3 grid. The thing I must do is check the grid for whether the shape will be able to fit on top of it. Take for example placing a line shape at the top square of the grid, the line will go out of bounds and should not work, or another example is that the grid may already have a shape on it and so the line should not be able to be put on top of it.
This is the code that I've got thus far, and it is not working, I'm just really having a tough time conceptualising what to do. Thank you in advance.
Please note that cols is the number of columns in the grid (5) and rows is the same (5). Game piece is the shape, and the co-ordinates is where the user has clicked on the 5x5 grid.
Also: The anchor point of the shape is 1,1 of the 3x3 grid (so the anchor point is right in the middle of the grid). And get(int x, int y) method is getting the value stored in the 5x5 grid.
Sorry if this was not made clear in the beginning but I am trying to basically see whether the shape stored in the 3x3 grid (made up of blocks) can be placed on top of the 5x5 grid. The 3x3 grid that contains the block has a centre anchor point, so it would be 1,1 (since arrays start with 0). If the 5x5 grid has other blocks that are at the same co-ordinate of the new shape being added, then I want it to return false or if the shape becomes out of bounds when being placed on the 5x5 grid, but if it can be added successfully then it will return true.
public boolean canPlayPiece (GamePiece piece, int x, int y) {
logger.info("canPlayPiece - Block clicked coordinates: " + x + "," + y);
// Piece co-ordinates are 3 x 3, each element that is 1 means there is a block there
int[][] pieceCoordinates = piece.getBlocks();
// For loop to iterate through the grid
// first looping through x values
for (int i = x - 1; i < cols; i++) {
System.out.println("i= " + i);
// nested for loop to find the y values stored inside the x
for (int j = y - 1; j < rows; j++) {
System.out.println("j: " + j);
if (pieceCoordinates[x][y] == 1 && get(i,j) != 0) {
logger.info("canPlayPiece: FALSE");
return false;
}
}
}
logger.info("canPlayPiece: TRUE");
return true;
}
Ok i made the following for you:
public boolean canPlayPiece(GamePiece piece, int x, int y) {
int[][] pc = piece.getBlocks();
final int w = 3, h = 3, e = w - 1;
final int offX = -1, offY = -1; // The offset of the left top corner from 'x' and 'y'
int i, si, ei, ax, ay, rx, ry;
for (ei = w * h - 1; ei >= 0 && pc[ei / w][ei % w] == 0; ei--);
for (si = 0; si <= ei && pc[si / w][si % w] == 0; si++);
for (i = si + 1, ax = si % w; ax > 0 && i <= ei; i++) if (pc[i / w][rx = i % w] != 0) { si += Math.min(rx - ax, 0); ax = rx; }
for (i = ei - 1, ax = ei % w; ax < e && i >= si; i--) if (pc[i / w][rx = i % w] != 0) { ei += Math.max(rx - ax, 0); ax = rx; }
if (si > ei) return true; // There is no block in the piece's grid
int sx = si % w, sy = si / w, ex = ei % w, ey = ei / w; // The bounds of the shape inside of pc
int asx = x + offX + sx, asy = y + offY + sy, aex = asx + ex - sx, aey = asy + ey - sy;
if ((asx | asy | aex | aey | cols - 1 - aex | rows - 1 - aey) < 0) return false; // Would be out of bounds
for (rx = sx, ax = asx; rx <= ex; rx++, ax++) {
for (ry = sy, ay = asy; ry <= ey; ry++, ay++) {
// if (grid[ay][ax] != 0 && pc[ry][rx] != 0) return false; // Block overlaps another block
if (get(ax, ay) != 0 && pc[ry][rx] != 0) return false; // Block overlaps another block
}
}
return true;
}
First it figues out the bounds of the shape inside of 'pc' grid (the grid returned by 'piece.getBlocks()')
If there is no shape inside of 'pc' it will return true, since an empty shape can be placed anywhere (change the return value to false, if you want to return false in that case)
If the inner shape would go out of bounds, when being inserted, it will return false
In the end it will walk through both the grid (using your 'get(x: int, y: int) function) and 'pc' to check whether the shape in 'pc' overlaps with any preexisting blocks inside the grid. And if it doesn't it returns true.
I really hope that this works for you. I tested it out and it worked at least for me.

How can I use an arraylist to store coordinates to draw random points of different colors in a fixed area?

The assignment is to draw chips on a supposed cookie at random points while counting each chip and storing the coordinates so that each chip doesn't move. Each chip should be a different color and initiated on a mouse press.
I've tried to put the coordinates into an array, multiple arrays a single array list and tried to use if and for loops. The results before were that it would generate a single chip of a different colour each click (sort of because sometimes the random number generated is outside of my specified range). After using and looping through multiple array lists the current behaviour is that it generates a grid and the count is exponentially growing with each click, some points have a lot of overlap and the chips in the grid all ave one colour i.e. The last to be assigned
//Put graphics code here
public void draw(Graphics g){
ArrayList coordinates = new ArrayList();
col1= generator.nextInt(256) + 0;
col2= generator.nextInt(256) + 0;
col3= generator.nextInt(256) + 0;
canvasMaxWidth=800;
canvasMaxHeight=600;
canvasMinWidth=400;
canvasMinHeight=200;
int newX = (int) (Math.random() * canvasMaxWidth) + canvasMinWidth;
int newY = (int) (Math.random() * canvasMaxHeight) + canvasMinHeight;
Point point = new Point(newX, newY);
g.setColor(new Color(205,133,63));
g.fillOval(canvasMinWidth,canvasMinHeight,400,400);
for(Point point : coordinates){
if(point.y > 249 && point.y < 549 && point.x > 449 && point.x < 749){
g.setColor(new Color(col1, col2, col3));
g.fillOval(point.x, point.y, 7, 7);
}
}
g.setColor(Color.black);
g.drawString("Number of Sprinkles: "+ count, 100, 80);
}
//Code to respond to a mouse press
public void mousePressed(MouseEvent mouse){
}
The expected result is essentially a speckled disk that counts each speckle on the disk with each speckle not moving.
At present it appears that no point is moving but there's not a lot of randomness to what is happening. the speckles multiply each click vs iterate and form a grid.
ArrayList<Point> coordinates = new ArrayList<Point>();
is much easier to track coordinates rather than using two separate lists. Everything is happening in a grid format because you are using a nested for loop for i and j.
You are currently performing:
if i = 0, 1, 2 and j = 0 , 1, 2
i j
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
so you can see where the grid-like layout is coming from. Using a Point object, you could instead do:
for(Point point : coordinates){
if(point.y > 249 && point.y < 549 && point.x > 449 && point.x < 749){
g.setColor(new Color(col1, col2, col3);
g.fillOval(point.x, point.y, 7, 7);
}
}
I'm unsure why you are using a counter, as it would be performing for the length of the coordinates. If you would like to add randomness, then you can dynamically create values using the Random class.
int colorValue = (int) (Math.random() * 255);
and if you wanted to perform random positions, you could randomly generate them through:
int newX = (int) (Math.random() * (canvasMaxWidth - canvasMinWidth)) + canvasMinWidth;
int newY = (int) (Math.random() * (canvasMaxHeight - canvasMinHeight)) + canvasMinHeight;
Point point = new Point(newX, newY);
Edit with your code:
int newX = (int) (Math.random() * (canvasMaxWidth - canvasMinWidth)) + canvasMinWidth;
int newY = (int) (Math.random() * (canvasMaxHeight - canvasMinHeight)) + canvasMinHeight;
Point point = new Point(newX, newY);
coordinates.add(point);
counter++;
redList.add((int) (Math.random() * 255));
greenList.add((int) (Math.random() * 255));
blueList.add((int) (Math.random() * 255));
g.setColor(new Color(205,133,63));
g.fillOval(canvasMinWidth,canvasMinHeight,400,400);
for(int z = 0; z < coordinates.size(); z++){
if(coordinates.get(z).y > 249 && coordinates.get(z).y < 549 && coordinates.get(z).x > 449 && coordinates.get(z).x < 749){
g.setColor(new Color(redList.get(z).intValue(), greenList.get(z).intValue(), blueList.get(z).intValue()));
g.fillOval(coordinates.get(z).x, coordinates.get(z).y, 7, 7);
}
}
Edit #2: here is a sample of how you would have the static variables
public class myClass{
static ArrayList<Point> coordinates = new ArrayList<Point>();
static ArrayList<Integer> redList = new ArrayList<Integer>();
static ArrayList<Integer> greenList = new ArrayList<Integer>();
static ArrayList<Integer> blueList = new ArrayList<Integer>();
static int counter = 0;

Implementing a License plate detection algorithm

To improve my knowledge of imaging and get some experience working with the topics, I decided to create a license plate recognition algorithm on the Android platform.
The first step is detection, for which I decided to implement a recent paper titled "A Robust and Efficient Approach to License Plate Detection". The paper presents their idea very well and uses quite simple techniques to achieve detection. Besides some details lacking in the paper, I implemented the bilinear downsampling, converting to gray scale, and the edging + adaptive thresholding as described in Section 3A, 3B.1, and 3B.2.
Unfortunately, I am not getting the output this paper presents in e.g. figure 3 and 6.
The image I use for testing is as follows:
The gray scale (and downsampled) version looks fine (see the bottom of this post for the actual implementation), I used a well-known combination of the RGB components to produce it (paper does not mention how, so I took a guess).
Next is the initial edge detection using the Sobel filter outlined. This produces an image similar to the ones presented in figure 6 of the paper.
And finally, the remove the "weak edges" they apply adaptive thresholding using a 20x20 window. Here is where things go wrong.
As you can see, it does not function properly, even though I am using their stated parameter values. Additionally I have tried:
Changing the beta parameter.
Use a 2d int array instead of Bitmap objects to simplify creating the integral image.
Try a higher Gamma parameter so the initial edge detection allows more "edges".
Change the window to e.g. 10x10.
Yet none of the changes made an improvement; it keeps producing images as the one above. My question is: what am I doing different than what is outlined in the paper? and how can I get the desired output?
Code
The (cleaned) code I use:
public int[][] toGrayscale(Bitmap bmpOriginal) {
int width = bmpOriginal.getWidth();
int height = bmpOriginal.getHeight();
// color information
int A, R, G, B;
int pixel;
int[][] greys = new int[width][height];
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = bmpOriginal.getPixel(x, y);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
greys[x][y] = gray;
}
}
return greys;
}
The code for edge detection:
private int[][] detectEges(int[][] detectionBitmap) {
int width = detectionBitmap.length;
int height = detectionBitmap[0].length;
int[][] edges = new int[width][height];
// Loop over all pixels in the bitmap
int c1 = 0;
int c2 = 0;
for (int y = 0; y < height; y++) {
for (int x = 2; x < width -2; x++) {
// Calculate d0 for each pixel
int p0 = detectionBitmap[x][y];
int p1 = detectionBitmap[x-1][y];
int p2 = detectionBitmap[x+1][y];
int p3 = detectionBitmap[x-2][y];
int p4 = detectionBitmap[x+2][y];
int d0 = Math.abs(p1 + p2 - 2*p0) + Math.abs(p3 + p4 - 2*p0);
if(d0 >= Gamma) {
c1++;
edges[x][y] = Gamma;
} else {
c2++;
edges[x][y] = d0;
}
}
}
return edges;
}
The code for adaptive thresholding. The SAT implementation is taken from here:
private int[][] AdaptiveThreshold(int[][] detectionBitmap) {
// Create the integral image
processSummedAreaTable(detectionBitmap);
int width = detectionBitmap.length;
int height = detectionBitmap[0].length;
int[][] binaryImage = new int[width][height];
int white = 0;
int black = 0;
int h_w = 20; // The window size
int half = h_w/2;
// Loop over all pixels in the bitmap
for (int y = half; y < height - half; y++) {
for (int x = half; x < width - half; x++) {
// Calculate d0 for each pixel
int sum = 0;
for(int k = -half; k < half - 1; k++) {
for (int j = -half; j < half - 1; j++) {
sum += detectionBitmap[x + k][y + j];
}
}
if(detectionBitmap[x][y] >= (sum / (h_w * h_w)) * Beta) {
binaryImage[x][y] = 255;
white++;
} else {
binaryImage[x][y] = 0;
black++;
}
}
}
return binaryImage;
}
/**
* Process given matrix into its summed area table (in-place)
* O(MN) time, O(1) space
* #param matrix source matrix
*/
private void processSummedAreaTable(int[][] matrix) {
int rowSize = matrix.length;
int colSize = matrix[0].length;
for (int i=0; i<rowSize; i++) {
for (int j=0; j<colSize; j++) {
matrix[i][j] = getVal(i, j, matrix);
}
}
}
/**
* Helper method for processSummedAreaTable
* #param row current row number
* #param col current column number
* #param matrix source matrix
* #return sub-matrix sum
*/
private int getVal (int row, int col, int[][] matrix) {
int leftSum; // sub matrix sum of left matrix
int topSum; // sub matrix sum of top matrix
int topLeftSum; // sub matrix sum of top left matrix
int curr = matrix[row][col]; // current cell value
/* top left value is itself */
if (row == 0 && col == 0) {
return curr;
}
/* top row */
else if (row == 0) {
leftSum = matrix[row][col - 1];
return curr + leftSum;
}
/* left-most column */
if (col == 0) {
topSum = matrix[row - 1][col];
return curr + topSum;
}
else {
leftSum = matrix[row][col - 1];
topSum = matrix[row - 1][col];
topLeftSum = matrix[row - 1][col - 1]; // overlap between leftSum and topSum
return curr + leftSum + topSum - topLeftSum;
}
}
Marvin provides an approach to find text regions. Perhaps it can be a start point for you:
Find Text Regions in Images:
http://marvinproject.sourceforge.net/en/examples/findTextRegions.html
This approach was also used in this question:
How do I separates text region from image in java
Using your image I got this output:
Source Code:
package textRegions;
import static marvin.MarvinPluginCollection.findTextRegions;
import java.awt.Color;
import java.util.List;
import marvin.image.MarvinImage;
import marvin.image.MarvinSegment;
import marvin.io.MarvinImageIO;
public class FindVehiclePlate {
public FindVehiclePlate() {
MarvinImage image = MarvinImageIO.loadImage("./res/vehicle.jpg");
image = findText(image, 30, 20, 100, 170);
MarvinImageIO.saveImage(image, "./res/vehicle_out.png");
}
public MarvinImage findText(MarvinImage image, int maxWhiteSpace, int maxFontLineWidth, int minTextWidth, int grayScaleThreshold){
List<MarvinSegment> segments = findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextWidth, grayScaleThreshold);
for(MarvinSegment s:segments){
if(s.height >= 10){
s.y1-=20;
s.y2+=20;
image.drawRect(s.x1, s.y1, s.x2-s.x1, s.y2-s.y1, Color.red);
image.drawRect(s.x1+1, s.y1+1, (s.x2-s.x1)-2, (s.y2-s.y1)-2, Color.red);
image.drawRect(s.x1+2, s.y1+2, (s.x2-s.x1)-4, (s.y2-s.y1)-4, Color.red);
}
}
return image;
}
public static void main(String[] args) {
new FindVehiclePlate();
}
}

acm.program.GraphicsProgram, not able to get appropriate size of canvas

This is not a homework problem. I am only going over a freely available course from Stanford. I am using Ubuntu Linux with Eclipse.
Problem and Question:
I am drawing rectangles by calling add() on a acm.program.GraphicsProgram object. I am drawing certain number of rectangles which have a certain fixed width. However I am seeing that my rectangles are flowing off the visible area. I have tried setting a big enough width and height for both the GraphicsProgram object and the GCanvas object but still my rectangles are falling off the visible area. I always get the same height for GraphicsProgram object no matter what height I set. Any pointers as to what am I doing wrong?
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Pyramid extends GraphicsProgram {
/** 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;
public void run() {
setWindowSize();
this.createPyramid();
}
private void createPyramid()
{
int centerX = findCenter();
int startingX = centerX - (BRICKS_IN_BASE / 2) * BRICK_WIDTH;
int startingY = BRICK_HEIGHT;
for(int numBricks = BRICKS_IN_BASE; numBricks>= 1; numBricks--)
{
this.layBricks(startingX,startingY , numBricks);
startingX = startingX + BRICK_WIDTH / 2;
startingY = (BRICKS_IN_BASE - numBricks + 2) * BRICK_HEIGHT;
}
}
private void layBricks(int x, int y, int numOfBricks)
{
for(int i = 0; i < numOfBricks; i++)
{
add(new GRect(x,y,this.BRICK_WIDTH, this.BRICK_HEIGHT));
x+=this.BRICK_WIDTH;
}
}
private void setWindowSize()
{
int width = BRICK_WIDTH * BRICKS_IN_BASE * 2;
int height = BRICKS_IN_BASE * BRICK_HEIGHT * 2;
this.setSize(width, height);
//this.setForeground(Color.GREEN);
//this.setBackground(Color.BLUE);
//this.getGCanvas().setBounds(0, 0, width, height);
//this.getGCanvas().add(new GRect(0,0,300,30));
//this.getGCanvas().setBackground(Color.WHITE);
System.out.println(this.getHeight());
System.out.println(this.getWidth());
System.out.println(this.getGCanvas().getHeight());
System.out.println(this.getGCanvas().getWidth());
}
private int findCenter()
{
return this.getWidth() / 2;
}
}
I'm working through the same Stanford course online and ran into the same problem. The setSize method would resize the display but not the values returned by getWidth and getHeight.
You can change the width and height by going to Project > Properties > Run/Debug Settings > Edit > Parameters tab.
I assume there is something more direct or code-based, but this is an easy solution.
Start by not hard coding the brick sizes like this
int brick_width = (getWidth() / BRICKS_IN_BASE) - (getWidth() / 50);
int brick_height = (brick_width / 3);
That way your pyramid will always be drawn within whatever the screen size happens to be.
It should also be centered, once your brick sizes are relative to window size, guaranteeing that the bricks will always be centered becomes easier. The only wrench I have found are weird
window sizes such as 50 x 500, but that doesn't happen too often.
Here is a look at my solution
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class Pyramid1 extends GraphicsProgram {
public void run(){
int brick_width = (getWidth() / BRICKS_IN_BASE) - (getWidth() / 50);
int brick_height = (brick_width / 3);
for(int n = 0; n < BRICKS_IN_BASE; n++ ){
//make a row at level n of bricks that is BRICKS_IN_BASE - n bricks wide.
int bricks_in_level = BRICKS_IN_BASE - n;
int x = ((getWidth() / 2) - ((bricks_in_level * brick_width) / 2)); //find the center then offset to farthest left.
int y = (((getHeight() / 2) + ((BRICKS_IN_BASE / 2) * brick_height )) - ((n + 1) * brick_height)); //start at the 1/2 and move down half max stack height and move up a brick each round.
GRect brick = new GRect(x, y, brick_width, brick_height);
brick.setFilled(true);
brick.setFillColor(Color.RED);
add(brick);
if(bricks_in_level > 1){ //If there are 2 or more bricks needed in this level
for(int needed_bricks = bricks_in_level - 1; needed_bricks > 0; needed_bricks -= 1){
x += brick_width;
GRect needed_brick = new GRect(x, y, brick_width, brick_height);
needed_brick.setFilled(true);
needed_brick.setFillColor(Color.RED);
add(needed_brick);
}
}
}
}
private static final int BRICKS_IN_BASE = 12;
}
The main problem was that I was using open-java-jdk and not sun-java-jdk. After changing the jre my Applet is behaving in a more predictable way.

Categories

Resources