Commit 6426c894 authored by Erwan BOUSSE's avatar Erwan BOUSSE

Initial version

parent 2a966c9d
import java.util.List;
/**
* Represents a bishop piece.
*
*/
public class Bishop extends Piece {
public Bishop(int color, Square initSq, String img_file) {
super(color, initSq, img_file);
}
@Override
public List<Square> getLegalMoves(Board b) {
Square[][] board = b.getSquareArray();
int x = this.getPosition().getXNum();
int y = this.getPosition().getYNum();
return getDiagonalOccupations(board, x, y);
}
}
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
/**
* Represents a chess board.
*
*/
public class Board extends JPanel implements MouseListener, MouseMotionListener {
// Resource location constants for piece images
private String RESOURCES_WBISHOP_PNG = "resources/wbishop.png";
private String RESOURCES_BBISHOP_PNG = "resources/bbishop.png";
private String RESOURCES_WKNIGHT_PNG = "resources/wknight.png";
private String RESOURCES_BKNIGHT_PNG = "resources/bknight.png";
private String RESOURCES_WROOK_PNG = "resources/wrook.png";
private String RESOURCES_BROOK_PNG = "resources/brook.png";
private String RESOURCES_WKING_PNG = "resources/wking.png";
private String RESOURCES_BKING_PNG = "resources/bking.png";
private String RESOURCES_BQUEEN_PNG = "resources/bqueen.png";
private String RESOURCES_WQUEEN_PNG = "resources/wqueen.png";
private String RESOURCES_WPAWN_PNG = "resources/wpawn.png";
private String RESOURCES_BPAWN_PNG = "resources/bpawn.png";
// Logical and graphical representations of board
private final Square[][] board;
private final GameWindow g;
// List of pieces and whether they are movable
public final LinkedList<Piece> Bpieces;
public final LinkedList<Piece> Wpieces;
public List<Square> movable;
private boolean whiteTurn;
private Piece cp;
private int currX;
private int currY;
private CheckmateDetector cmd;
public Board(GameWindow g) {
this.g = g;
board = new Square[8][8];
Bpieces = new LinkedList<Piece>();
Wpieces = new LinkedList<Piece>();
setLayout(new GridLayout(8, 8, 0, 0));
this.addMouseListener(this);
this.addMouseMotionListener(this);
System.out.println("DEBUG: creating a board");
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
int xMod = x % 2;
int yMod = y % 2;
if ((xMod == 0 && yMod == 0) || (xMod == 1 && yMod == 1)) {
board[x][y] = new Square(this, 1, y, x);
this.add(board[x][y]);
} else {
board[x][y] = new Square(this, 0, y, x);
this.add(board[x][y]);
}
}
}
initializePieces();
this.setPreferredSize(new Dimension(400, 400));
this.setMaximumSize(new Dimension(400, 400));
this.setMinimumSize(this.getPreferredSize());
this.setSize(new Dimension(400, 400));
whiteTurn = true;
}
private void initializePieces() {
for (int x = 0; x < 8; x++) {
board[1][x].put(new Pawn(0, board[1][x], RESOURCES_BPAWN_PNG));
board[6][x].put(new Pawn(1, board[6][x], RESOURCES_WPAWN_PNG));
}
board[7][3].put(new Queen(1, board[7][3], RESOURCES_WQUEEN_PNG));
board[0][3].put(new Queen(0, board[0][3], RESOURCES_BQUEEN_PNG));
King bk = new King(0, board[0][4], RESOURCES_BKING_PNG);
King wk = new King(1, board[7][4], RESOURCES_WKING_PNG);
board[0][4].put(bk);
board[7][4].put(wk);
board[0][0].put(new Rook(0, board[0][0], RESOURCES_BROOK_PNG));
board[0][7].put(new Rook(0, board[0][7], RESOURCES_BROOK_PNG));
board[7][0].put(new Rook(1, board[7][0], RESOURCES_WROOK_PNG));
board[7][7].put(new Rook(1, board[7][7], RESOURCES_WROOK_PNG));
board[0][1].put(new Knight(0, board[0][1], RESOURCES_BKNIGHT_PNG));
board[0][6].put(new Knight(0, board[0][6], RESOURCES_BKNIGHT_PNG));
board[7][1].put(new Knight(1, board[7][1], RESOURCES_WKNIGHT_PNG));
board[7][6].put(new Knight(1, board[7][6], RESOURCES_WKNIGHT_PNG));
board[0][2].put(new Bishop(0, board[0][2], RESOURCES_BBISHOP_PNG));
board[0][5].put(new Bishop(0, board[0][5], RESOURCES_BBISHOP_PNG));
board[7][2].put(new Bishop(1, board[7][2], RESOURCES_WBISHOP_PNG));
board[7][5].put(new Bishop(1, board[7][5], RESOURCES_WBISHOP_PNG));
for(int y = 0; y < 2; y++) {
for (int x = 0; x < 8; x++) {
Bpieces.add(board[y][x].getOccupyingPiece());
Wpieces.add(board[7-y][x].getOccupyingPiece());
}
}
cmd = new CheckmateDetector(this, Wpieces, Bpieces, wk, bk);
}
public Square[][] getSquareArray() {
return this.board;
}
public boolean getTurn() {
return whiteTurn;
}
public void setCurrPiece(Piece p) {
this.cp = p;
}
public Piece getCurrPiece() {
return this.cp;
}
@Override
public void paintComponent(Graphics g) {
// super.paintComponent(g);
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
Square sq = board[y][x];
sq.paintComponent(g);
}
}
if (cp != null) {
if ((cp.getColor() == 1 && whiteTurn)
|| (cp.getColor() == 0 && !whiteTurn)) {
final Image i = cp.getImage();
g.drawImage(i, currX, currY, null);
}
}
}
@Override
public void mousePressed(MouseEvent e) {
currX = e.getX();
currY = e.getY();
Square sq = (Square) this.getComponentAt(new Point(e.getX(), e.getY()));
if (sq.isOccupied()) {
cp = sq.getOccupyingPiece();
if (cp.getColor() == 0 && whiteTurn)
return;
if (cp.getColor() == 1 && !whiteTurn)
return;
sq.setDisplay(false);
}
repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
Square sq = (Square) this.getComponentAt(new Point(e.getX(), e.getY()));
if (cp != null) {
if (cp.getColor() == 0 && whiteTurn)
return;
if (cp.getColor() == 1 && !whiteTurn)
return;
List<Square> legalMoves = cp.getLegalMoves(this);
movable = cmd.getAllowableSquares(whiteTurn);
if (legalMoves.contains(sq) && movable.contains(sq)
&& cmd.testMove(cp, sq)) {
sq.setDisplay(true);
cp.move(sq);
cmd.update();
if (cmd.blackCheckMated()) {
cp = null;
repaint();
this.removeMouseListener(this);
this.removeMouseMotionListener(this);
g.checkmateOccurred(0);
} else if (cmd.whiteCheckMated()) {
cp = null;
repaint();
this.removeMouseListener(this);
this.removeMouseMotionListener(this);
g.checkmateOccurred(1);
} else {
cp = null;
whiteTurn = !whiteTurn;
movable = cmd.getAllowableSquares(whiteTurn);
}
} else {
cp.getPosition().setDisplay(true);
cp = null;
}
}
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
currX = e.getX() - 24;
currY = e.getY() - 24;
repaint();
}
// Irrelevant methods, do nothing for these mouse behaviors
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
\ No newline at end of file
This diff is collapsed.
public class Clock {
private int hh;
private int mm;
private int ss;
/**
* Store and manipulate the time.
* @param hh Starting hours.
* @param mm Starting minutes.
* @param ss Starting seconds.
*/
public Clock(int hh, int mm, int ss) {
this.hh = hh;
this.mm = mm;
this.ss = ss;
}
/**
* Computes whether the time is over.
* @return true is the time is 00:00:00
*/
public boolean outOfTime() {
return (hh == 0 && mm == 0 && mm == 0);
}
/**
* Decrements the time by one second.
*/
public void decr() {
if (this.mm == 0 && this.ss == 0) {
this.ss = 59;
this.mm = 59;
this.hh--;
} else if (this.ss == 0) {
this.ss = 58;
this.mm--;
} else this.ss--;
}
public String getTime() {
String fHrs = String.format("%02d", this.hh);
String fMins = String.format("%02d", this.mm);
String fSecs = String.format("%02d", this.ss);
String fTime = fHrs + ":" + fMins + ":" + fSecs;
return fTime;
}
}
import javax.swing.*;
public class Game implements Runnable {
public void run() {
SwingUtilities.invokeLater(new StartMenu());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Game());
}
}
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.URL;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import javax.swing.*;
public class GameWindow {
private JFrame gameWindow;
public Clock blackClock;
public Clock whiteClock;
private Timer timer;
private Board board;
public GameWindow(String blackName, String whiteName, int hh,
int mm, int ss) {
blackClock = new Clock(hh, ss, mm);
whiteClock = new Clock(hh, ss, mm);
gameWindow = new JFrame("Chess");
try {
Image whiteImg = ImageIO.read(Paths.get("resources/wp.png").toUri().toURL());
gameWindow.setIconImage(whiteImg);
} catch (Exception e) {
System.out.println("File not found");
}
gameWindow.setLocation(100, 100);
gameWindow.setLayout(new BorderLayout(20,20));
// Game Data window
JPanel gameData = gameDataPanel(blackName, whiteName, hh, mm, ss);
gameData.setSize(gameData.getPreferredSize());
gameWindow.add(gameData, BorderLayout.NORTH);
this.board = new Board(this);
gameWindow.add(board, BorderLayout.CENTER);
gameWindow.add(buttons(), BorderLayout.SOUTH);
gameWindow.setMinimumSize(gameWindow.getPreferredSize());
gameWindow.setSize(gameWindow.getPreferredSize());
gameWindow.setResizable(false);
gameWindow.pack();
gameWindow.setVisible(true);
gameWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
// Helper function to create data panel
private JPanel gameDataPanel(final String bn, final String wn,
final int hh, final int mm, final int ss) {
JPanel gameData = new JPanel();
gameData.setLayout(new GridLayout(3,2,0,0));
// PLAYER NAMES
JLabel w = new JLabel(wn);
JLabel b = new JLabel(bn);
w.setHorizontalAlignment(JLabel.CENTER);
w.setVerticalAlignment(JLabel.CENTER);
b.setHorizontalAlignment(JLabel.CENTER);
b.setVerticalAlignment(JLabel.CENTER);
w.setSize(w.getMinimumSize());
b.setSize(b.getMinimumSize());
gameData.add(w);
gameData.add(b);
// CLOCKS
final JLabel bTime = new JLabel(blackClock.getTime());
final JLabel wTime = new JLabel(whiteClock.getTime());
bTime.setHorizontalAlignment(JLabel.CENTER);
bTime.setVerticalAlignment(JLabel.CENTER);
wTime.setHorizontalAlignment(JLabel.CENTER);
wTime.setVerticalAlignment(JLabel.CENTER);
if (!(hh == 0 && mm == 0 && ss == 0)) {
timer = new Timer(1000, null);
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean turn = board.getTurn();
if (turn) {
whiteClock.decr();
wTime.setText(whiteClock.getTime());
if (whiteClock.outOfTime()) {
timer.stop();
int n = JOptionPane.showConfirmDialog(
gameWindow,
bn + " wins by time! Play a new game? \n" +
"Choosing \"No\" quits the game.",
bn + " wins!",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
new GameWindow(bn, wn, hh, mm, ss);
gameWindow.dispose();
} else gameWindow.dispose();
}
} else {
blackClock.decr();
bTime.setText(blackClock.getTime());
if (blackClock.outOfTime()) {
timer.stop();
int n = JOptionPane.showConfirmDialog(
gameWindow,
wn + " wins by time! Play a new game? \n" +
"Choosing \"No\" quits the game.",
wn + " wins!",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
new GameWindow(bn, wn, hh, mm, ss);
gameWindow.dispose();
} else gameWindow.dispose();
}
}
}
});
timer.start();
} else {
wTime.setText("Untimed game");
bTime.setText("Untimed game");
}
gameData.add(wTime);
gameData.add(bTime);
gameData.setPreferredSize(gameData.getMinimumSize());
return gameData;
}
private JPanel buttons() {
JPanel buttons = new JPanel();
buttons.setLayout(new GridLayout(1, 3, 10, 0));
final JButton quit = new JButton("Quit");
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int n = JOptionPane.showConfirmDialog(
gameWindow,
"Are you sure you want to quit?",
"Confirm quit", JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
if (timer != null) timer.stop();
gameWindow.dispose();
}
}
});
final JButton nGame = new JButton("New game");
nGame.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int n = JOptionPane.showConfirmDialog(
gameWindow,
"Are you sure you want to begin a new game?",
"Confirm new game", JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
SwingUtilities.invokeLater(new StartMenu());
gameWindow.dispose();
}
}
});
final JButton instr = new JButton("How to play");
instr.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(gameWindow,
"Move the chess pieces on the board by clicking\n"
+ "and dragging. The game will watch out for illegal\n"
+ "moves. You can win either by your opponent running\n"
+ "out of time or by checkmating your opponent.\n"
+ "\nGood luck, hope you enjoy the game!",
"How to play",
JOptionPane.PLAIN_MESSAGE);
}
});
buttons.add(instr);
buttons.add(nGame);
buttons.add(quit);
buttons.setPreferredSize(buttons.getMinimumSize());
return buttons;
}
public void checkmateOccurred (int c) {
if (c == 0) {
if (timer != null) timer.stop();
int n = JOptionPane.showConfirmDialog(
gameWindow,
"White wins by checkmate! Set up a new game? \n" +
"Choosing \"No\" lets you look at the final situation.",
"White wins!",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
SwingUtilities.invokeLater(new StartMenu());
gameWindow.dispose();
}
} else {
if (timer != null) timer.stop();
int n = JOptionPane.showConfirmDialog(
gameWindow,
"Black wins by checkmate! Set up a new game? \n" +
"Choosing \"No\" lets you look at the final situation.",
"Black wins!",
JOptionPane.YES_NO_OPTION);
if (n == JOptionPane.YES_OPTION) {
SwingUtilities.invokeLater(new StartMenu());
gameWindow.dispose();
}
}
}
}
import java.util.LinkedList;
import java.util.List;
public class King extends Piece {
public King(int color, Square initSq, String img_file) {
super(color, initSq, img_file);
}
@Override
public List<Square> getLegalMoves(Board b) {
LinkedList<Square> legalMoves = new LinkedList<Square>();
Square[][] board = b.getSquareArray();
int x = this.getPosition().getXNum();
int y = this.getPosition().getYNum();
for (int i = 1; i > -2; i--) {
for (int k = 1; k > -2; k--) {
if(!(i == 0 && k == 0)) {
try {
if(!board[y + k][x + i].isOccupied() ||
board[y + k][x + i].getOccupyingPiece().getColor()
!= this.getColor()) {
legalMoves.add(board[y + k][x + i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
continue;
}
}
}
}
return legalMoves;
}
}