About the BoardGame package

Copyright © 2012 by David Matuszek

The BoardGame package is a simple graphical API for board games, and for simulations that resemble board games.

A Board is a rectangular grid of "squares," and a Piece is a object that can be placed on one of those squares. For example, a chess game could be represented with an 8 by 8 board containing several different kinds of pieces (pawns, bishops, etc.).

This API supports most common operations. Pieces can be placed on the board, moved about (by program or by dragging with the mouse), and taken off the board. It is possible to define where a piece may or may not move. Pieces can be stacked atop one another on the same square. Multiple game boards are supported.

The GameBoard API maintains information about where game pieces are located on boards; in most cases, this information should not be duplicated in programs that use this API.

See the GameBoard API for more complete information.

How to get started

Begin by creating a Board, as follows:

Board myBoard = new Board(numberOfRows, numberOfColumns);

Once you have created a board, you will of course want to display it. The board is drawn in a Swing JPanel, but you have to get this JPanel and put it into your own GUI. After creating the board, you need to do the following:

JPanel myDisplayPanel = myBoard.getJPanel();

It is up to you to put this JPanel into your GUI. Typically, the CENTER portion of a BoardLayout works well. Once you are displaying this component, the display will be updated automatically as you do things with pieces on the board.

Next, create some Pieces. Piece is actually an abstract class--you need to extend it and provide your own method for drawing pieces--but to get you started, one concrete implementation, RoundPiece, is provided for you. Round pieces are pretty boring, but at least you can create them in a variety of colors. For instance,

Piece myPiece = new RoundPiece(Color.RED);
Piece yourPiece = new RoundPiece(Color.BLUE);

Sometimes you will want several pieces of the same kind:

Piece[ ] myCheckers = new Piece[12];
for (int i = 0; i < 12; i++) {
    myCheckers[i] = new RoundPiece(Color.BLACK);
}

Once you have some pieces, you can place them on the board. There are two equivalent ways of doing this:

myBoard.place(myPiece, row, column);

and

myPiece.place(myBoard, row, column);

You can use whichever of these seems more natural or more convenient.

Rows and columns use array numbering; that is, row 0 is at the top and column 0 is at the left. Moving "up" a row means reducing the row number by one, and moving right a column means increasing the column number by one.

The program can move a piece from one square to another in two different ways: by moving it to an "absolute" position, given by row and column numbers; or by moving it relative to its starting position, given by the amounts to change the row and column numbers.

myPiece.moveTo(row, column); // absolute move
myPiece.move(rowIncrement, columnIncrement); // relative move

The user can also move pieces, by clicking on them with the mouse and dragging them to their new location.

The Board and Piece classes have some similar methods. For example, pieces can be removed from the board in either of two ways:

myPiece.remove();
myBoard.remove(row, column);

The first of these removes the given piece. The second is a little more complicated; since a square on a board can hold multiple pieces, stacked one on top of the other, it will remove the "top" piece (the one most recently placed there).

A typical game has restrictions on what pieces can be moved, where they can be moved to, and who can move them. These details are explained in the sections that follow.


The Board class

Creating Boards

There is one constructor for Boards:

public Board(int rows, int columns)

Constructs a Board with rows 0 (top row) to rows-1 (bottom row) and columns 0 (leftmost column) to columns-1 (rightmost column).

Once you have constructed a Board, you will want to display it in the GUI for your program. Each Board is drawn on a JPanel, which you can get and put into your GUI, just like any other JPanel. Once you have done this, pieces put on the Board will be automatically displayed in their current positions.

public JPanel getDisplay()

Returns the JPanel on which this Board is displayed. Changes to the Board, such as the placement and movement of Pieces, will be automatically displayed.

Drawing Boards

By default, a board is painted with a white background and light blue lines between the squares (like graph paper). For a more interesting background, extend the Board class and override the following method:

public void paint(Graphics g)

Paints this board. Note that this method is not concerned with painting pieces on the board; that is done elsewhere.

The following methods are useful if you are overriding paint(Graphics) and drawing your own Board. There is very little reason to use them otherwise, but they are available if the other getter methods do not meet your needs. These methods always return the correct values for the current board size, even if the JPanel containing the board is resized by the user.

public int rowToY(int rowNumber)

Returns the y-coordinate at which to draw the line at the top of the given row number. In addition, rowToY(numberOfRows) will give the y-coordinate at which to draw the line beneath the bottom row of squares.

public int columnToX(int columnNumber)

Returns the x-coordinate at which to draw the line at the left of the given column number. In addition, columnToX(numberOfColumns) will give the x-coordinate at which to draw the line to the right of the rightmost column of squares.

public int yToRow(int y)

Returns the number of the row containing the given y-coordinate.

public int xToColumn(int x)

Returns the number of the column containing the given x-coordinate.

Manipulating Pieces on the Board

These are methods in the Board class; some of them have equivalent methods in the Piece class. Note that these methods will throw an ArrayIndexOutOfBoundsException if they are given illegal row and/or column numbers.

