diff --git a/.idea/libraries/jfreechart_1_5_3.xml b/.idea/libraries/jfreechart_1_5_3.xml new file mode 100644 index 0000000..2b8d511 --- /dev/null +++ b/.idea/libraries/jfreechart_1_5_3.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Chess.iml b/Chess.iml index 4a41191..f1845b4 100644 --- a/Chess.iml +++ b/Chess.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/lib/jfreechart-1.5.3.jar b/lib/jfreechart-1.5.3.jar new file mode 100644 index 0000000..0f73437 Binary files /dev/null and b/lib/jfreechart-1.5.3.jar differ diff --git a/src/APiece.java b/src/APiece.java index 93a0666..85d6a65 100644 --- a/src/APiece.java +++ b/src/APiece.java @@ -325,8 +325,8 @@ public abstract class APiece { double startY = chessboard.startY + (fromY*chessboard.SQUARE_SIZE)*chessboard.boardScale; double endX = chessboard.startX + (toX*chessboard.SQUARE_SIZE)*chessboard.boardScale; double endY = chessboard.startY + (toY*chessboard.SQUARE_SIZE)*chessboard.boardScale; - double stepX = (endX-startX)/100; - double stepY = (endY-startY)/100; + double stepX = (endX-startX)/250; + double stepY = (endY-startY)/250; Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { int i = 1; @@ -334,7 +334,7 @@ public abstract class APiece { double currentY = 0; public void run() { chessboard.repaintRootPane(getRepaintRectangle()); - if(i > 100) { + if(i > 250) { timer.cancel(); setOverride(0, 0); } else { @@ -345,7 +345,7 @@ public abstract class APiece { chessboard.repaintRootPane(getRepaintRectangle()); i++; } - }, 5, 5); + }, 2, 2); } public void remove(boolean animate) { diff --git a/src/Chess.java b/src/Chess.java index 24e3a24..a02b606 100644 --- a/src/Chess.java +++ b/src/Chess.java @@ -1,3 +1,7 @@ +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.svg.SVGGraphics2D; import javax.imageio.ImageIO; @@ -7,6 +11,8 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * Main program layout @@ -68,7 +74,10 @@ public class Chess { JMenu menuGame = new JMenu("Game"); JMenuItem startNewGame = new JMenuItem("Start new game"); - startNewGame.addActionListener(l -> newGame(Chessboard.fromFEN(DEFAULT_FEN))); + startNewGame.addActionListener(l -> { + int response = JOptionPane.showConfirmDialog(chessboard, "Do you really want to start a new game?"); + if(response == 0) newGame(Chessboard.fromFEN(DEFAULT_FEN)); + }); menuGame.add(startNewGame); JMenuItem newGameFromFEN = new JMenuItem("Load from FEN"); @@ -81,6 +90,18 @@ public class Chess { }); menuGame.add(newGameFromFEN); + JMenuItem getFEN = new JMenuItem("Get current FEN"); + getFEN.addActionListener(l -> { + JOptionPane.showInputDialog("Here is current FEN: ", chessboard.toFEN()); + }); + menuGame.add(getFEN); + + JMenuItem showStats = new JMenuItem("Statistics"); + showStats.addActionListener(l -> { + showStatistics(); + }); + menuGame.add(showStats); + menuGame.add(new JPopupMenu.Separator()); JCheckBoxMenuItem toggleBlindMode = new JCheckBoxMenuItem("Blind mode"); @@ -273,4 +294,30 @@ public class Chess { } } + public static void showStatistics() { + JFrame window = new JFrame(); + window.setTitle("Statistics"); + + DefaultCategoryDataset dataset = new DefaultCategoryDataset(); + Player[] players = new Player[]{chessboard.getPlayer1(), chessboard.getPlayer2()}; + String[] playerNames = new String[]{"White", "Black"}; + for (int i = 0; i < players.length; i++) { + List delays = players[i].getDelays(); + for (int j = 0; j < delays.size(); j++) { + dataset.addValue(delays.get(j), playerNames[i], (j+1)+"."); + } + } + JFreeChart chart = ChartFactory.createLineChart( + "Turn speed", "Turns", "Time (ms)", + dataset + ); + + ChartPanel panel = new ChartPanel(chart); + window.add(panel); + window.pack(); + window.setMinimumSize(new Dimension(500, 300)); + + window.setVisible(true); + } + } diff --git a/src/Chessboard.java b/src/Chessboard.java index a8f2cb2..af5c248 100644 --- a/src/Chessboard.java +++ b/src/Chessboard.java @@ -1,8 +1,8 @@ import javax.swing.*; import java.awt.*; import java.awt.geom.AffineTransform; -import java.util.HashSet; -import java.util.Set; +import java.util.*; +import java.util.Timer; /** * Chessboard class @@ -65,6 +65,8 @@ public class Chessboard extends JPanel { static private Theme theme = Theme.activeTheme; + private long lastMoveTime = System.currentTimeMillis(); + /** * Constructor of the chessboard */ @@ -508,17 +510,41 @@ public class Chessboard extends JPanel { return player2; } + public void checkGame() { + Player[] players = new Player[]{player1, player2}; + String[] playerNames = new String[]{"White", "Black"}; + for (int i = 0; i < players.length; i++) { + if(players[i].inCheck()) { + System.out.println(playerNames[i] + " is in check!"); + if(players[i].hasNoPossibleMove()) { + String winner = playerNames[(i+1)%2]; + delayedMessage("Checkmate! Congratulations " + winner + ", you have won the game."); + return; + } + } + } + if(!activePlayer.inCheck() && activePlayer.hasNoPossibleMove()) { + delayedMessage("It's a stalemate! Neither player can make a move without putting their king in checkmate."); + } + } + + public void delayedMessage(String msg) { + Timer t = new Timer(); + t.schedule(new TimerTask() { + @Override + public void run() { + JOptionPane.showMessageDialog(Chess.chessboard, msg); + } + }, 1000); + } + public void changeActivePlayer() { + long now = System.currentTimeMillis(); + activePlayer.addDelay((int) (now-lastMoveTime)); + lastMoveTime = now; activePlayer = getOtherPlayer(); repaintRootPane(); - if(player1.inCheck()) { - System.out.println("Player1 in check!"); - if(player1.inMate()) System.out.println("Player1 in mate!"); - } - if(player2.inCheck()) { - System.out.println("Player2 in check!"); - if(player2.inMate()) System.out.println("Player2 in mate!"); - } + checkGame(); activePlayer.play(); } diff --git a/src/Player.java b/src/Player.java index c8c9380..e618cce 100644 --- a/src/Player.java +++ b/src/Player.java @@ -1,7 +1,4 @@ -import java.util.ArrayList; -import java.util.Random; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; public class Player { @@ -17,6 +14,8 @@ public class Player { private boolean isPlaying = false; + private ArrayList delays = new ArrayList<>(); + public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) { this.chessboard = chessboard; this.color = color; @@ -27,7 +26,7 @@ public class Player { return king.isEndangered(); } - public boolean inMate() { + public boolean hasNoPossibleMove() { for (APiece piece : getPieces()) { boolean[][] possibleMoves = piece.getPossibleMoves(); for (int y = 0; y < possibleMoves.length; y++) { @@ -142,4 +141,12 @@ public class Player { return cpu; } + public void addDelay(int delay) { + delays.add(delay); + } + + public List getDelays() { + return delays; + } + }