Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Storing rectangle/parameters in an Array

Status
Not open for further replies.

atsea

Technical User
Feb 27, 2005
51
JP
I'm currently trying to develop a GUI for a "Tower of Hanoi" game. (The "towers" game should be familiar to many out there as a lesson in recursion. I however am using this example to practice developing GUI's and Graphics)

Not sure if my train of thought is on the right track so I'll write a little description of what I am trying to do, followed by my code.

Basically I have a game board divded into 3 cells.
- each cell can hold MAX of 10 disks.
- Class "Disk" handles each instance of a disk.
- Class "GameSheet" has a method "addDisk" that creates a specified number of disks and adds them to an array.

Ideally what I am trying to accomplish (but not sure if it is possible this way), is have each disk and it properties stored in an array...somehow like this:
disks[0] = fillRoundRect(5,5,10,10,15,15);
disks[1] = fillRoundRect(7,7,14,14,15,15);
disks[2] = fillRoundRect(9,9,18,18,15,15);
disks[3] = fillRoundRect(11,11,22,22,15,15);
disks[4] = fillRoundRect(13,13,26,26,15,15);
disks[n] = fillRoundRect(n,n,n,n,n,n);
(the value of the parameters here are irrelavant, just note that they are all different)

So whenever i want a disk that is "fillRoundRect(9,9,18,18,15,15);" all I have to do is (somehow) draw disks[2].

Is this possible? Is there a better way to do this?

I am trying to figure out the best way to write a "moveDisk" method, that will get a starting row, and a destination row. Then draw the selected "disk" in the destiniation row, while deleting the original in the starting row.(using click events)

Below is what I have so far:

Code:
public class Disk {
    
    //private int row;
    //private int column;
    private int startX;
    private int startY;
    private int diskWidth;
    private int diskHeight;
    private int arcWidth;
    private int arcHeight;
    
    /** Creates a new instance of Disk */
    public Disk(Graphics gfx, int x, int y, int width, int height, int arcW, int arcH) {
        
        this.arcHeight = arcH;
        this.arcWidth = arcW;
        this.diskHeight = height;
        this.diskWidth = width;
        this.startX = x;
        this.startY = y;
        
        gfx.fillRoundRect(startX, startY, diskWidth, diskHeight, arcW, arcH);
        
    }

}

Code:
public class GameSheet {
    
    private static final int GAME_LINE_HEIGHT = 300;
    private static final int GAME_POLE_HEIGHT = 240;
    private static final int GAME_POLE_WIDTH = 10;
    private static final int MAX_DISK = 10;
    private static final int ROW_COUNT = 12;
    private static final int COL_COUNT = 3;
    public static final int GAME_CELL_WIDTH = 200;
    public static final int GAME_AREA_START_X = 5;
    public static final int GAME_AREA_START_Y = 5;
    public static final int DISK_HEIGHT = 25;
    
    private int firstClickRow;
    private int firstClickCol;
    
    private int[][] gameCells;
    private Disk[]  disks;
    
    
    /** Creates a new instance of GameSheet */
    public GameSheet() {
        this.gameCells = new int[ROW_COUNT][COL_COUNT];
        
        //later MAX_DISK will be user defined
        this.disks = new Disk[MAX_DISK];
        
        //fill each cell with -1 so that it can detemine wether to draw or not
        //-1 means the cell is empty...maybe put in a "final" variable later
        //THIS MAY NOT BE NECESSARY
        int i = 0;
        while (i < ROW_COUNT){
            int j = 0;
            while (j < COL_COUNT){
                gameCells[i][j] = -1;
                j++;
            }
            i++;
        }
        
        //initialize the first click row and column
        this.firstClickRow = -1;
        this.firstClickCol = -1;
    }
    
    /**
     *set the column and row of the FIRST click that is
     *inside the playing area
     *@param row the row that was clicked
     *@param col the column that was clicked
     */
    public void setFirstRowColumn(int row, int col) {
        if ((row >= 0) &&
                (row < 12) &&
                (col >= 0) &&
                (col < COL_COUNT)) {
            
        }else{
            this.firstClickRow = -1;
            this.firstClickCol = -1;
        }
    }
    
    /**
     *set the column and row of the SECOND click that is
     *inside the playing area
     *@param row the row that was clicked
     *@param col the column that was clicked
     */
    public void setSecondRowColumn(int row, int col) {
        if ((row >= 0) &&
                (row < 12) &&
                (col >= 0) &&
                (col < COL_COUNT)) {
            
            //this will draw a disk in the location of the second click
            this.firstClickRow = row;
            this.firstClickCol = col;
            
        }
    }
    
