Added game end dialogs & statistics

This commit is contained in:
Filip Znachor 2023-05-05 00:34:52 +02:00
parent 82c14e3ee1
commit 9f44b1dc78
7 changed files with 110 additions and 20 deletions

View file

@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="jfreechart-1.5.3">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/jfreechart-1.5.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View file

@ -8,5 +8,6 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="org.jfree.svg-5.0.5" level="project" /> <orderEntry type="library" name="org.jfree.svg-5.0.5" level="project" />
<orderEntry type="library" name="jfreechart-1.5.3" level="project" />
</component> </component>
</module> </module>

BIN
lib/jfreechart-1.5.3.jar Normal file

Binary file not shown.

View file

@ -325,8 +325,8 @@ public abstract class APiece {
double startY = chessboard.startY + (fromY*chessboard.SQUARE_SIZE)*chessboard.boardScale; double startY = chessboard.startY + (fromY*chessboard.SQUARE_SIZE)*chessboard.boardScale;
double endX = chessboard.startX + (toX*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 endY = chessboard.startY + (toY*chessboard.SQUARE_SIZE)*chessboard.boardScale;
double stepX = (endX-startX)/100; double stepX = (endX-startX)/250;
double stepY = (endY-startY)/100; double stepY = (endY-startY)/250;
Timer timer = new Timer(); Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() { timer.scheduleAtFixedRate(new TimerTask() {
int i = 1; int i = 1;
@ -334,7 +334,7 @@ public abstract class APiece {
double currentY = 0; double currentY = 0;
public void run() { public void run() {
chessboard.repaintRootPane(getRepaintRectangle()); chessboard.repaintRootPane(getRepaintRectangle());
if(i > 100) { if(i > 250) {
timer.cancel(); timer.cancel();
setOverride(0, 0); setOverride(0, 0);
} else { } else {
@ -345,7 +345,7 @@ public abstract class APiece {
chessboard.repaintRootPane(getRepaintRectangle()); chessboard.repaintRootPane(getRepaintRectangle());
i++; i++;
} }
}, 5, 5); }, 2, 2);
} }
public void remove(boolean animate) { public void remove(boolean animate) {

View file

@ -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 org.jfree.svg.SVGGraphics2D;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@ -7,6 +11,8 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/** /**
* Main program layout * Main program layout
@ -68,7 +74,10 @@ public class Chess {
JMenu menuGame = new JMenu("Game"); JMenu menuGame = new JMenu("Game");
JMenuItem startNewGame = new JMenuItem("Start new 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); menuGame.add(startNewGame);
JMenuItem newGameFromFEN = new JMenuItem("Load from FEN"); JMenuItem newGameFromFEN = new JMenuItem("Load from FEN");
@ -81,6 +90,18 @@ public class Chess {
}); });
menuGame.add(newGameFromFEN); 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()); menuGame.add(new JPopupMenu.Separator());
JCheckBoxMenuItem toggleBlindMode = new JCheckBoxMenuItem("Blind mode"); 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<Integer> 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);
}
} }

View file

@ -1,8 +1,8 @@
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.util.HashSet; import java.util.*;
import java.util.Set; import java.util.Timer;
/** /**
* Chessboard class * Chessboard class
@ -65,6 +65,8 @@ public class Chessboard extends JPanel {
static private Theme theme = Theme.activeTheme; static private Theme theme = Theme.activeTheme;
private long lastMoveTime = System.currentTimeMillis();
/** /**
* Constructor of the chessboard * Constructor of the chessboard
*/ */
@ -508,17 +510,41 @@ public class Chessboard extends JPanel {
return player2; 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() { public void changeActivePlayer() {
long now = System.currentTimeMillis();
activePlayer.addDelay((int) (now-lastMoveTime));
lastMoveTime = now;
activePlayer = getOtherPlayer(); activePlayer = getOtherPlayer();
repaintRootPane(); repaintRootPane();
if(player1.inCheck()) { checkGame();
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!");
}
activePlayer.play(); activePlayer.play();
} }

View file

@ -1,7 +1,4 @@
import java.util.ArrayList; import java.util.*;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class Player { public class Player {
@ -17,6 +14,8 @@ public class Player {
private boolean isPlaying = false; private boolean isPlaying = false;
private ArrayList<Integer> delays = new ArrayList<>();
public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) { public Player(Chessboard chessboard, StartPosition startPosition, PieceColor color) {
this.chessboard = chessboard; this.chessboard = chessboard;
this.color = color; this.color = color;
@ -27,7 +26,7 @@ public class Player {
return king.isEndangered(); return king.isEndangered();
} }
public boolean inMate() { public boolean hasNoPossibleMove() {
for (APiece piece : getPieces()) { for (APiece piece : getPieces()) {
boolean[][] possibleMoves = piece.getPossibleMoves(); boolean[][] possibleMoves = piece.getPossibleMoves();
for (int y = 0; y < possibleMoves.length; y++) { for (int y = 0; y < possibleMoves.length; y++) {
@ -142,4 +141,12 @@ public class Player {
return cpu; return cpu;
} }
public void addDelay(int delay) {
delays.add(delay);
}
public List<Integer> getDelays() {
return delays;
}
} }