/****************
* Name: Koh Wei Jie
*
* Purpose of this file: To work as the chessboard for the game.
* Uses graphics for the board and pieces, as well as drag-and-
* drop event handling.
*
****************/
import java.util.*;
import java.awt.event.*;
import java.lang.Math.*;
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
import game.*;
public class Chessboard extends JComponent implements MouseMotionListener, MouseListener{
private ImageIcon boardbg;
private ImageIcon redSq;
private ImageIcon greenSq;
private Dimension totalSize = new Dimension(402, 402);
private final int sqLen = 50;
private String imgDir = "images/";
private String boardImgDir = imgDir + "board/";
private String bPiecesImgDir = imgDir + "b_pieces/";
private String wPiecesImgDir = imgDir + "w_pieces/";
private Board board;
private Piece beingDragged = null;
private int beingDraggedX = -1;
private int beingDraggedY = -1;
private int originalX = -1;
private int originalY = -1;
private boolean isWhite;
private boolean myTurn;
private ChessController cc;
private Vector<int[]> greenSqLocations = new Vector<int[]>();
public Chessboard(boolean isWhite, ChessController cc){
this.isWhite = isWhite;
this.myTurn = isWhite;
this.cc = cc;
this.boardbg = new ImageIcon(this.boardImgDir + "board.png");
this.greenSq = new ImageIcon(this.boardImgDir + "green_square.png");
this.redSq = new ImageIcon(this.boardImgDir + "red_square.png");
this.board = new Board(isWhite);
this.addMouseMotionListener(this);
this.addMouseListener(this);
}
//make this component of a fixed size
public Dimension getMinimumSize(){ return this.totalSize; }
public Dimension getMaximumSize(){ return this.totalSize; }
public Dimension getPreferredSize() { return this.totalSize; }
public void mouseMoved(MouseEvent e){ }
public void mouseEntered(MouseEvent e){ }
public void mouseExited(MouseEvent e){ }
public void mouseClicked(MouseEvent e){ }
public Vector<int[]> calcRedSqLocations(){
Vector<int[]> canCapture = new Vector<int[]>();
for (int[] p : this.greenSqLocations){
if (p != null){
if (this.board.isOccupied(p[0], p[1]) || this.board.isEnPassantLoc(p[0], p[1])){
canCapture.add(p);
}
}
}
return canCapture;
}
public void movePiece(int fromX, int fromY, int toX, int toY){
//called when the opponent moves a piece
this.board.movePiece(fromX, fromY, toX, toY);
this.repaint();
this.myTurn = true;
}
public void clearBeingMoved(){
this.beingDragged = null;
this.beingDraggedX = -1;
this.beingDraggedY = -1;
this.greenSqLocations.clear();
this.repaint();
}
//Drag and drop
public void mousePressed(MouseEvent e){
if (!myTurn){
return;
}
Point mouseLoc = e.getPoint();
int xLoc = (int)(Math.floor(mouseLoc.getX() / this.sqLen));
int yLoc = (int)(Math.floor(mouseLoc.getY() / this.sqLen));
if (this.board.getPieces()[yLoc][xLoc] != null){
this.beingDraggedX = xLoc;
this.beingDraggedY = yLoc;
this.originalX = xLoc;
this.originalY = yLoc;
this.beingDragged = this.board.getPieces()[yLoc][xLoc];
if (this.beingDragged.getIsWhite() == this.isWhite){
this.greenSqLocations = this.beingDragged.possiblePositions(this.board, xLoc, yLoc);
}
if (this.greenSqLocations.isEmpty()){
clearBeingMoved();
}
}
}
public void mouseDragged(MouseEvent e){
this.repaint();
if ((!myTurn) || (this.greenSqLocations.size() == 0) || (this.beingDragged.getIsWhite() != this.isWhite)){
return;
}
Point mouseLoc = e.getPoint();
this.beingDraggedX = (int)(Math.floor(mouseLoc.getX() / this.sqLen));
this.beingDraggedY = (int)(Math.floor(mouseLoc.getY() / this.sqLen));
}
public void mouseReleased(MouseEvent e){
this.repaint();
if (!myTurn || (this.greenSqLocations.size() == 0) || (this.beingDragged.getIsWhite() != this.isWhite)){
clearBeingMoved();
return;
}
Point mouseLoc = e.getPoint();
int xLoc = (int)(Math.floor(mouseLoc.getX() / this.sqLen));
int yLoc = (int)(Math.floor(mouseLoc.getY() / this.sqLen));
if (!(xLoc > 7 || yLoc > 7 || xLoc < 0 || yLoc < 0)){
if (!(xLoc == originalX && yLoc == originalY)){
for (int[] sq : this.greenSqLocations){
if (sq[0] == xLoc && sq[1] == yLoc){
this.board.movePiece(originalX, originalY, xLoc, yLoc);
this.cc.movePiece(originalX, originalY, xLoc, yLoc);
this.myTurn = false;
clearBeingMoved();
this.repaint();
break;
}
this.beingDraggedX = this.originalX;
this.beingDraggedY = this.originalY;
}
this.greenSqLocations.clear();
}
else{
clearBeingMoved();
}
}
else{
clearBeingMoved();
this.repaint();
}
this.greenSqLocations.clear();
this.repaint();
if (this.board.isCheckMate(!this.isWhite)){
this.cc.checkmateOpp();
}
else if (this.board.isStalemate(!this.isWhite)){
this.cc.stalemateOpp();
}
else if (this.board.isCheck(!this.isWhite)){
this.cc.checkOpp();
}
else if (this.board.canPromote(this.isWhite)){
String pieces[] = {"Queen", "Rook", "Bishop", "Knight"};
int promoteTo = JOptionPane.showOptionDialog(null,
"Please select a piece to this pawn to.",
"Promotion",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
pieces,
pieces[0]);
int xPos = board.promote(promoteTo, isWhite);
this.cc.promote(promoteTo, xPos);
this.repaint();
}
this.repaint();
}
public void promoteOpp(int promoteTo, int xPos){
switch (promoteTo){
case 0:
this.board.getPieces()[7][xPos] = new Queen(!isWhite);
break;
case 1:
this.board.getPieces()[7][xPos] = new Rook(!isWhite);
break;
case 2:
this.board.getPieces()[7][xPos] = new Bishop(!isWhite);
break;
case 3:
this.board.getPieces()[7][xPos] = new Knight(!isWhite);
break;
}
}
protected ImageIcon makePiece(boolean white, String type){
String colour;
String dir;
if (white){
colour = "w";
dir = this.wPiecesImgDir;
}
else{
colour = "b";
dir = this.bPiecesImgDir;
}
return new ImageIcon(dir + colour + "_" + type + ".png");
}
public String genFilename(Piece p){
String name = "";
if (p.getIsWhite()){
name += wPiecesImgDir + "w";
}
else{
name += bPiecesImgDir + "b";
}
name += "_";
name += p.getName() + ".png";
return name;
}
public void paint(Graphics g){
super.paint(g);
//background image of the checkered board
g.drawImage(this.boardbg.getImage(), 0, 0, 402, 402, this);
//green squares
if (this.greenSqLocations != null){
for (int[] i : greenSqLocations){
g.drawImage(this.greenSq.getImage(),
i[0] * this.sqLen + 1,
i[1] * this.sqLen + 1,
this.sqLen,
this.sqLen,
this);
}
for (int[] i : calcRedSqLocations()){
if (i != null){
g.drawImage(this.redSq.getImage(),
i[0] * this.sqLen + 1,
i[1] * this.sqLen + 1,
this.sqLen,
this.sqLen,
this);
}
}
}
//individual pieces
for (int i = 0; i < this.board.getPieces().length; i++){
for (int j = 0; j < this.board.getPieces()[i].length; j++){
if (this.board.getPieces()[i][j] != null){
//for each piece
Piece piece = this.board.getPieces()[i][j];
ImageIcon icon = new ImageIcon(genFilename(piece));
if (!piece.equals(this.beingDragged)){
g.drawImage(icon.getImage(), j * this.sqLen, i * this.sqLen, this.sqLen, this.sqLen, this);
}
}
}
}
//the piece being dragged
if (this.beingDragged != null){
ImageIcon icon = new ImageIcon(genFilename(this.beingDragged));
g.drawImage(icon.getImage(), this.beingDraggedX * this.sqLen, this.beingDraggedY * this.sqLen, this.sqLen, this.sqLen, this);
}
}
}