    /**
     *Draw the game space in the main window
     *1 row 3 col grid and 3 poles
     *@param gfx Graphics
     */
    public void drawGameSpace(Graphics gfx){
        
        //draws the vertical lines
        //set initial loop conditions
        int lineCount = 0;
        int startX = GAME_AREA_START_X;
        int startY = GAME_AREA_START_Y;
        
        //a loop to draw the 4 vertical lines
        while (lineCount < 4){
            //draw the line
            gfx.drawLine(startX, startY, startX, startY + GAME_LINE_HEIGHT);
            //move over cell width pixles
            startX += GAME_CELL_WIDTH;
            //increment lineCount
            lineCount++;
        }
        
        //re initialize the start point for the horizontal lines
        startX = GAME_AREA_START_X;
        startY = GAME_AREA_START_Y;
        //draw the top and bottom lines
        gfx.drawLine(startX, startY, startX + GAME_CELL_WIDTH * 3, startY);
        gfx.drawLine(startX, startY + GAME_LINE_HEIGHT, startX + GAME_CELL_WIDTH * 3, startY + GAME_LINE_HEIGHT);
        
        //draw the poles in the middle of each "cell"
        gfx.setColor(Color.gray);
        gfx.fillRoundRect(102, startY + GAME_LINE_HEIGHT - GAME_POLE_HEIGHT, GAME_POLE_WIDTH, GAME_POLE_HEIGHT, 3, 3);
        gfx.fillRoundRect(302, startY + GAME_LINE_HEIGHT - GAME_POLE_HEIGHT, GAME_POLE_WIDTH, GAME_POLE_HEIGHT, 3, 3);
        gfx.fillRoundRect(502, startY + GAME_LINE_HEIGHT - GAME_POLE_HEIGHT, GAME_POLE_WIDTH, GAME_POLE_HEIGHT, 3, 3);
        
        // Disk dropper
        if ((this.firstClickRow != -1) &&
                (this.firstClickCol != -1)) {
            //this will eventually place the disk in the proper location
            //must put it in the next available row in the column

        }
        
    }
    
    
    /**
     *Create a specified number of disks. As the number of disks increases the size
     *of the disk descreases, giving a pyramid appearance.  Each disk is then placed in an array
     *so it may be used later.
     *@param numberOfDisks the number of disks to create
     *@param gfx graphics area associated with the disk
     *@param diskColor color of the disks
     *@param startX start x co ordinate of the disk/roundRect
     *@param startY start y co ordinate of the disk/roundRect
     */
    public void addDisk(int numberOfDisks, Graphics gfx, Color diskColor, int startX, int startY){
        
        //set the color of the Disks
        gfx.setColor(diskColor);
        
        int i = 0;
        int diskNumber = numberOfDisks;
        int startDiskSize = GAME_CELL_WIDTH - 8;
        
        // Calculate the starting position of the cell.
        int x = startX + 2; //2 pixles in
        
        //draw as many rectangles as requested
        while (i < diskNumber){
            int y = startY - i * DISK_HEIGHT;
            
            // Make a new disk
            Disk newDisk = new Disk(gfx, x, y + 2, startDiskSize, DISK_HEIGHT - 4, 15, 15);
            
            //add it to an array
            this.disks[i] = newDisk;
            
            startDiskSize = startDiskSize - 16;
            x = x + 8;
            i++;
        }
    }
    
}

Code:
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
import java.awt.*;

public class HanoiRedux extends JFrame implements MouseListener {
    
    private int gameState;
    
    private static final int GAME_HEIGHT = 500;
    private static final int GAME_WIDTH = 800;
    private static final int TITLE_X = 350;
    private static final int TITLE_Y = 200;
    private static final int TITLE_MSG_X = 326;
    private static final int TITLE_MSG_Y = 215;
    private static final int GAME_STATE_INTRO = 0;
    private static final int GAME_STATE_SETUP = 1;
    private static final int GAME_STATE_PLAYING = 2;
    private static final int GAME_STATE_OVER = 3;
    
    private boolean bFromClick;
    
    private GameSheet gameSheet;
    
