diff --git a/schach/src/main/java/de/hs_mannheim/informatik/chess/controller/GameController.java b/schach/src/main/java/de/hs_mannheim/informatik/chess/controller/GameController.java index c0b4d56..7f6b602 100644 --- a/schach/src/main/java/de/hs_mannheim/informatik/chess/controller/GameController.java +++ b/schach/src/main/java/de/hs_mannheim/informatik/chess/controller/GameController.java @@ -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(); + } } @@ -179,14 +191,33 @@ public class GameController { BoardDTO board = engine.getBoardAsDTO(); 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); int rank = 8 - modelRow; return "" + file + rank; } + + // 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); diff --git a/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java index 1b9fb78..d51554f 100644 --- a/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java +++ b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/ChessEngine.java @@ -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; } + } diff --git a/schach/src/main/java/de/hs_mannheim/informatik/chess/model/Timer.java b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/Timer.java new file mode 100644 index 0000000..4ad3738 --- /dev/null +++ b/schach/src/main/java/de/hs_mannheim/informatik/chess/model/Timer.java @@ -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 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 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; + } +} + + diff --git a/schach/src/main/java/de/hs_mannheim/informatik/chess/view/GameGui.java b/schach/src/main/java/de/hs_mannheim/informatik/chess/view/GameGui.java index 5d9dac3..e2bdb9f 100644 --- a/schach/src/main/java/de/hs_mannheim/informatik/chess/view/GameGui.java +++ b/schach/src/main/java/de/hs_mannheim/informatik/chess/view/GameGui.java @@ -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,29 +174,46 @@ 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"}; @@ -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);