Compare commits

..

No commits in common. "8447ce5fe3ac05132e797591e8f0d168f1cf4bbb" and "12bea41b1e9b189df4d9e2182b70b3fad854d94d" have entirely different histories.

15 changed files with 169 additions and 4410 deletions

File diff suppressed because it is too large Load Diff

View File

@ -33,20 +33,13 @@
<artifactId>chesslib</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<!-- Mockito damit man Controller und Gui besser testen kann-->
<!-- JUnit 3 (wie im Template, ggf. auf JUnit 4/5 upgraden für moderne Projekte) -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -89,7 +82,7 @@
<version>3.1.2</version>
</plugin>
</plugins>
</pluginManagement>
</pluginManagement>
</build>
<reporting>

View File

@ -8,8 +8,6 @@ import java.util.List;
import javax.swing.BorderFactory;
import com.github.bhlangonijr.chesslib.game.Game;
import de.hs_mannheim.informatik.chess.model.ChessEngine;
import de.hs_mannheim.informatik.chess.model.MoveDTO;
import de.hs_mannheim.informatik.chess.model.PieceDTO;
@ -83,25 +81,6 @@ public class GameController {
engine.setPositionToMoveIndex(engine.getMoveListSize());
updateGuiBoard();
});
gui.getBtnSave().addActionListener(e -> {
System.out.println("Save-Button wurde geklickt!");
Game currentGame = engine.getCurrentGame();
javax.swing.JFileChooser fileChooser = new javax.swing.JFileChooser();
fileChooser.setDialogTitle("PGN speichern unter...");
int userSelection = fileChooser.showSaveDialog(null);
if (userSelection == javax.swing.JFileChooser.APPROVE_OPTION) {
java.io.File fileToSave = fileChooser.getSelectedFile();
try {
engine.saveAsPgn(currentGame, fileToSave.getParent(), fileToSave.getName());
gui.displayMessage("PGN gespeichert: " + fileToSave.getAbsolutePath());
} catch (Exception ex) {
gui.displayMessage("Fehler beim Speichern: " + ex.getMessage());
}
}
});
gui.getFlipBoardButton().addActionListener(e -> {
@ -122,89 +101,14 @@ public class GameController {
// 3. Board neu zeichnen
updateGuiBoard();
});
// --- AUFGEBEN-BUTTON ---
gui.getResignButton().addActionListener(e -> {
if (gameOver) return;
int answer = javax.swing.JOptionPane.showConfirmDialog(
null,
"Willst du wirklich aufgeben?",
"Aufgeben",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (answer == javax.swing.JOptionPane.YES_OPTION) {
gameOver = true;
String winner = engine.getCurrentPlayer().equals("WHITE") ? "SCHWARZ" : "WEIß";
gui.displayMessage(winner + " gewinnt durch Aufgabe!");
engine.getWhiteTimer().stop();
engine.getBlackTimer().stop();
askForRestart();
}
});
// --- PATT-/REMIS-BUTTON ---
gui.getDrawButton().addActionListener(e -> {
if (gameOver) return;
int answer = javax.swing.JOptionPane.showConfirmDialog(
null,
"Remis anbieten? (Das Spiel endet sofort unentschieden)",
"Remis",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (answer == javax.swing.JOptionPane.YES_OPTION) {
gameOver = true;
gui.displayMessage("Remis! (durch Einigung)");
engine.getWhiteTimer().stop();
engine.getBlackTimer().stop();
askForRestart();
}
});
gui.getUndoButton().addActionListener(e -> {
// Wer ist am Zug? (Das ist der, der gefragt wird)
String currentPlayer = engine.getCurrentPlayer(); // "WHITE" oder "BLACK"
// Wer möchte zurücknehmen? (Das ist der, der NICHT am Zug ist)
String currentName = currentPlayer.equals("WHITE") ? "Weiß" : "Schwarz";
String previousName = currentPlayer.equals("WHITE") ? "Schwarz" : "Weiß";
int answer = javax.swing.JOptionPane.showConfirmDialog(
null,
currentName + " ist am Zug. " +
previousName + " möchte seinen letzten Zug zurücknehmen.\n" +
currentName + ", erlaubst du das?",
"Zug zurücknehmen?",
javax.swing.JOptionPane.YES_NO_OPTION
);
if (answer == javax.swing.JOptionPane.YES_OPTION) {
engine.undoLastMove();
updateGuiBoard();
gui.updateMoveList(engine.getMoveListStringsGrouped());
gui.setOpeningLabel(engine.getOpeningName());
gui.displayMessage("Der letzte Zug wurde zurückgenommen.");
} else if (answer == javax.swing.JOptionPane.NO_OPTION) {
gui.displayMessage("Das Zurücknehmen wurde abgelehnt.");
}
});
}
private boolean isAtLatestMove() {
return engine.getCurrentMoveIndex() == engine.getMoveListSize();
}
private void handleClick(int guiRow, int guiCol) {
if (gameOver) return;
if (!isAtLatestMove()) {
gui.displayMessage("Du bist im Zug-Archiv und kannst keine Figuren bewegen. Klick auf '>|', um zum letzten Zug zu gehen.");
return;
}
int modelRow = flipRow(guiRow);
int modelCol = flipCol(guiCol);
@ -301,7 +205,6 @@ public class GameController {
public void updateGuiBoard() {
BoardDTO board = engine.getBoardAsDTO();
gui.updateBoard(board);
gui.setOpeningLabel(engine.getOpeningName());
}
private void switchTimers() {

View File

@ -47,24 +47,6 @@ public class MainController {
CreativeGui creativegui = new CreativeGui();
ChessEngine engine = new ChessEngine();
new CreativeController(creativegui, engine);
creativegui.setStartGameCallback(fen -> {
ChessEngine newEngine = new ChessEngine();
newEngine.setPositionFromFEN(fen);
GameGui gameGui = new GameGui();
GameEndCallback callback = new GameEndCallback() {
public void onNewGameRequested() {
startCreativeMode();
}
public void onReturnToMenu() {
new MainController();
}
};
new GameController(gameGui, newEngine, callback);
});
}
private void startLoadGameMode() {

View File

@ -65,8 +65,7 @@ public class PgnController {
public void updateGuiBoard() {
BoardDTO board = engine.getBoardAsDTO();
gui.updateBoard(board);
gui.updateMoveList(engine.getMoveListStringsGrouped());
gui.setOpeningLabel(engine.getOpeningName());
gui.updateMoveList(engine.getMoveListStringsGrouped());
}
private void resetFieldBackground(int row, int col) {

View File

@ -14,30 +14,24 @@ import java.util.logging.SimpleFormatter;
import com.github.bhlangonijr.chesslib.Board;
import com.github.bhlangonijr.chesslib.Piece;
import com.github.bhlangonijr.chesslib.Square;
import com.github.bhlangonijr.chesslib.game.Game;
import com.github.bhlangonijr.chesslib.move.Move;
import com.github.bhlangonijr.chesslib.pgn.PgnHolder;
import com.github.bhlangonijr.chesslib.game.*;
import com.github.bhlangonijr.chesslib.move.MoveList;
import java.time.LocalDate;
import com.github.bhlangonijr.chesslib.Side;
public class ChessEngine {
private Board board;
private List<Move> moves = new ArrayList<>();
private String initialFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
private static final Logger logger = Logger.getLogger(ChessEngine.class.getName());
private int currentMoveIndex = 0;
private Timer whiteTimer;
private Timer blackTimer;
private Opening detectedOpening = null;
public ChessEngine() {
logging();
board = new Board();
}
public boolean move(MoveDTO move) {
String from = "" + (char)('A' + move.getFromCol()) + (8 - move.getFromRow());
String to = "" + (char)('A' + move.getToCol()) + (8 - move.getToRow());
@ -45,44 +39,19 @@ public class ChessEngine {
if (board.legalMoves().contains(libMove)) {
board.doMove(libMove);
// Replay? Dann abschneiden
//Replay? Dann abschneiden
if (currentMoveIndex < moves.size()) {
logger.info("Replay-Modus: Züge nach " + currentMoveIndex + " werden entfernt.");
logger.info("Replay-Modus: Züge nach " + currentMoveIndex + " werden entfernt.");
moves = new ArrayList<>(moves.subList(0, currentMoveIndex));
}
moves.add(libMove);
currentMoveIndex++;
logger.info("Zug erfolgreich durchgeführt: " + libMove);
// Opening-Erkennung nach jedem erfolgreichen Zug
String playedMovesUci = movesToUciString(moves);
detectedOpening = Opening.detect(playedMovesUci);
if (detectedOpening != null) {
logger.info("Aktuelles Opening erkannt: " + detectedOpening.getEco() + " - " + detectedOpening.getName());
// Optional: Speichere das Opening in ein Feld, falls benötigt
}
return true;
}
logger.warning("Ungültiger Zug: " + libMove);
return false;
}
public String getOpeningName() {
if (detectedOpening != null) {
return detectedOpening.getEco() + " - " + detectedOpening.getName();
} else {
return "unbekannt";
}
}
private String movesToUciString(List<Move> moves) {
StringBuilder sb = new StringBuilder();
for (Move m : moves) {
sb.append(m.toString()).append(" ");
}
return sb.toString().trim();
}
public List<MoveDTO> getLegalDestinations(String from) {
logger.info("Hole legale Züge von: " + from);
@ -189,17 +158,15 @@ public class ChessEngine {
}
public void setPositionToMoveIndex(int idx) {
logger.info("Setze Board auf Zug-Index: " + idx);
// Neues Board erzeugen
logger.info("Setze Board auf Zug-Index: " + idx);
board = new Board();
board.loadFromFen(initialFen); // Statt new Board() -> initialFen!
for (int i = 0; i < idx; i++) {
board.doMove(moves.get(i));
}
currentMoveIndex = idx;
String playedMovesUci = movesToUciString(moves.subList(0, idx));
detectedOpening = Opening.detect(playedMovesUci);
}
public int getCurrentMoveIndex() {
logger.info("Hole aktuellen Zug-Index: " + currentMoveIndex);
return currentMoveIndex;
@ -220,7 +187,6 @@ public class ChessEngine {
public void setPositionFromFEN(String fen) {
board.loadFromFen(fen);
initialFen = fen;
}
@ -264,7 +230,7 @@ public class ChessEngine {
logger.info("ChessEngine wurde initialisiert.");
}
public List<Game> loadGamesFromPgn(String path) throws IOException {
PgnHolder pgnHolder = new PgnHolder(path);
@ -283,17 +249,14 @@ public class ChessEngine {
}
public void saveAsPgn(Game game, String path, String dateiname) {
// Sicher alle Strings holen (nie null)
String event = safe(game.getRound().getEvent().getName());
String site = safe(game.getRound().getEvent().getSite());
String event = game.getRound().getEvent().getName();
String site = game.getRound().getEvent().getSite();
String round = "" + game.getRound().getNumber();
// Datum für PGN-Format (YYYY.MM.DD)
String date = safe(game.getRound().getEvent().getStartDate()).replace("-", ".");
String wName = safe(game.getWhitePlayer().getName());
String bName = safe(game.getBlackPlayer().getName());
String result = safe(game.getResult().getDescription());
String date = game.getRound().getEvent().getStartDate();
String wName = game.getWhitePlayer().getName();
String bName = game.getBlackPlayer().getName();
String result = game.getResult().getDescription();
// PGN-Header zusammenbauen
StringBuilder header = new StringBuilder();
header.append("[Event \"" + event + "\"]\n");
header.append("[Site \"" + site + "\"]\n");
@ -301,102 +264,29 @@ public class ChessEngine {
header.append("[Round \"" + round + "\"]\n");
header.append("[White \"" + wName + "\"]\n");
header.append("[Black \"" + bName + "\"]\n");
header.append("[Result \"" + result + "\"]\n\n");
header.append("[Result \"" + result + "\"]\n");
header.append("\n");
// Züge als SAN holen
StringBuilder moves = new StringBuilder();
StringBuilder sb = new StringBuilder();
String[] sanArray = game.getHalfMoves().toSanArray();
for (int i = 0; i < sanArray.length; i++) {
if (i % 2 == 0) {
moves.append((i / 2 + 1)).append(". ");
sb.append((i / 2 + 1)).append(". ");
}
moves.append(sanArray[i]).append(" ");
// Optional: Zeilenumbruch für Lesbarkeit
// if (i > 0 && i % 8 == 0) moves.append("\n");
sb.append(sanArray[i]).append(" ");
}
moves.append(result); // Ergebnis am Ende!
String file = header + moves.toString();
sb.append(result); // Endergebnis muss auch am Ende stehen!
String file = header.toString() + sb.toString();
// Datei schreiben
try {
Files.writeString(Path.of(path, dateiname), file, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
}
// Hilfsfunktion für Null-Sicherheit
private String safe(String s) {
return s == null ? "?" : s;
}
public Game getCurrentGame() {
return getCurrentGame(this.board, this.moves, this.currentMoveIndex);
}
public Game getCurrentGame(Board board, java.util.List<Move> moves, int currentMoveIndex) {
// Event und Turnierdaten setzen
Event event = new Event();
event.setName("Generated Game");
event.setSite("Local");
event.setStartDate(LocalDate.now().toString()); // Format: yyyy-MM-dd
// Runde anlegen
Round round = new Round(event);
round.setNumber(1);
// Spiel initialisieren
Game game = new Game("1", round); // "1" ist die Game-ID
// Spieler setzen (deine MyPlayer-Klasse)
game.setWhitePlayer(new MyPlayer("White"));
game.setBlackPlayer(new MyPlayer("Black"));
// Ergebnis setzen
if (board.isMated()) {
game.setResult(board.getSideToMove() == Side.WHITE ? GameResult.BLACK_WON : GameResult.WHITE_WON);
} else if (board.isStaleMate() || board.isDraw()) {
game.setResult(GameResult.DRAW);
} else {
game.setResult(GameResult.ONGOING);
}
// Züge übernehmen
MoveList moveList = new MoveList();
for (Move move : moves) {
moveList.add(move);
}
game.setHalfMoves(moveList);
// Position auf aktuellen Zug setzen (letzter gespielter Halbzug)
if (currentMoveIndex > 0 && currentMoveIndex <= moveList.size()) {
game.setPosition(currentMoveIndex - 1);
} else {
game.setPosition(moveList.size() - 1);
}
// FEN setzen: JETZT das aktuelle Board-FEN verwenden!
game.setBoard(new Board());
game.getBoard().loadFromFen(board.getFen());
return game;
}
public void undoLastMove() {
if (currentMoveIndex > 0 && moves.size() > 0) {
board.undoMove(); // 1. Brett zurücksetzen
moves.remove(currentMoveIndex - 1); // 2. Zug aus Move-Liste löschen
currentMoveIndex--; // 3. Index anpassen
// 4. Erkennung Opening neu machen!
String playedMovesUci = movesToUciString(moves.subList(0, currentMoveIndex));
detectedOpening = Opening.detect(playedMovesUci);
}
}
public void loadMoves(List<Move> moveList) {
board = new Board(); // Neues leeres Brett
@ -412,6 +302,6 @@ public class ChessEngine {
}
public Timer getWhiteTimer() { return whiteTimer; }
public Timer getBlackTimer() { return blackTimer; }
public Timer getBlackTimer() { return blackTimer; }
}

View File

@ -1,72 +0,0 @@
package de.hs_mannheim.informatik.chess.model;
import com.github.bhlangonijr.chesslib.game.Player;
import com.github.bhlangonijr.chesslib.game.PlayerType;
public class MyPlayer implements Player {
private String id = "";
private String name;
private int elo = 0;
private PlayerType type = PlayerType.HUMAN;
private String description = "";
private String longDescription = "";
public MyPlayer(String name) {
this.name = name;
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
@Override
public int getElo() {
return elo;
}
@Override
public void setElo(int elo) {
this.elo = elo;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public PlayerType getType() {
return type;
}
@Override
public void setType(PlayerType type) {
this.type = type;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setDescription(String description) {
this.description = description;
}
@Override
public String getLongDescription() {
return longDescription;
}
}

View File

@ -1,68 +0,0 @@
package de.hs_mannheim.informatik.chess.model;
import java.util.*;
import java.nio.file.*;
import java.io.*;
public class Opening {
private final String eco;
private final String name;
private final String moves;
public Opening(String eco, String name, String moves) {
this.eco = eco;
this.name = name;
this.moves = moves;
}
public String getEco() { return eco; }
public String getName() { return name; }
public String getMoves() { return moves; }
// Öffnet und cached die Liste aus der gewünschten CSV
private static List<Opening> cachedOpenings = null;
public static List<Opening> allOpenings() {
if (cachedOpenings == null) {
cachedOpenings = new ArrayList<>();
// Passe den Pfad für deinen Benutzernamen an!
String path = "Ressources/all_openings.csv";
try (BufferedReader br = Files.newBufferedReader(Paths.get(path))) {
String line;
while ((line = br.readLine()) != null) {
// CSV-Format: ECO,"Name","Moves"
String[] parts = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
if (parts.length == 3) {
String eco = parts[0];
String name = parts[1].replaceAll("^\"|\"$", "");
String moves = parts[2].replaceAll("^\"|\"$", "");
cachedOpenings.add(new Opening(eco, name, moves));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return cachedOpenings;
}
/**
* Sucht das längste passende Opening für eine gegebene Zugfolge (UCI).
* @param playedMovesUci UCI-Züge als String, z.B. "e2e4 e7e5 g1f3"
* @return bestes Opening oder null
*/
public static Opening detect(String playedMovesUci) {
Opening bestMatch = null;
int bestLength = 0;
for (Opening opening : allOpenings()) {
if (playedMovesUci.startsWith(opening.getMoves())) {
if (opening.getMoves().length() > bestLength) {
bestMatch = opening;
bestLength = opening.getMoves().length();
}
}
}
return bestMatch;
}
}

View File

@ -5,11 +5,6 @@ import java.awt.*;
import java.util.HashMap;
public class CreativeGui {
public interface StartGameCallback {
void onStartGame(String fen);
}
private boolean isFlipped = false;
private JFrame frame;
@ -18,10 +13,6 @@ public class CreativeGui {
private JTextField fenField;
private JButton updateBtn;
private JButton flipBoardButton;
private StartGameCallback startGameCallback;
private JButton startGameButton;
public static final HashMap<String, String> UNICODE_MAP = new HashMap<String, String>() {{
put("BLACK_KING", "\u265A"); put("BLACK_QUEEN", "\u265B");
@ -39,8 +30,7 @@ public class CreativeGui {
public CreativeGui() {
frame = new JFrame("Creative Mode");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(false);
frame.setSize(1600, 1200);
frame.setLocationRelativeTo(null);
JPanel mainPanel = new JPanel(new GridBagLayout());
@ -50,7 +40,7 @@ public class CreativeGui {
// LINKS: chessPanel (Board+Toolbars)
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0.7;
gbc.weightx = 0.6;
gbc.weighty = 1.0;
gbc.insets = new Insets(5, 5, 5, 0);
gbc.fill = GridBagConstraints.BOTH;
@ -59,7 +49,7 @@ public class CreativeGui {
// RECHTS: FEN & Optionen
gbc.gridx = 1;
gbc.gridy = 0;
gbc.weightx = 0.3;
gbc.weightx = 0.4;
gbc.weighty = 1.0;
gbc.insets = new Insets(5, 0, 5, 5);
gbc.fill = GridBagConstraints.BOTH;
@ -81,7 +71,7 @@ public class CreativeGui {
btn.setFocusPainted(false);
btn.setPreferredSize(new Dimension(70, 70));
btn.setBackground(white ? LIGHT : DARK);
btn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
btn.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0));
String key = prefix + type;
btn.addActionListener(e -> selectedPiece = key);
panel.add(btn);
@ -114,76 +104,47 @@ public class CreativeGui {
}
private JPanel chessPanel() {
JPanel chessPanel = new JPanel(new BorderLayout());
JPanel chessPanel = new JPanel(new GridBagLayout());
chessPanel.setBackground(new Color(0x1b263b));
GridBagConstraints gbc = new GridBagConstraints();
// Board UND Toolbars in EINEM Panel, damit sie linksbündig mit dem Brett starten!
JPanel boardAndToolbars = new JPanel(new BorderLayout());
boardAndToolbars.setOpaque(false);
// Toolbar oben
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
chessPanel.add(toolbarPanel(false), gbc);
// Toolbar Schwarz (oben)
JPanel blackToolbar = toolbarPanel(false);
boardAndToolbars.add(blackToolbar, BorderLayout.NORTH);
// Board
gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.BOTH;
chessPanel.add(boardPanel(), gbc);
// Board (zentriert im Panel)
JPanel board = boardPanel();
boardAndToolbars.add(board, BorderLayout.CENTER);
// Toolbar unten
gbc.gridx = 0;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
chessPanel.add(toolbarPanel(true), gbc);
// Toolbar Weiß (unten)
JPanel whiteToolbar = toolbarPanel(true);
boardAndToolbars.add(whiteToolbar, BorderLayout.SOUTH);
// Board+Toolbars mittig in einem Panel mit FlowLayout, damit sie zentriert sind
JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
centerPanel.setOpaque(false);
centerPanel.add(boardAndToolbars);
// Drehknopf
flipBoardButton = new JButton("⇵");
flipBoardButton.setPreferredSize(new Dimension(70, 70));
flipBoardButton.setFont(new Font("SansSerif", Font.BOLD, 40));
flipBoardButton.setBackground(new Color(0x5500ff));
flipBoardButton.setForeground(Color.WHITE);
flipBoardButton.setFocusPainted(false);
blackToolbar.setPreferredSize(new Dimension(0, 70)); // 70 px hoch
whiteToolbar.setPreferredSize(new Dimension(0, 70));
// Dynamisch skalieren wie gehabt
centerPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
int totalHeight = centerPanel.getHeight();
int totalWidth = centerPanel.getWidth();
int toolbarHeight = blackToolbar.getPreferredSize().height + whiteToolbar.getPreferredSize().height;
// Falls Toolbars keine PrefSize haben, nimm getHeight()
if (toolbarHeight == 0) toolbarHeight = blackToolbar.getHeight() + whiteToolbar.getHeight();
int boardMaxHeight = totalHeight - toolbarHeight;
int size = Math.min(totalWidth, boardMaxHeight);
board.setPreferredSize(new Dimension(size, size));
board.revalidate();
}
});
chessPanel.add(centerPanel, BorderLayout.CENTER);
// Drehknopf rechts, schön mittig
JPanel eastPanel = new JPanel();
eastPanel.setOpaque(false);
eastPanel.setLayout(new BoxLayout(eastPanel, BoxLayout.Y_AXIS));
eastPanel.add(Box.createVerticalGlue());
eastPanel.add(flipBoardButton = createFlipButton());
eastPanel.add(Box.createVerticalGlue());
chessPanel.add(eastPanel, BorderLayout.EAST);
// Buffer links, wenn du willst
chessPanel.add(Box.createRigidArea(new Dimension(40, 0)), BorderLayout.WEST);
GridBagConstraints btn = new GridBagConstraints();
btn.gridx = 0;
btn.gridy = 2;
btn.weightx = 0.0;
btn.weighty = 0.0;
btn.anchor = GridBagConstraints.EAST;
btn.insets = new Insets(5, 0, 0, 0);
chessPanel.add(flipBoardButton, btn);
return chessPanel;
}
// Flip-Knopf Builder, damit dus an mehreren Stellen nutzen kannst:
private JButton createFlipButton() {
JButton btn = new JButton("⇵");
btn.setPreferredSize(new Dimension(70, 70));
btn.setFont(new Font("SansSerif", Font.BOLD, 40));
btn.setBackground(new Color(0x5500ff));
btn.setForeground(Color.WHITE);
btn.setFocusPainted(false);
return btn;
}
private JPanel fenPanel() {
JPanel panel = new JPanel();
@ -198,20 +159,7 @@ public class CreativeGui {
updateBtn = new JButton("Update Board");
updateBtn.setAlignmentX(Component.CENTER_ALIGNMENT);
panel.add(updateBtn);
startGameButton = new JButton("🟢 Partie starten");
startGameButton.setAlignmentX(Component.CENTER_ALIGNMENT);
startGameButton.setBackground(new Color(0x218838));
startGameButton.setForeground(Color.WHITE);
panel.add(startGameButton);
startGameButton.addActionListener(e -> {
if (startGameCallback != null) {
startGameCallback.onStartGame(getFenText());
}
});
return panel;
}
// Für Controller
@ -223,12 +171,6 @@ public class CreativeGui {
public void setSelectedPiece(String piece) { selectedPiece = piece; }
public String getSelectedPiece() { return selectedPiece; }
public JButton getStartGameButton() { return startGameButton; }
public void setStartGameCallback(StartGameCallback callback) {
this.startGameCallback = callback;
}
public boolean isFlipped() { return isFlipped; }
public void setFlipped(boolean f) { isFlipped = f; }
public JButton getFlipBoardButton() { return flipBoardButton; }

View File

@ -7,12 +7,9 @@ import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
@ -30,21 +27,14 @@ public class GameGui {
private JLabel[][] fields = new JLabel[8][8];
private JButton flipBoardButton;
private boolean isFlipped = false;
JButton btnSave = new JButton("💾");
private JLabel whiteTimerLabel;
private JLabel blackTimerLabel;
private JLabel openingLabel;
private JButton btnFirst = new JButton("|<");
private JButton btnPrev = new JButton("<");
private JButton btnNext = new JButton(">");
private JButton btnLast = new JButton(">|");
private JButton resignButton;
private JButton drawButton;
private JButton quickSaveButton;
private JButton undoButton;
JButton btnFirst = new JButton("|<");
JButton btnPrev = new JButton("<");
JButton btnNext = new JButton(">");
JButton btnLast = new JButton(">|");
Color LIGHT = new Color(0xe0e1dd);
Color DARK = new Color(0x778da9);
@ -60,8 +50,7 @@ public class GameGui {
public JFrame mainFrame() {
JFrame frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(false);
frame.setSize(1600, 1000);
frame.setLocationRelativeTo(null);
frame.add(mainPanel());
@ -137,82 +126,38 @@ public class GameGui {
return boardPanel;
}
public JPanel chessPanel(JPanel boardPanel) {
JPanel chessPanel = new JPanel(new BorderLayout());
chessPanel.setBackground(new Color(0x1b263b));
public JPanel chessPanel(JPanel panel) {
JPanel chessPanel = new JPanel(new GridBagLayout());
GridBagConstraints board = new GridBagConstraints();
chessPanel.setBackground(new Color(0x1b263b));
board.gridx = 0;
board.gridy = 0;
board.weightx = 0.7;
board.weighty = 1.0;
board.insets = new Insets(0, 0, 0, 0);
//oben, links, unten, rechts
board.fill = GridBagConstraints.BOTH;
chessPanel.add(panel);
// Button unten rechts
flipBoardButton = new JButton("⇵");
flipBoardButton.setPreferredSize(new Dimension(70, 70));
flipBoardButton.setFont(new Font("SansSerif", Font.BOLD, 40));
flipBoardButton.setBackground(new Color(0x5500ff));
flipBoardButton.setForeground(Color.WHITE);
flipBoardButton.setFocusPainted(false);
// --- Eröffnungslabel oben ---
openingLabel = new JLabel("Eröffnung: unbekannt", SwingConstants.CENTER);
openingLabel.setFont(new Font("SansSerif", Font.BOLD, 24));
openingLabel.setForeground(Color.WHITE);
openingLabel.setOpaque(true);
openingLabel.setBackground(new Color(0x283655));
openingLabel.setPreferredSize(new Dimension(800, 50));
chessPanel.add(openingLabel, BorderLayout.NORTH);
GridBagConstraints btn = new GridBagConstraints();
btn.gridx = 0;
btn.gridy = 1;
btn.weightx = 0.0;
btn.weighty = 0.0;
btn.anchor = GridBagConstraints.SOUTHEAST;
btn.insets = new Insets(10, 0, 0, 0);
// --- Board in ein zentriertes Panel mit fixer Größe ---
JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
centerPanel.setOpaque(false);
centerPanel.add(boardPanel);
centerPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
int size = Math.min(centerPanel.getWidth(), centerPanel.getHeight());
boardPanel.setPreferredSize(new Dimension(size, size));
boardPanel.revalidate();
}
});
chessPanel.add(centerPanel, BorderLayout.CENTER);
// --- Dummy-Buffer für WEST und EAST ---
chessPanel.add(Box.createRigidArea(new Dimension(40, 0)), BorderLayout.WEST);
chessPanel.add(Box.createRigidArea(new Dimension(40, 0)), BorderLayout.EAST);
// --- Buttonleiste unten bauen ---
JPanel buttonRow = new JPanel();
buttonRow.setOpaque(false);
buttonRow.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT, 10, 0));
resignButton = new JButton("🏳");
resignButton.setPreferredSize(new Dimension(70, 70));
resignButton.setFont(new Font("SansSerif", Font.BOLD, 35));
resignButton.setBackground(new Color(0xff0044));
resignButton.setForeground(Color.WHITE);
resignButton.setFocusPainted(false);
drawButton = new JButton("½");
drawButton.setPreferredSize(new Dimension(70, 70));
drawButton.setFont(new Font("SansSerif", Font.BOLD, 35));
drawButton.setBackground(new Color(0x0080ff));
drawButton.setForeground(Color.WHITE);
drawButton.setFocusPainted(false);
flipBoardButton = new JButton("⇵");
flipBoardButton.setPreferredSize(new Dimension(70, 70));
flipBoardButton.setFont(new Font("SansSerif", Font.BOLD, 40));
flipBoardButton.setBackground(new Color(0x5500ff));
flipBoardButton.setForeground(Color.WHITE);
flipBoardButton.setFocusPainted(false);
undoButton = new JButton("↧");
undoButton.setPreferredSize(new Dimension(70, 70));
undoButton.setFont(new Font("SansSerif", Font.BOLD, 40));
undoButton.setBackground(new Color(0xffa500)); // Orange
undoButton.setForeground(Color.WHITE);
undoButton.setFocusPainted(false);
buttonRow.add(undoButton);
buttonRow.add(resignButton);
buttonRow.add(drawButton);
buttonRow.add(flipBoardButton);
chessPanel.add(buttonRow, BorderLayout.SOUTH);
return chessPanel;
chessPanel.add(flipBoardButton, btn);
return chessPanel;
}
public JPanel statsPanel() {
JPanel statsPanel = new JPanel(new BorderLayout());
@ -232,18 +177,15 @@ public class GameGui {
// Button-Leiste (SÜD)
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(new Color(0x0d1b2a));
buttonPanel.setLayout(new GridLayout(1, 5, 10, 0)); // Jetzt 5 statt 4 Spalten!
buttonPanel.setLayout(new GridLayout(1, 4, 10, 0));
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);
btnSave.setBackground(new Color(0x218838)); btnSave.setForeground(Color.WHITE);
buttonPanel.add(btnFirst);
buttonPanel.add(btnPrev);
buttonPanel.add(btnNext);
buttonPanel.add(btnLast);
buttonPanel.add(btnSave);
statsPanel.add(buttonPanel, BorderLayout.SOUTH);
return statsPanel;
@ -324,9 +266,6 @@ public class GameGui {
public JButton getBtnPrev() { return btnPrev; }
public JButton getBtnNext() { return btnNext; }
public JButton getBtnLast() { return btnLast; }
public JButton getBtnSave() { return btnSave; }
public JButton getResignButton() { return resignButton; }
public JButton getDrawButton() { return drawButton; }
public void updateBoard(BoardDTO boardDTO) {
PieceDTO[][] board = boardDTO.getBoard();
@ -366,13 +305,6 @@ public class GameGui {
public JLabel getWhiteTimerLabel() { return whiteTimerLabel; }
public JLabel getBlackTimerLabel() { return blackTimerLabel; }
public void setOpeningLabel(String text) {
openingLabel.setText("Eröffnung: " + text);
}
public JButton getUndoButton() {
return undoButton;
}
public void displayMessage(String msg) {
JOptionPane.showMessageDialog(null, msg);

View File

@ -17,8 +17,7 @@ public class MainGui {
frame = new JFrame("Chess - Hauptmenü");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(false);
frame.setSize(1600, 1000);
frame.setLocationRelativeTo(null);
//Haupt-Panel mit GridBagLayout

View File

@ -3,7 +3,6 @@ package de.hs_mannheim.informatik.chess.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
@ -11,7 +10,6 @@ import java.awt.GridLayout;
import java.awt.Insets;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
@ -35,8 +33,6 @@ public class PgnGui {
JButton btnNext = new JButton(">");
JButton btnLast = new JButton(">|");
private JLabel openingLabel;
Color LIGHT = new Color(0xe0e1dd);
Color DARK = new Color(0x778da9);
@ -51,8 +47,7 @@ public class PgnGui {
public JFrame mainFrame() {
JFrame frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(false);
frame.setSize(1600, 1000);
frame.setLocationRelativeTo(null);
frame.add(mainPanel());
@ -128,57 +123,37 @@ public class PgnGui {
return boardPanel;
}
public JPanel chessPanel(JPanel boardPanel) {
JPanel chessPanel = new JPanel(new BorderLayout());
chessPanel.setBackground(new Color(0x1b263b));
public JPanel chessPanel(JPanel panel) {
JPanel chessPanel = new JPanel(new GridBagLayout());
GridBagConstraints board = new GridBagConstraints();
chessPanel.setBackground(new Color(0x1b263b));
board.gridx = 0;
board.gridy = 0;
board.weightx = 0.7;
board.weighty = 1.0;
board.insets = new Insets(0, 0, 0, 0);
//oben, links, unten, rechts
board.fill = GridBagConstraints.BOTH;
chessPanel.add(panel);
// Button unten rechts
flipBoardButton = new JButton("⇵");
flipBoardButton.setPreferredSize(new Dimension(70, 70));
flipBoardButton.setFont(new Font("SansSerif", Font.BOLD, 40));
flipBoardButton.setBackground(new Color(0x5500ff));
flipBoardButton.setForeground(Color.WHITE);
flipBoardButton.setFocusPainted(false);
// --- Eröffnungslabel oben ---
openingLabel = new JLabel("Eröffnung: unbekannt", SwingConstants.CENTER);
openingLabel.setFont(new Font("SansSerif", Font.BOLD, 24));
openingLabel.setForeground(Color.WHITE);
openingLabel.setOpaque(true);
openingLabel.setBackground(new Color(0x283655));
openingLabel.setPreferredSize(new Dimension(800, 50));
chessPanel.add(openingLabel, BorderLayout.NORTH);
GridBagConstraints btn = new GridBagConstraints();
btn.gridx = 0;
btn.gridy = 1;
btn.weightx = 0.0;
btn.weighty = 0.0;
btn.anchor = GridBagConstraints.SOUTHEAST;
btn.insets = new Insets(10, 0, 0, 0);
// --- Board in ein zentriertes Panel mit fixer Größe ---
JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
centerPanel.setOpaque(false);
centerPanel.add(boardPanel);
centerPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
int size = Math.min(centerPanel.getWidth(), centerPanel.getHeight());
boardPanel.setPreferredSize(new Dimension(size, size));
boardPanel.revalidate();
}
});
chessPanel.add(centerPanel, BorderLayout.CENTER);
// --- Dummy-Buffer für WEST und EAST ---
chessPanel.add(Box.createRigidArea(new Dimension(40, 0)), BorderLayout.WEST);
chessPanel.add(Box.createRigidArea(new Dimension(40, 0)), BorderLayout.EAST);
// --- Buttonleiste unten bauen ---
JPanel buttonRow = new JPanel();
buttonRow.setOpaque(false);
buttonRow.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT, 10, 0));
flipBoardButton = new JButton("⇵");
flipBoardButton.setPreferredSize(new Dimension(70, 70));
flipBoardButton.setFont(new Font("SansSerif", Font.BOLD, 40));
flipBoardButton.setBackground(new Color(0x5500ff));
flipBoardButton.setForeground(Color.WHITE);
flipBoardButton.setFocusPainted(false);
buttonRow.add(flipBoardButton);
chessPanel.add(buttonRow, BorderLayout.SOUTH);
return chessPanel;
chessPanel.add(flipBoardButton, btn);
return chessPanel;
}
public JPanel statsPanel() {
@ -264,11 +239,6 @@ public class PgnGui {
this.isFlipped = flipped;
}
public void setOpeningLabel(String text) {
openingLabel.setText("Eröffnung: " + text);
}
public JButton getBtnFirst() { return btnFirst; }
public JButton getBtnPrev() { return btnPrev; }
public JButton getBtnNext() { return btnNext; }

View File

@ -0,0 +1,36 @@
package de.hs_mannheim.informatik.chess.test;
import junit.framework.*;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static TestSuite suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@ -1,222 +0,0 @@
package de.hs_mannheim.informatik.chess.test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.List;
import de.hs_mannheim.informatik.chess.model.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ModelTest {
private ChessEngine engine;
@BeforeEach
public void setUp() {
engine = new ChessEngine(); // Echte Instanz!
}
@Test
public void ErkenntObZugLegalOderIllegal()
{
assertTrue(engine.move(new MoveDTO(6, 4, 4, 4)));
assertFalse(engine.move(new MoveDTO(7, 0, 5, 1)));
}
@Test
public void GibtLegaleMovesAn() {
List<MoveDTO> mvs = new ArrayList<>();
mvs.add(new MoveDTO(6,4,5,4));
mvs.add(new MoveDTO(6,4,4,4));
List<MoveDTO> moves = engine.getLegalDestinations("E2");
assertEquals(2, moves.size());
assertTrue(moves.stream().anyMatch(m -> m.getToRow() == 5 && m.getToCol() == 4));
assertTrue(moves.stream().anyMatch(m -> m.getToRow() == 4 && m.getToCol() == 4));
}
@Test //Stichprobenartige Kontrolle ob richtige Figur an richtiger Stelle
public void BoardWirdRichtigAufgebaut() {
BoardDTO board = engine.getBoardAsDTO();
PieceDTO a1 = board.getBoard()[7][0];
assertEquals("ROOK", a1.getType());
assertEquals("WHITE", a1.getColor());
PieceDTO e1 = board.getBoard()[7][4];
assertEquals("KING", e1.getType());
assertEquals("WHITE", e1.getColor());
PieceDTO a8 = board.getBoard()[0][0];
assertEquals("ROOK", a8.getType());
assertEquals("BLACK", a8.getColor());
PieceDTO e8 = board.getBoard()[0][4];
assertEquals("KING", e8.getType());
assertEquals("BLACK", e8.getColor());
PieceDTO e2 = board.getBoard()[6][4];
assertEquals("PAWN", e2.getType());
assertEquals("WHITE", e2.getColor());
PieceDTO d7 = board.getBoard()[1][3];
assertEquals("PAWN", d7.getType());
assertEquals("BLACK", d7.getColor());
PieceDTO e4 = board.getBoard()[4][4];
assertNull(e4);
PieceDTO d5 = board.getBoard()[3][3];
assertNull(d5);
}
@Test
public void speichertMovesRichtigGruppiert() {
engine.move(new MoveDTO(6, 6, 4, 6));
engine.move(new MoveDTO(1, 4, 3, 4));
engine.move(new MoveDTO(7, 6, 5, 5)); //Züge um das speichern zu testen
engine.move(new MoveDTO(0, 1, 2, 2));
engine.move(new MoveDTO(7, 1, 5, 2));
List<String> gruppiertGespeichert = engine.getMoveListStringsGrouped(); //Moves in Liste gespeichert um zu testen
assertTrue(gruppiertGespeichert.size() >= 3, "Zu wenige gespeicherte Gruppen");
assertTrue(gruppiertGespeichert.get(0).startsWith("1."));
assertTrue(gruppiertGespeichert.get(1).startsWith("2."));
assertTrue(gruppiertGespeichert.get(2).startsWith("3."));
for (int i = 0; i < gruppiertGespeichert.size(); i++) {
String[] parts = gruppiertGespeichert.get(i).split(" ");
if (i == gruppiertGespeichert.size() - 1) {
assertTrue(parts.length == 2 || parts.length == 3);
} else {
assertEquals(3, parts.length);
}
}
}
@Test
public void erkenntMattKorrekt() {
assertFalse(engine.isMated()); //<--Test, dass nicht immer alles einfach Matt ist
engine.setPositionFromFEN("7k/6Q1/5K2/8/8/8/8/8 b - - 0 1"); //<--Matt position vorbereiten
System.out.println("Aktueller Spieler: " + engine.getCurrentPlayer());
System.out.println("isMated(): " + engine.isMated());
assertEquals("BLACK", engine.getCurrentPlayer());
assertTrue(engine.isMated()); //<Test ob nun spieler Matt ist
}
@Test
public void erkenntPattKorrekt() {
assertFalse(engine.isStalemate());
engine.setPositionFromFEN("7k/5Q2/6K1/8/8/8/8/8 b - - 0 1");
System.out.println("Aktueller Spieler: " + engine.getCurrentPlayer());
System.out.println("isStalemate(): " + engine.isStalemate());
assertEquals("BLACK", engine.getCurrentPlayer());
assertTrue(engine.isStalemate());
}
@Test
public void erkenntUnentschieden() {
assertFalse(engine.isDraw());
engine.setPositionFromFEN("8/8/8/8/8/8/8/4K2k w - - 0 1"); // nur zwei Könige
assertTrue(engine.isDraw());
}
@Test
public void MethodeGibtRichtigeFigurZurück() {
String type = "KING";
String color= "WHITE";
PieceDTO test = engine.getPieceAt("E1");
assertEquals(type, test.getType());
assertEquals(color, test.getColor());
}
@Test
public void MethodeGibtRichtigenPlayerZurück() {
assertEquals("WHITE", engine.getCurrentPlayer());
engine.move(new MoveDTO(6, 4, 4, 4));
assertEquals("BLACK", engine.getCurrentPlayer());
}
@Test
public void MethodeSetztBoardRichtigzurück() {
engine.move(new MoveDTO(6,4,4,4)); // e2-e4
engine.move(new MoveDTO(1,4,3,4)); // e7-e5
engine.setPositionToMoveIndex(1);
PieceDTO pawn = engine.getPieceAt("E4");
assertNotNull(pawn);
assertEquals("PAWN", pawn.getType());
assertNull(engine.getPieceAt("E5"));
assertEquals(1, engine.getCurrentMoveIndex());
}
@Test
public void FigurZurQueenBefördernklappt() {
engine.setPositionFromFEN("8/P7/8/8/8/8/8/k6K w - - 0 1"); // Weißer Bauer auf a7, Weiß am Zug
boolean moved = engine.moveWithPromotion(new MoveDTO(1, 0, 0, 0), "QUEEN"); // a7-a8=Dame
assertTrue(moved);
PieceDTO piece = engine.getPieceAt("A8");
assertEquals("QUEEN", piece.getType());
assertEquals("WHITE", piece.getColor());
}
@Test
public void fenAufbauFunktioniert() {
// Beispiel-FEN: Weißer König auf e1, schwarze Dame auf d8, schwarzer Bauer auf a7, Rest leer
String fen = "3q4/p7/8/8/8/8/8/4K3 w - - 0 1";
engine.setPositionFromFEN(fen);
// Kontrolliere schwarze Dame auf d8 (0,3)
PieceDTO d8 = engine.getPieceAt("D8");
assertEquals("QUEEN", d8.getType());
assertEquals("BLACK", d8.getColor());
// Kontrolliere schwarzen Bauern auf a7 (1,0)
PieceDTO a7 = engine.getPieceAt("A7");
assertEquals("PAWN", a7.getType());
assertEquals("BLACK", a7.getColor());
// Kontrolliere weißen König auf e1 (7,4)
PieceDTO e1 = engine.getPieceAt("E1");
assertEquals("KING", e1.getType());
assertEquals("WHITE", e1.getColor());
// Leeres Feld testen: e2 (6,4)
PieceDTO e2 = engine.getPieceAt("E2");
assertNull(e2);
// Leeres Feld testen: h5 (3,7)
PieceDTO h5 = engine.getPieceAt("H5");
assertNull(h5);
}
@Test
public void timerWirdRichtigErstellt() {
engine.initTimers(5, 30);
assertEquals(330, engine.getWhiteTimer().getSecondsLeft());
assertEquals(330, engine.getBlackTimer().getSecondsLeft());
}
}

View File

@ -1,102 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.hs-mannheim.informatik.schach</groupId>
<artifactId>schach</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>schach</name>
<description>A simple schach.</description>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<!-- Schachlib (bhlangonijr) -->
<dependency>
<groupId>com.github.bhlangonijr</groupId>
<artifactId>chesslib</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<!-- Mockito damit man Controller und Gui besser testen kann-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.6.1</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>