Implemented timer for testing new chess mode

SavePgn^2
Justin 2025-06-23 19:14:01 +02:00
parent 1dccba2e15
commit 268f5e2398
4 changed files with 172 additions and 9 deletions

View File

@ -23,10 +23,18 @@ public class GameController {
public GameController(GameGui gui, ChessEngine engine) {
this.gui = gui;
this.engine = engine;
engine.initTimers(3, 0);
time();
initListeners();
updateGuiBoard();
}
private void time() {
engine.getWhiteTimer().setOnTick(secs -> gui.updateWhiteTimerLabel(secs));
engine.getBlackTimer().setOnTick(secs -> gui.updateBlackTimerLabel(secs));
engine.getWhiteTimer().setOnTimeout(() -> onTimeout("WHITE"));
engine.getBlackTimer().setOnTimeout(() -> onTimeout("BLACK"));
engine.getWhiteTimer().start();
}
private int flipRow(int row) {
return gui.isFlipped() ? 7 - row : row;
}
@ -172,6 +180,10 @@ public class GameController {
} else if (engine.isStalemate() || engine.isDraw()) {
gui.displayMessage("Remis! (Stalemate oder andere Regel)");
}
if (!engine.isMated() && !engine.isStalemate() && !engine.isDraw()) {
switchTimers();
}
}
@ -180,6 +192,17 @@ public class GameController {
gui.updateBoard(board);
}
private void switchTimers() {
if (engine.getCurrentPlayer().equals("WHITE")) {
engine.getBlackTimer().stop();
engine.getWhiteTimer().start();
} else {
engine.getWhiteTimer().stop();
engine.getBlackTimer().start();
}
}
// Hilfsmethode, um von Koordinaten (row/col) auf z.B. "E2" zu kommen
private String coordToChessNotation(int modelRow, int modelCol) {
char file = (char)('A' + modelCol);
@ -188,6 +211,14 @@ public class GameController {
}
// Timeout-Methode
private void onTimeout(String color) {
String winner = color.equals("WHITE") ? "SCHWARZ" : "WEIß";
gui.displayMessage(winner + " hat durch Zeit gewonnen!");
engine.getWhiteTimer().stop();
engine.getBlackTimer().stop();
}
private void resetFieldBackground(int row, int col) {
Color LIGHT = new Color(0xe0e1dd);
Color DARK = new Color(0x778da9);

View File

@ -24,6 +24,8 @@ public class ChessEngine {
private static final Logger logger = Logger.getLogger(ChessEngine.class.getName());
private int currentMoveIndex = 0;
private Timer whiteTimer;
private Timer blackTimer;
public ChessEngine() {
logging();
@ -241,6 +243,11 @@ public class ChessEngine {
return games;
}
public void initTimers(int min, int sec) {
whiteTimer = new Timer(min, sec);
blackTimer = new Timer(min, sec);
}
public void saveAsPgn(Game game, String path, String dateiname) {
String event = game.getRound().getEvent().getName();
String site = game.getRound().getEvent().getSite();
@ -294,4 +301,7 @@ public class ChessEngine {
}
public Timer getWhiteTimer() { return whiteTimer; }
public Timer getBlackTimer() { return blackTimer; }
}

View File

@ -0,0 +1,81 @@
package de.hs_mannheim.informatik.chess.model;
import java.util.function.Consumer;
public class Timer {
private int secondsLeft;
private javax.swing.Timer swingTimer;
private Runnable onTimeout;
private Consumer<Integer> onTick;
/**
* Erstellt einen neuen Timer mit Startzeit in Minuten und Sekunden.
*/
public Timer(int minutes, int seconds) {
this.secondsLeft = minutes * 60 + seconds;
}
/**
* Setzt den Timeout-Callback.
*/
public void setOnTimeout(Runnable onTimeout) {
this.onTimeout = onTimeout;
}
/**
* Setzt den Tick-Callback (wird jede Sekunde aufgerufen).
*/
public void setOnTick(Consumer<Integer> onTick) {
this.onTick = onTick;
}
/**
* Startet oder setzt den Timer fort.
*/
public void start() {
if (swingTimer != null && swingTimer.isRunning()) {
swingTimer.stop();
}
swingTimer = new javax.swing.Timer(1000, e -> {
secondsLeft--;
if (onTick != null) {
onTick.accept(secondsLeft);
}
if (secondsLeft <= 0) {
stop();
if (onTimeout != null) {
onTimeout.run();
}
}
});
swingTimer.start();
}
/**
* Stoppt den Timer.
*/
public void stop() {
if (swingTimer != null) {
swingTimer.stop();
}
}
/**
* Setzt den Timer auf die gegebene Zeit zurück.
*/
public void reset(int minutes, int seconds) {
stop();
this.secondsLeft = minutes * 60 + seconds;
if (onTick != null) {
onTick.accept(secondsLeft);
}
}
/**
* Gibt die aktuelle Restzeit in Sekunden zurück.
*/
public int getSecondsLeft() {
return secondsLeft;
}
}

View File

@ -28,6 +28,9 @@ public class GameGui {
private JButton flipBoardButton;
private boolean isFlipped = false;
private JLabel whiteTimerLabel;
private JLabel blackTimerLabel;
JButton btnFirst = new JButton("|<");
JButton btnPrev = new JButton("<");
JButton btnNext = new JButton(">");
@ -160,6 +163,9 @@ public class GameGui {
JPanel statsPanel = new JPanel(new BorderLayout());
statsPanel.setBackground(new Color(0x0d1b2a));
// Panel für die Timer (NORD)
statsPanel.add(timerPanel(), BorderLayout.NORTH);
// Move-Liste
moveListPanel = new JPanel();
moveListPanel.setLayout(new BoxLayout(moveListPanel, BoxLayout.Y_AXIS));
@ -168,30 +174,47 @@ public class GameGui {
moveListScroll.setPreferredSize(new Dimension(250, 800));
statsPanel.add(moveListScroll, BorderLayout.CENTER);
// Button-Leiste
// Button-Leiste (SÜD)
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(new Color(0x0d1b2a));
// Grid oder Flow
buttonPanel.setLayout(new GridLayout(1, 4, 10, 0));
// Style (optional)
btnFirst.setBackground(new Color(0x212529)); btnFirst.setForeground(Color.WHITE);
btnPrev.setBackground(new Color(0x212529)); btnPrev.setForeground(Color.WHITE);
btnNext.setBackground(new Color(0x212529)); btnNext.setForeground(Color.WHITE);
btnLast.setBackground(new Color(0x212529)); btnLast.setForeground(Color.WHITE);
// Hinzufügen
buttonPanel.add(btnFirst);
buttonPanel.add(btnPrev);
buttonPanel.add(btnNext);
buttonPanel.add(btnLast);
// Unten ins BorderLayout
statsPanel.add(buttonPanel, BorderLayout.SOUTH);
return statsPanel;
}
private JPanel timerPanel() {
JPanel panel = new JPanel(new GridLayout(2, 1));
panel.setBackground(new Color(0x0d1b2a));
whiteTimerLabel = new JLabel("Weiß: 03:00", SwingConstants.CENTER);
blackTimerLabel = new JLabel("Schwarz: 03:00", SwingConstants.CENTER);
whiteTimerLabel.setFont(new Font("SansSerif", Font.BOLD, 24));
whiteTimerLabel.setForeground(Color.WHITE);
whiteTimerLabel.setBackground(new Color(0x1b263b));
whiteTimerLabel.setOpaque(true);
blackTimerLabel.setFont(new Font("SansSerif", Font.BOLD, 24));
blackTimerLabel.setForeground(Color.WHITE);
blackTimerLabel.setBackground(new Color(0x1b263b));
blackTimerLabel.setOpaque(true);
panel.add(whiteTimerLabel);
panel.add(blackTimerLabel);
return panel;
}
public String showPromotionDialog(String color) {
String[] choices = {"Dame", "Turm", "Springer", "Läufer"};
String choice = (String) JOptionPane.showInputDialog(
@ -264,6 +287,24 @@ public class GameGui {
}
}
public void updateWhiteTimerLabel(int secondsLeft) {
whiteTimerLabel.setText("Weiß: " + formatTime(secondsLeft));
}
public void updateBlackTimerLabel(int secondsLeft) {
blackTimerLabel.setText("Schwarz: " + formatTime(secondsLeft));
}
private String formatTime(int seconds) {
int min = seconds / 60;
int sec = seconds % 60;
return String.format("%02d:%02d", min, sec);
}
// Optional: Getter, falls du direkt ran willst (braucht man aber fast nie)
public JLabel getWhiteTimerLabel() { return whiteTimerLabel; }
public JLabel getBlackTimerLabel() { return blackTimerLabel; }
public void displayMessage(String msg) {
JOptionPane.showMessageDialog(null, msg);