305 lines
8.2 KiB
Java
305 lines
8.2 KiB
Java
import javax.swing.*;
|
|
import java.awt.*;
|
|
import java.awt.geom.AffineTransform;
|
|
|
|
/**
|
|
* Chessboard class
|
|
*/
|
|
public class Chessboard extends JPanel {
|
|
|
|
/**
|
|
* Size of single square
|
|
*/
|
|
private final int SQUARE_SIZE = 100;
|
|
|
|
/**
|
|
* Count of squares on the board
|
|
*/
|
|
public final int SQUARE_COUNT = 8;
|
|
|
|
/**
|
|
* Width of the chessboard
|
|
*/
|
|
private final double BOARD_WIDTH = SQUARE_COUNT*SQUARE_SIZE;
|
|
|
|
/**
|
|
* Scale of the chessboard
|
|
*/
|
|
public double boardScale;
|
|
|
|
/**
|
|
* Scale of single piece
|
|
*/
|
|
public double pieceScale;
|
|
|
|
/**
|
|
* Top location of the board
|
|
*/
|
|
private double startX;
|
|
|
|
/**
|
|
* Left location of the board
|
|
*/
|
|
private double startY;
|
|
|
|
/**
|
|
* Instance of the floating piece
|
|
*/
|
|
private IPiece floating;
|
|
|
|
/**
|
|
* Two-dimensional array of pieces
|
|
*/
|
|
public IPiece[][] pieces = new IPiece[SQUARE_COUNT][SQUARE_COUNT];
|
|
|
|
private boolean[][] possibleMoves;
|
|
|
|
private boolean[][] lastMove;
|
|
|
|
private Player player1;
|
|
|
|
private Player player2;
|
|
|
|
private Player activePlayer;
|
|
|
|
/**
|
|
* Constructor of the chessboard
|
|
*/
|
|
public Chessboard() {
|
|
|
|
ChessboardMouseAdapter ma = new ChessboardMouseAdapter();
|
|
addMouseListener(ma);
|
|
addMouseMotionListener(ma);
|
|
|
|
}
|
|
|
|
/**
|
|
* Add passed piece to the specified coordinates
|
|
* @param piece piece
|
|
* @param x piece's X location
|
|
* @param y piese's Y location
|
|
*/
|
|
public void addPiece(IPiece piece, int x, int y) {
|
|
if(!isOnBoard(x, y)) return;
|
|
pieces[y][x] = piece;
|
|
}
|
|
|
|
/**
|
|
* Remove piece at specified coordinates
|
|
* @param x piece's X location
|
|
* @param y piece's Y location
|
|
* @return removed piece
|
|
*/
|
|
public IPiece removePiece(int x, int y) {
|
|
if(!isOnBoard(x, y)) return null;
|
|
IPiece piece = pieces[y][x];
|
|
pieces[y][x] = null;
|
|
return piece;
|
|
}
|
|
|
|
/**
|
|
* Paint the chessboard
|
|
* @param g the <code>Graphics</code> context in which to paint
|
|
*/
|
|
public void paint(Graphics g) {
|
|
|
|
Graphics2D g2 = getGraphics2D(g);
|
|
|
|
double cx = this.getWidth() / 2.0;
|
|
double cy = this.getHeight() / 2.0;
|
|
|
|
boardScale = Math.min(this.getWidth(), this.getHeight())/ BOARD_WIDTH;
|
|
|
|
startX = cx-(BOARD_WIDTH /2.0*boardScale);
|
|
startY = cy-(BOARD_WIDTH /2.0*boardScale);
|
|
|
|
AffineTransform beforeBoard = g2.getTransform();
|
|
g2.translate(startX, startY);
|
|
g2.scale(boardScale, boardScale);
|
|
|
|
boolean isBlack = true;
|
|
|
|
AffineTransform beforeSquares = g2.getTransform();
|
|
|
|
for(int i=0; i<SQUARE_COUNT; i++) {
|
|
if(SQUARE_COUNT % 2 == 0) isBlack = !isBlack;
|
|
for(int j=0; j<SQUARE_COUNT; j++) {
|
|
g2.setTransform(beforeSquares);
|
|
if(isBlack) g2.setColor(Color.LIGHT_GRAY);
|
|
else g2.setColor(Color.WHITE);
|
|
isBlack = !isBlack;
|
|
g2.translate(i*SQUARE_SIZE, j*SQUARE_SIZE);
|
|
g2.fillRect(0, 0, SQUARE_SIZE, SQUARE_SIZE);
|
|
}
|
|
}
|
|
|
|
g2.setStroke(new BasicStroke(10));
|
|
for(int i=0; i<SQUARE_COUNT; i++) {
|
|
for(int j=0; j<SQUARE_COUNT; j++) {
|
|
if(lastMove != null && lastMove[j][i]) {
|
|
g2.setTransform(beforeSquares);
|
|
g2.translate(i*SQUARE_SIZE, j*SQUARE_SIZE);
|
|
g2.setColor(new Color(50, 50, 250, 25));
|
|
g2.fillRect(0, 0, SQUARE_SIZE, SQUARE_SIZE);
|
|
}
|
|
if(possibleMoves != null && possibleMoves[j][i]) {
|
|
g2.setTransform(beforeSquares);
|
|
g2.translate(i*SQUARE_SIZE, j*SQUARE_SIZE);
|
|
g2.setColor(new Color(255, 0, 0, 25));
|
|
g2.fillRect(0, 0, SQUARE_SIZE, SQUARE_SIZE);
|
|
g2.setColor(new Color(255, 50, 50));
|
|
g2.drawRect(0, 0, SQUARE_SIZE, SQUARE_SIZE);
|
|
}
|
|
}
|
|
}
|
|
|
|
g2.setTransform(beforeSquares);
|
|
|
|
AffineTransform beforePieces = g2.getTransform();
|
|
pieceScale = SQUARE_SIZE / 140.0;
|
|
|
|
for (IPiece[] pieces2: pieces) {
|
|
for (IPiece piece : pieces2) {
|
|
if(piece != null && piece != floating) {
|
|
double xOffset = 20*pieceScale + SQUARE_SIZE*piece.getX();
|
|
double yOffset = 20*pieceScale + SQUARE_SIZE*piece.getY();
|
|
g2.translate(xOffset, yOffset);
|
|
g2.scale(pieceScale, pieceScale);
|
|
piece.paint(g2);
|
|
g2.setTransform(beforePieces);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(floating != null) {
|
|
g2.setTransform(beforeBoard);
|
|
g2.translate(floating.getOverrideX(), floating.getOverrideY());
|
|
g2.scale(pieceScale * boardScale, pieceScale * boardScale);
|
|
floating.paint(g2);
|
|
}
|
|
|
|
g2.setTransform(beforeBoard);
|
|
|
|
}
|
|
|
|
/**
|
|
* Setup Graphics2D with anti-aliasing
|
|
* @param g Graphics instance
|
|
* @return Graphics2D instance
|
|
*/
|
|
public Graphics2D getGraphics2D(Graphics g) {
|
|
|
|
Graphics2D g2 = (Graphics2D) g;
|
|
RenderingHints rh = new RenderingHints(RenderingHints.KEY_RENDERING,
|
|
RenderingHints.VALUE_RENDER_QUALITY);
|
|
rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
g2.setRenderingHints(rh);
|
|
return g2;
|
|
|
|
}
|
|
|
|
/**
|
|
* Get coordinates of piece from mouse X and Y location
|
|
* @param x mouse X location
|
|
* @param y mouse Y location
|
|
* @return piece position
|
|
*/
|
|
public PiecePosition getPieceCoordinates(int x, int y) {
|
|
int pieceX = (int) ((x-startX)/(SQUARE_SIZE*boardScale));
|
|
int pieceY = (int) ((y-startY)/(SQUARE_SIZE*boardScale));
|
|
return new PiecePosition(
|
|
Math.min(Math.max(pieceX, 0), SQUARE_COUNT-1),
|
|
Math.min(Math.max(pieceY, 0), SQUARE_COUNT-1)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get piece on specified piece position
|
|
* @param pos piece position
|
|
* @return piece
|
|
*/
|
|
public IPiece getPiece(PiecePosition pos) {
|
|
if(!isOnBoard(pos.x, pos.y)) return null;
|
|
return pieces[pos.y][pos.x];
|
|
}
|
|
|
|
/**
|
|
* Grab piece at specified position and mark it as floating
|
|
* @param pos piece position
|
|
* @return piece
|
|
*/
|
|
public IPiece grabPiece(PiecePosition pos) {
|
|
if(!isOnBoard(pos.x, pos.y)) return null;
|
|
IPiece piece = getPiece(pos);
|
|
floating = piece;
|
|
this.repaint();
|
|
return piece;
|
|
}
|
|
|
|
/**
|
|
* Get current floating piece
|
|
* @return floating piece
|
|
*/
|
|
public IPiece getFloatingPiece() {
|
|
return floating;
|
|
}
|
|
|
|
/**
|
|
* Return piece at specified position to the board and unmark it from floating
|
|
* @param pos piece position
|
|
*/
|
|
public void returnPiece(PiecePosition pos) {
|
|
if(floating != null) {
|
|
if(pos != null) floating.setPosition(pos);
|
|
floating.setOverride(0, 0);
|
|
}
|
|
floating = null;
|
|
this.repaint();
|
|
}
|
|
|
|
public boolean isEndangered(PieceColor color, int x, int y) {
|
|
for (IPiece[] pieces : pieces) {
|
|
for (IPiece piece : pieces) {
|
|
if(piece != null && piece.getColor() != color) {
|
|
if(piece.getPossibleMoves()[y][x] == true) return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void showPossibleMoves(boolean[][] moves) {
|
|
possibleMoves = moves;
|
|
}
|
|
|
|
public void showLastMove(boolean[][] move) {
|
|
lastMove = move;
|
|
}
|
|
|
|
public boolean isOnBoard(int x, int y) {
|
|
return !(y < 0 || y >= SQUARE_COUNT || x < 0 || x >= SQUARE_COUNT);
|
|
}
|
|
|
|
public void setPlayer1(Player player) {
|
|
player1 = player;
|
|
activePlayer = player;
|
|
}
|
|
|
|
public void setPlayer2(Player player) {
|
|
player2 = player;
|
|
}
|
|
|
|
public Player getActivePlayer() {
|
|
return activePlayer;
|
|
}
|
|
|
|
public void changeActivePlayer() {
|
|
if(activePlayer == player1) {
|
|
activePlayer = player2;
|
|
} else {
|
|
activePlayer = player1;
|
|
}
|
|
}
|
|
|
|
}
|