    /** Creates a new instance of HanoiRedux */
    public HanoiRedux() {
        this.setSize(GAME_WIDTH, GAME_HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.addMouseListener(this);
        this.gameState = GAME_STATE_INTRO;
        this.setVisible(true);
        
        //initialize the game board
        this.gameSheet = new GameSheet();
    }
    
    public static void main(String[] args) {
        new HanoiRedux();
    }
    
    /**
     *Draw the title screen
     */
    private void drawTitleScreen(){
        //grab the area within the borders of the window
        Container clientArea = this.getContentPane();
        
        //get the graphics associated with the clientArea
        Graphics gfx = clientArea.getGraphics();
        
        //get the dimensions of the client area
        int width = clientArea.getWidth();
        int height = clientArea.getHeight();
        
        //set the contents of the clientArea to black
        gfx.fillRect(0, 0, width, height);
        //write the Title in Red
        gfx.setColor(Color.red);
        gfx.drawString("Towers Of Hanoi", TITLE_X, TITLE_Y );
        //write a short title messgae
        gfx.setColor(Color.gray);
        gfx.drawString("(click screen to continue)", TITLE_MSG_X, TITLE_MSG_Y);
        
        
    }
    
    /**
     *Draws the space the where the game is actually played
     */
    private void drawGameSpace(){
        //grab the area within the borders of the window
        Container clientArea = this.getContentPane();
        
        //get the graphics associated with the clientArea
        Graphics gfx = clientArea.getGraphics();
        
        //get the dimensions of the client area
        int width = clientArea.getWidth();
        int height = clientArea.getHeight();
        
        //set the contents of the clientArea to black
        gfx.fillRect(0, 0, width, height);
        
        //code to draw the lines of the board
        //set the color of the lines
        gfx.setColor(Color.red);
        
        //use the class GameSheet
        this.gameSheet.drawGameSpace(gfx);
        //this.gameSheet.drawDisks(4, gfx, Color.ORANGE, 7, 275);
        this.gameSheet.addDisk(7, gfx, Color.ORANGE, 7, 280);
        //this.gameSheet.addDiskTest(7, gfx, Color.ORANGE, 7, 275);
        //this.gameSheet.addDiskTest(gfx, 7, 275);
    }
    
    /**
     *Paint on the game sheet
     *Overides the previous paint method
     */
    public void paint(Graphics gfx){
        //decide exactly what to paint using an if statement
        if (this.gameState == GAME_STATE_INTRO){
            this.drawTitleScreen();
        } else if(this.gameState == GAME_STATE_SETUP){
            this.drawGameSpace();
        }
    }
    
    public void mouseClicked(MouseEvent e) {
    }
    
    public void mousePressed(MouseEvent e) {
    }
    
    public void mouseReleased(MouseEvent e) {
        if (this.gameState == GAME_STATE_INTRO){
            this.gameState = GAME_STATE_SETUP;
            this.repaint();
            this.initializeFromClick();
        }else if (this.gameState == GAME_STATE_SETUP){
            if (this.bFromClick){
                //record the mouse row and column
                int row = this.convertYtoRow(e.getY());
                int col = this.convertXtoCol(e.getX());
                gameSheet.setFirstRowColumn(row, col);
                this.bFromClick = false;
                
                this.repaint();
            }else{
                int row = this.convertYtoRow(e.getY());
                int col = this.convertXtoCol(e.getX());
                gameSheet.setSecondRowColumn(row, col);
                this.repaint();
                this.bFromClick = true;
            }
            
        }else if (this.gameState == GAME_STATE_PLAYING){
            this.repaint();
        }
    }
    
    /**
     *Initializes the position of the first click
     *i.e. the "from" col
     */
    private void initializeFromClick(){
        this.bFromClick = true;
    }
    
    public void mouseEntered(MouseEvent e) {
    }
    
    public void mouseExited(MouseEvent e) {
    }
    
    private int convertXtoCol(int x) {
        Container clientArea = this.getContentPane();
        int borderSize = (this.getWidth() - clientArea.getWidth());
        int col = (x - borderSize - GameSheet.GAME_AREA_START_X) / GameSheet.GAME_CELL_WIDTH;
        return col;
    }
    
    private int convertYtoRow(int y){
        Container clientArea = this.getContentPane();
        int borderSize = (this.getWidth() - clientArea.getWidth());
        int titleSize = (this.getHeight() - clientArea.getHeight()) - borderSize;
        int row = (y - titleSize - GameSheet.GAME_AREA_START_Y) / GameSheet.DISK_HEIGHT;
        return row;
    }
}

Any help/suggestions would be greatly appreciated.

atsea
 
Have your logic and data structure creation separate from your drawing routines. Basically, your constructor for the disk class needs to be split into two routines: the constructor that sets the class variables and the drawing routine. You should also add a moveDisk(x, y) routine, which will set or calculate startX, startY, and invalidate the screen. Since the radius of the disk (your width parameter) will vary, you might want to make x the center of the disk, not the left edge, which can be quickly calculated as x - width/2.

Create one disk for each disk in the game. I think you do this, but I didn't see it on a quick read.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top