import java.util.Random;
import java.awt.Color;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
/**
* In the application Puzzler, a Cell is a specialized type of
* JButton that represents a ball in the game. Upon a first click, if
* there are adjacent cells of the same type, this cell and the adjacent cells
* of the same type are selected. Upon a second click, this cell and the
* adjacent cells of the same type are removed from the Board. This
* causes other cells to fall down, and right.
*
* @author Marcel Turcotte, University of Ottawa
*/
public class Cell extends JButton {
private static final long serialVersionUID = 1L;
/**
* A random number generator is used to generate the cell type, when a new
* board is created, or the user clicks reset. The same number generator is
* shared by all the cells.
*/
private static Random generator = new Random();
/**
* Number of colours
*/
public static final int NUM_COLOURS = 5;
/**
* Symbolic constant that represents an empty cell
*/
public static final int EMPTY = 0;
/**
* The cell type. Valid values are Empty, Blue, Green, etc.
*/
private int type;
/**
* This instance variable is true if the cell is selected.
*/
private boolean selected = false;
/**
* The coordinate of this cell on the Board.
*/
private int row, column;
/**
* A an array is used to cache all the images. Since the images are not
* modified. All the cells that display the same image reuse the same
* ImageIcon object. Notice the use of the keyword static.
*/
private static final ImageIcon[] icons = new ImageIcon[NUM_COLOURS + 2];
/**
* Constructor used for initializing a cell of an unspecified type. The
* actual type is randomly generated. A randomly generated cell is never
* Empty.
*
* @param board
* the grid that holds all the cells
* @param row
* the row of this Cell
* @param column
* the column of this Cell
*/
public Cell(Board board, int row, int column) {
this(board, row, column, generator.nextInt(NUM_COLOURS) + 1);
}
/**
* Constructor used for initializing a cell of a specified type.
*
* @param board
* the grid that holds all the cells
* @param row
* the row of this Cell
* @param column
* the column of this Cell
* @param type
* specifies the type of this cell
*/
public Cell(Board board, int row, int column, int type) {
this.row = row;
this.column = column;
this.type = type;
setBackground(Color.WHITE);
setIcon(getImageIcon());
Border emptyBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0);
setBorder(emptyBorder);
setBorderPainted(false);
addActionListener(board);
}
/**
* A helper method that randomly generates a non-empty cell type.
*
* @return randomly generated non-empty cell type
*/
private int newRandomCellType() {
return generator.nextInt(NUM_COLOURS) + 1;
}
/**
* Determine the image to use based on the cell type. Uses
* getResource to locate the image file, either on the file system or
* the .jar file. Implements a caching mechanism.
*
* @return the image to be displayed by the button
*/
private ImageIcon getImageIcon() {
int id;
if (selected) {
id = NUM_COLOURS + 1;
} else {
id = type;
}
if (icons[id] == null) {
String strId = Integer.toString(id);
icons[id] = new ImageIcon(“data/ball-” + strId + “.png”);
}
return icons[id];
}
/**
* This method is called when the used clicks the reset button. A new cell
* type is generated. Its image is updated. The cell is unselected.
*/
public void reset() {
type = newRandomCellType();
setIcon(getImageIcon());
selected = false;
}
/**
* Returns the cell type of this cell.
*
* @return the type
*/
public int getType() {
return type;
}
/**
* Returns true if this and the other cell have the same type.
*
* @param other
* other cell used for the comparison
* @return true if both cells have the same type
*/
public boolean sameType(Cell other) {
return type == other.type;
}
/**
* Changes the cell type of this cell. The image is updated accordingly.
*
* @param type
* the type to set
*/
public void setType(int type) {
this.type = type;
setIcon(getImageIcon());
}
/**
* Returns true if this cell is empty, i.e. its type is
* CellType.Empty.
*
* @return true is this cell is empty
*/
public boolean isEmpty() {
return type == EMPTY;
}
/**
* Returns true is this cell is selected. Note: isSelected would have
* been a better name. However, this would overwrite the parent method
* isSelected.
*
* @return true is this cell is selected.
*/
public boolean selected() {
return selected;
}
/**
* Sets the value of the attribute selected.
*
* @param selected
* the new value for the attribute selected
*/
public void setSelected(boolean selected) {
this.selected = selected;
setIcon(getImageIcon());
}
/**
* Getter method for the attribute row.
*
* @return the value of the attribute row
*/
public int getRow() {
return row;
}
/**
* Getter method for the attribute column.
*
* @return the value of the attribute column
*/
public int getColumn() {
return column;
}
}