public void place(Piece piece, int row, int column)

Puts the given Piece on the Board at the given row and column. If that square on the Board already contains other pieces, this Piece will go on top of them.

public Piece getPiece(int row, int column)

Returns the Piece in the given row and column. If there are multiple pieces, the topmost one is returned; if there are no pieces, null is returned.

public Stack getPieces(int row, int column)

Returns a (possibly empty) java.util.Stack of all the pieces in the given position. The top element of the stack is the topmost element in that board location. (The Stack is a copy of the actual Board contents, so manipulating the Stack contents has no effect on the Board itself.)

public boolean isEmpty(int row, int column)

Returns true if this board location contains no pieces.

public boolean remove(Piece piece)

Removes the given Piece from this Board. Returns true if the remove succeeded, false if the given Piece was null or was not on this Board.

public Piece remove(int row, int column)

Removes the Piece at the given row and column on this Board, and returns it. If there are multiple pieces in that location, the topmost one is removed and returned; if there are no pieces, null is returned.

public void clear()

Removes all Pieces from this Board.

public void setSpeed(int speed)

When the program moves a Piece (by calling move or moveTo), it moves smoothly to the new position. This method defines the default speed of movement (in squares per second) for pieces that do not specify their own speed.

public int getSpeed()

Returns the default speed of movement for pieces on this board.

Getting information about Boards

public int getRows()

Returns the number of rows on this Board.

public int getColumns()

Returns the number of columns on this Board.

public boolean isLegalPosition(int row, int column)

Tests whether the given row and column are within the Board boundaries.


The Piece class

Piece is an abstract class; it must be extended by another class that implements a method to draw the piece. The method that must be supplied is:

public void paint(Graphics g, Rectangle r)

g is the java.awt.Graphics object on which to paint. Painting should be normally be limited to the particular "square" of the board containing this Piece, as given by the java.awt.Rectangle object r.

One concrete implementation of Piece is provided, RoundPiece, which draws an oval of a given color. A (slightly simplified) version of RoundPiece is provided here, largely as an example of how to implement Piece.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;


public class RoundPiece extends Piece {

    public Color color;
    
    /**
     * Constructs a RoundPiece of the given color.
     * 
     * @param color The Color of the new piece.
     **/
     RoundPiece(Color color) {
        this.color = color;
    }
    
    /**
     * Draws this RoundPiece on the given Graphics.
     * Drawing should be limited to the provided java.awt.Rectangle.
     * 
     * @param g The graphics on which to draw.
     * @param r The rectangle in which to draw.
     */
    public void paint(Graphics g, Rectangle r) {
        Color oldColor = g.getColor();
        g.setColor(color);
        g.fillOval(r.x, r.y, r.width, r.height);
        g.setColor(oldColor);
    }
}

Manipulating Pieces

Note that these methods will throw an ArrayIndexOutOfBoundsException if they are given illegal row and/or column numbers.

public void place(Board board, int row, int column)

Puts this Piece on the Board at the given row and column. If that square on the Board already contains other pieces, this Piece will go on top of them.

public boolean move(int deltaRow, int deltaColumn)

Moves this Piece deltaRow rows down (or up, if deltaRow is negative) and deltaColumn column to the right (or left, if deltaColumn is negative). If the new location contains other pieces, this Piece will go on top of them.

public boolean moveTo(int newRow, int newColumn)

Moves this Piece to the specified location on the Board. If that location already contains other pieces, this Piece will go on top of them.

public boolean canMove(int deltaRow, int deltaColumn)

Tests whether this Piece can be moved down and right by the given number of rows and columns. The provided method simply determines the new row and column numbers, then calls canMoveTo to perform the actual test.

public boolean canMoveTo(int newRow, int newColumn)

Tests whether this Piece can be moved to the given location. The method will return true for all legal board positions, but can be overridden to provide game-specific tests.

public void moveToTop()

Does not change the location of this Piece, but ensures that it is above any other pieces that may be in the same Board location.

public void remove()

Removes this piece from whatever board it may be on. The Piece is not destroyed, and may be placed elsewhere on this Board or another Board.

public void redraw()

This method is not necessary when using one of the above methods, as they all cause the visual display to be updated. However, there may be times when you want to change the appearance of the Piece without moving it (for example, to change its color, or make it face in another direction). This method forces this Piece to be redrawn.

Getting and setting information about a Piece

public Board getBoard()

Returns the Board containing this Piece, or null if this Piece is not currently on any Board.

public boolean isDraggable()

Returns true if the user can move this Piece by dragging it with the mouse.

public void setDraggable(boolean draggable)

Specifies whether the user is able to move this Piece by dragging it with the mouse. Note: Dragging a Piece while other Pieces are in motion may cause temporary drawing artifacts.

public void isSelectable()

Returns true if the user can select this Piece by clicking on it with the mouse.

public void setSelectable(boolean selectable)

Specifies whether the user can select this Piece by clicking on it with the mouse.