diff --git a/quellen b/quellen index 246b419..3733f13 100644 --- a/quellen +++ b/quellen @@ -1,2 +1,2 @@ JFileChoser in UI: (mit GPT) -Prompt: "Wie kann ich in swing in java Files aus einem Explorer auswählen?". \ No newline at end of file +Prompt: "Wie kann ich in swing in java Files aus einem Explorer auswählen und speichern?". \ No newline at end of file diff --git a/src/main/java/de/mannheim/th/chess/App.java b/src/main/java/de/mannheim/th/chess/App.java index 1e90163..297b276 100644 --- a/src/main/java/de/mannheim/th/chess/App.java +++ b/src/main/java/de/mannheim/th/chess/App.java @@ -20,7 +20,6 @@ public class App { * @param args */ public static void main(String[] args) { - logger.info("Hello World."); userinterface = new MainFrame(); } } diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonAufgebenListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonAufgebenListener.java new file mode 100644 index 0000000..cd14562 --- /dev/null +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonAufgebenListener.java @@ -0,0 +1,22 @@ +package de.mannheim.th.chess.controller; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JFrame; + +public class ButtonAufgebenListener extends JFrame implements ActionListener{ + + private static final long serialVersionUID = 1L; + + public ButtonAufgebenListener() { + + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonFileLoaderListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonFileLoaderListener.java new file mode 100644 index 0000000..29c8af3 --- /dev/null +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonFileLoaderListener.java @@ -0,0 +1,54 @@ +package de.mannheim.th.chess.controller; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import de.mannheim.th.chess.ui.ModeSelectionFrame; + +public class ButtonFileLoaderListener implements ActionListener{ + + private ModeSelectionFrame msf; + + public ButtonFileLoaderListener(ModeSelectionFrame msf) { + this.msf = msf; + + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + JFileChooser dateiWaehler = new JFileChooser(); + JFrame jfFile = new JFrame(); + int auswahl = dateiWaehler.showOpenDialog(jfFile); + + if (auswahl == JFileChooser.APPROVE_OPTION) { + File ausgewaehlteDatei = dateiWaehler.getSelectedFile(); + JOptionPane.showMessageDialog(jfFile, "Gewählte Datei:\n" + ausgewaehlteDatei.getAbsolutePath()); + + try { + BufferedReader br = new BufferedReader(new FileReader(ausgewaehlteDatei)); + + msf.setFen(br.readLine()); + + } catch (FileNotFoundException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + } + +} diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonFileSaverListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonFileSaverListener.java new file mode 100644 index 0000000..2dc2860 --- /dev/null +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonFileSaverListener.java @@ -0,0 +1,61 @@ +package de.mannheim.th.chess.controller; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.github.bhlangonijr.chesslib.move.Move; + +import de.mannheim.th.chess.App; +import de.mannheim.th.chess.domain.Game; + +public class ButtonFileSaverListener implements ActionListener{ + + private static final Logger logger = LogManager.getLogger(App.class); + + private Game g; + private JFrame sf; + + public ButtonFileSaverListener(JFrame sf, Game g) { + this.sf = sf; + this.g = g; + } + + @Override + public void actionPerformed(ActionEvent e) { + + logger.info("Spiel wird gespeichert."); + + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new File(System.getProperty("user.home") + "/Documents")); + + chooser.setDialogTitle("Datei speichern"); + int userSelection = chooser.showSaveDialog(sf); + + if (userSelection == JFileChooser.APPROVE_OPTION) { + File fileToSave = chooser.getSelectedFile(); + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileToSave))) { + + writer.write(g.getFen()); + + logger.info(g.getFen()); + } catch (IOException e1) { + e1.printStackTrace(); + } + } else { + logger.info("Speichern fehlgeschlagen."); + } + } + +} diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonMovePieceListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonMovePieceListener.java index fab0dc3..83de36c 100644 --- a/src/main/java/de/mannheim/th/chess/controller/ButtonMovePieceListener.java +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonMovePieceListener.java @@ -39,5 +39,10 @@ public class ButtonMovePieceListener implements ActionListener { this.sf.setBoardMode(BoardMode.normal); this.sf.setCursor(null); this.sf.erstelleBrett(); + + if (game.getLastMove() != null) { + + sf.aktualisiereAusgabe(); + } } } diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonToNormalListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonToNormalListener.java index c4261de..ce83e28 100644 --- a/src/main/java/de/mannheim/th/chess/controller/ButtonToNormalListener.java +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonToNormalListener.java @@ -3,6 +3,7 @@ package de.mannheim.th.chess.controller; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import de.mannheim.th.chess.domain.Game; import de.mannheim.th.chess.ui.SpielFrame; import de.mannheim.th.chess.ui.SpielFrame.BoardMode; @@ -19,6 +20,7 @@ public class ButtonToNormalListener implements ActionListener { this.sf.setSelectedSquare(null); this.sf.setCursor(null); this.sf.erstelleBrett(); + } } diff --git a/src/main/java/de/mannheim/th/chess/controller/ButtonUndoMoveListener.java b/src/main/java/de/mannheim/th/chess/controller/ButtonUndoMoveListener.java new file mode 100644 index 0000000..6ecbca8 --- /dev/null +++ b/src/main/java/de/mannheim/th/chess/controller/ButtonUndoMoveListener.java @@ -0,0 +1,70 @@ +package de.mannheim.th.chess.controller; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.mannheim.th.chess.App; +import de.mannheim.th.chess.domain.Game; +import de.mannheim.th.chess.ui.SpielFrame; +import de.mannheim.th.chess.ui.SpielFrame.BoardMode; + +public class ButtonUndoMoveListener implements ActionListener { + + private static final Logger logger = LogManager.getLogger(App.class); + + private SpielFrame sf; + private Game game; + + public ButtonUndoMoveListener(SpielFrame sf, Game game) { + this.sf = sf; + this.game = game; + } + + @Override + public void actionPerformed(ActionEvent e) { + // TODO Auto-generated method stub + + Object source = e.getSource(); + + if (sf.getMode() != BoardMode.normal || !game.movesNotNull()) { + return; + } + + if (source == sf.getUndo()) { // Spieler 2 drückt seinen Button + if (sf.getUndo().getText().equals("Zug zurücknehmen") && game.getActivePlayer() == 1) { + sf.getUndo2().setText("Zurücknahme genehmigen?"); + sf.getUndo2().setEnabled(true); + logger.info("Spieler 2 hat zurücknahme angefordert."); + } else if (sf.getUndo().getText().equals("Zurücknahme genehmigen?")) { + logger.info("Zug zurücknehmen wurde von Spieler 2 genehmigt."); + sf.getUndo().setText("Zug zurücknehmen"); + sf.getUndo2().setText("Zug zurücknehmen"); + sf.getUndo2().setEnabled(false); + game.undo(); + sf.getClock().switchClock(); + sf.deleteLastAusgabe(); + sf.erstelleBrett(); + } + } else if (source == sf.getUndo2()) { // Spieler 1 drückt seinen Button + if (sf.getUndo2().getText().equals("Zug zurücknehmen") && game.getActivePlayer() == 2) { + sf.getUndo().setText("Zurücknahme genehmigen?"); + sf.getUndo().setEnabled(true); + logger.info("Spieler 1 hat zurücknahme angefordert."); + } else if (sf.getUndo2().getText().equals("Zurücknahme genehmigen?")) { + logger.info("Zug zurücknehmen wurde von Spieler 1 genehmigt."); + sf.getUndo2().setText("Zug zurücknehmen"); + sf.getUndo().setText("Zug zurücknehmen"); + sf.getUndo().setEnabled(false); + game.undo(); + sf.getClock().switchClock(); + sf.deleteLastAusgabe(); + sf.erstelleBrett(); + } + } + + } + +} diff --git a/src/main/java/de/mannheim/th/chess/domain/Game.java b/src/main/java/de/mannheim/th/chess/domain/Game.java index 71326db..94332ba 100644 --- a/src/main/java/de/mannheim/th/chess/domain/Game.java +++ b/src/main/java/de/mannheim/th/chess/domain/Game.java @@ -3,6 +3,9 @@ package de.mannheim.th.chess.domain; import java.util.List; import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.Piece; import com.github.bhlangonijr.chesslib.Rank; @@ -12,6 +15,8 @@ import com.github.bhlangonijr.chesslib.move.Move; import com.github.bhlangonijr.chesslib.move.MoveList; import com.github.bhlangonijr.chesslib.pgn.PgnHolder; +import de.mannheim.th.chess.App; +import de.mannheim.th.chess.ui.SpielFrame; import de.mannheim.th.chess.utl.Clock; /** @@ -20,21 +25,44 @@ import de.mannheim.th.chess.utl.Clock; */ public class Game { + private static final Logger logger = LogManager.getLogger(App.class); + private Board board; private Clock clock; + private SpielFrame sp; + private String modus; + private boolean rotieren, zuruecknahme; private MoveList movelist; + public Game() { + + this.board = new Board(); + this.movelist = new MoveList(); + clock = new Clock("blitz"); + clock.start(); + } + /** * Conststructs a new standard GameBoard. */ - public Game() { + public Game(String modus, boolean rotieren, boolean zuruecknahme, String fen) { + this.modus = modus; + this.rotieren = rotieren; + this.zuruecknahme = zuruecknahme; + this.board = new Board(); + if (fen == null) + fen = board.getFen(); + + this.board.loadFromFen(fen); + this.movelist = new MoveList(); - clock = new Clock("blitz"); - clock.start(); + clock = new Clock(modus); + + sp = new SpielFrame(this); } @@ -66,6 +94,7 @@ public class Game { this.board.loadFromFen(fen); this.movelist = new MoveList(); + // this.sp = new SpielFrame(); // this.clockPlayer1 = new Clock(); // this.clockPlayer2 = new Clock(); @@ -82,6 +111,18 @@ public class Game { clock.pressClock(); } + /** + * Plays the move on the board and adds it to the movelist + * + * @param origin The square from wich it moves from. + * @param desination The square where it will move to. + */ + + public void undo() { + this.board.undoMove(); + this.movelist.removeLast(); + } + /** * Plays the move on the board and adds it to the movelist * @@ -118,9 +159,7 @@ public class Game { * @return A list of legal moves that originate from the specified square. */ public List getLegalMoves(Square square) { - return this.board.legalMoves().stream() - .filter(move -> move.getFrom() == square) - .collect(Collectors.toList()); + return this.board.legalMoves().stream().filter(move -> move.getFrom() == square).collect(Collectors.toList()); } @@ -139,10 +178,7 @@ public class Game { * @return a List of Square objects representing all legal moveable squares. */ public List getAllLegalMoveableSquares() { - return this.board.legalMoves().stream() - .map(move -> move.getFrom()) - .distinct() - .collect(Collectors.toList()); + return this.board.legalMoves().stream().map(move -> move.getFrom()).distinct().collect(Collectors.toList()); } /** @@ -194,6 +230,43 @@ public class Game { playMove(promotionMove); } + public void setModus(String modus) { + this.modus = modus; + } + + public Clock getClock() { + return this.clock; + } + + public boolean isZuruecknahme() { + return zuruecknahme; + } + + public boolean movesNotNull() { + if (movelist.getLast() != null) { + return true; + } + return false; + } + + public String getFen() { + return this.board.getFen(); + } + + public Move getLastMove() { + logger.info(this.movelist.getLast().toString()); + return this.movelist.getLast(); + } + + public MoveList getMoveList() { + return this.movelist; + } + + public Board getBoard() { + // TODO Auto-generated method stub + return this.board; + } + public String toFEN() { board.toString(); return board.getFen(); @@ -202,4 +275,12 @@ public class Game { public Square getSelectedSquare() { return this.getSelectedSquare(); } + + public String getUnicodeFromMove(Move move) { + return board.getPiece(move.getTo()).getFanSymbol().toUpperCase(); + } + + public Square getSelectedSquare() { + return this.getSelectedSquare(); + } } diff --git a/src/main/java/de/mannheim/th/chess/ui/GameWindow.java b/src/main/java/de/mannheim/th/chess/ui/GameWindow.java index d220a5c..7fa393f 100644 --- a/src/main/java/de/mannheim/th/chess/ui/GameWindow.java +++ b/src/main/java/de/mannheim/th/chess/ui/GameWindow.java @@ -7,7 +7,7 @@ import de.mannheim.th.chess.domain.Game; */ public class GameWindow{ - private Game gamelogic = new Game(); + //private Game gamelogic = new Game(); public GameWindow() { diff --git a/src/main/java/de/mannheim/th/chess/ui/MainFrame.java b/src/main/java/de/mannheim/th/chess/ui/MainFrame.java index fc5a437..73c5010 100644 --- a/src/main/java/de/mannheim/th/chess/ui/MainFrame.java +++ b/src/main/java/de/mannheim/th/chess/ui/MainFrame.java @@ -3,26 +3,28 @@ package de.mannheim.th.chess.ui; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.mannheim.th.chess.App; + import javax.swing.JLabel; -import javax.swing.JOptionPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; -import java.util.ArrayList; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; -import javax.swing.JFileChooser; import java.awt.Component; import java.awt.Font; import java.awt.Color; public class MainFrame extends JFrame { - - private ArrayList spiele = new ArrayList<>(); + + private static final Logger logger = LogManager.getLogger(App.class); private static final long serialVersionUID = 1L; private JPanel contentPane; @@ -76,8 +78,7 @@ public class MainFrame extends JFrame { @Override public void actionPerformed(ActionEvent e) { - SpielFrame sp = new SpielFrame(); - spiele.add(sp); + ModeSelectionFrame ms = new ModeSelectionFrame(); } @@ -86,36 +87,7 @@ public class MainFrame extends JFrame { contentPane.add(Box.createVerticalStrut(15)); - JButton btnNewButton_1 = new JButton("Vergangenes Spiel laden"); - - btnNewButton_1.setBackground(Color.LIGHT_GRAY); - btnNewButton_1.setForeground(Color.BLACK); - btnNewButton_1.setFont(new Font("Tahoma", Font.BOLD, 16)); - btnNewButton_1.setAlignmentX(Component.CENTER_ALIGNMENT); - btnNewButton_1.addActionListener(new ActionListener() { - - - @Override - public void actionPerformed(ActionEvent e) { - JFileChooser dateiWaehler = new JFileChooser(); - JFrame jfFile = new JFrame(); - int auswahl = dateiWaehler.showOpenDialog(jfFile); - - if (auswahl == JFileChooser.APPROVE_OPTION) { - File ausgewaehlteDatei = dateiWaehler.getSelectedFile(); - JOptionPane.showMessageDialog(jfFile, "Gewählte Datei:\n" + ausgewaehlteDatei.getAbsolutePath()); - - // Uebergabe zu Logik zum extrahieren der Daten - } - } - - }); - - contentPane.add(btnNewButton_1); - - contentPane.add(Box.createVerticalStrut(15)); - - JButton btnNewButton_2 = new JButton("Spiel beenden"); + JButton btnNewButton_2 = new JButton("App beenden"); btnNewButton_2.setBackground(Color.LIGHT_GRAY); btnNewButton_2.setForeground(Color.BLACK); diff --git a/src/main/java/de/mannheim/th/chess/ui/ModeSelectionFrame.java b/src/main/java/de/mannheim/th/chess/ui/ModeSelectionFrame.java new file mode 100644 index 0000000..fb15899 --- /dev/null +++ b/src/main/java/de/mannheim/th/chess/ui/ModeSelectionFrame.java @@ -0,0 +1,137 @@ +package de.mannheim.th.chess.ui; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import javax.swing.*; +import javax.swing.border.EmptyBorder; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import de.mannheim.th.chess.App; +import de.mannheim.th.chess.controller.ButtonFileLoaderListener; +import de.mannheim.th.chess.domain.Game; + +public class ModeSelectionFrame extends JFrame { + + private static final Logger logger = LogManager.getLogger(App.class); + + private static final long serialVersionUID = 1L; + private final JPanel contentPane; + private final ArrayList spiele = new ArrayList<>(); + private String fen; + + public ModeSelectionFrame() { + // Frame-Eigenschaften + setTitle("Modusauswahl"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 500, 500); + setResizable(true); + setAlwaysOnTop(true); + + // Panel konfigurieren + contentPane = new JPanel(); + contentPane.setBackground(new Color(90, 90, 90)); + contentPane.setBorder(new EmptyBorder(20, 20, 20, 20)); + contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); + setContentPane(contentPane); + + // Überschrift + JLabel jl = new JLabel("Welchen Modus wollen Sie spielen?"); + jl.setFont(new Font("Calibri", Font.BOLD, 20)); + jl.setForeground(Color.BLACK); + jl.setAlignmentX(Component.CENTER_ALIGNMENT); + contentPane.add(jl); + contentPane.add(Box.createVerticalStrut(15)); + + // Modusauswahl + String[] modi = {"Blitz", "Schnellschach", "Klassisch"}; + JComboBox jcb1 = new JComboBox<>(modi); + jcb1 .setMaximumSize(new Dimension(150, 30)); + jcb1 .setAlignmentX(Component.CENTER_ALIGNMENT); + contentPane.add(jcb1 ); + contentPane.add(Box.createVerticalStrut(15)); + + // Spielbrettdrehen + JLabel jl2 = new JLabel("Soll das Spielbrett nach jedem Zug gedreht werden?"); + jl2 .setFont(new Font("Calibri", Font.BOLD, 20)); + jl2 .setForeground(Color.BLACK); + jl2 .setAlignmentX(Component.CENTER_ALIGNMENT); + contentPane.add(jl2 ); + + JCheckBox jb1 = new JCheckBox(); + jb1.setOpaque(false); + jb1.setFocusPainted(false); + jb1.setForeground(Color.BLACK); + jb1 .setAlignmentX(Component.CENTER_ALIGNMENT); + jb1 .setMaximumSize(new Dimension(30, 30)); + contentPane.add(jb1 ); + contentPane.add(Box.createVerticalStrut(15)); + + // Zurücknahmeoption + JLabel jl3 = new JLabel("Sollen Zurücknahmen erlaubt sein?"); + jl3.setFont(new Font("Calibri", Font.BOLD, 20)); + jl3.setForeground(Color.BLACK); + jl3.setAlignmentX(Component.CENTER_ALIGNMENT); + contentPane.add(jl3); + + JCheckBox jb2 = new JCheckBox(); + jb2.setOpaque(false); + jb2.setFocusPainted(false); + jb2.setForeground(Color.BLACK); + jb2.setAlignmentX(Component.CENTER_ALIGNMENT); + jb2.setMaximumSize(new Dimension(30, 30)); + contentPane.add(jb2); + + contentPane.add(Box.createVerticalStrut(15)); + + JButton btnNewButton_1 = new JButton("Vergangenes Spiel laden"); + + btnNewButton_1.setBackground(Color.LIGHT_GRAY); + btnNewButton_1.setForeground(Color.BLACK); + btnNewButton_1.setFont(new Font("Tahoma", Font.BOLD, 16)); + btnNewButton_1.setAlignmentX(Component.CENTER_ALIGNMENT); + btnNewButton_1.addActionListener(new ButtonFileLoaderListener(this)); + + contentPane.add(btnNewButton_1); + + contentPane.add(Box.createVerticalStrut(25)); + + // Spiel starten Button + JButton btnNewButton = new JButton("Spiel starten"); + btnNewButton .setBackground(Color.LIGHT_GRAY); + btnNewButton .setForeground(Color.BLACK); + btnNewButton .setFont(new Font("Tahoma", Font.BOLD, 16)); + btnNewButton .setAlignmentX(Component.CENTER_ALIGNMENT); + contentPane.add(btnNewButton ); + + // Button-Listener + btnNewButton .addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String modus = (String) jcb1.getSelectedItem(); + boolean rotieren = jb1.isSelected(); + boolean zuruecknahme = jb2.isSelected(); + + Game game = new Game(modus, rotieren, zuruecknahme, fen); + + spiele.add(game); + + dispose(); + } + }); + + setVisible(true); + } + + public void setFen(String fen) { + this.fen = fen; + } +} diff --git a/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java b/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java index e9984df..665821b 100644 --- a/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java +++ b/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java @@ -6,27 +6,37 @@ import org.apache.logging.log4j.Logger; import com.github.bhlangonijr.chesslib.Piece; import com.github.bhlangonijr.chesslib.Square; import com.github.bhlangonijr.chesslib.move.Move; +import com.github.bhlangonijr.chesslib.move.MoveList; import de.mannheim.th.chess.App; import de.mannheim.th.chess.domain.Game; +import de.mannheim.th.chess.utl.Clock; +import de.mannheim.th.chess.controller.ButtonAufgebenListener; +import de.mannheim.th.chess.controller.ButtonFileSaverListener; import de.mannheim.th.chess.controller.ButtonMovePieceListener; import de.mannheim.th.chess.controller.ButtonSelectPieceListener; import de.mannheim.th.chess.controller.ButtonToNormalListener; +import de.mannheim.th.chess.controller.ButtonUndoMoveListener; -import java.awt.EventQueue; import java.awt.Font; import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JTextArea; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -40,7 +50,10 @@ public class SpielFrame extends JFrame { private ArrayList buttons = new ArrayList<>(); private HashMap belegungen = new HashMap<>(); private JPanel panelLinks, panelRechts, contentPane; + private JButton undo, undo2; + private JTextArea ausgabe; private Game game; + private Clock clock; private BoardMode mode; private Square selectedSquare; @@ -52,12 +65,15 @@ public class SpielFrame extends JFrame { /** * Create the frame. */ - public SpielFrame() { + public SpielFrame(Game game) { + + this.game = game; + this.clock = game.getClock(); + this.clock.start(); - game = new Game(); mode = BoardMode.normal; - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setBounds(100, 100, 1920, 1080); setTitle("Schach"); setAlwaysOnTop(true); @@ -73,30 +89,30 @@ public class SpielFrame extends JFrame { // Rechtes Panel für Steuerung oder zusätzliche Eingaben panelRechts = new JPanel(); - panelRechts.setBackground(Color.LIGHT_GRAY); + panelRechts.setBackground(new Color(90, 90, 90)); + panelRechts.setLayout(new BoxLayout(panelRechts, BoxLayout.Y_AXIS)); + + // Panel für alle Eingaben von Player 2 + panelRechts.add(getUiPlayerTwo()); + + // Panel für Statistikanzeigen + panelRechts.add(getUiStatistik()); + + // Panel für alle Eingaben von Player 1 + panelRechts.add(getUiPlayerOne()); // JSplitPane horizontal (linke und rechte Hälfte) JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panelLinks, panelRechts); - splitPane.setResizeWeight(0.70); - splitPane.setDividerSize(5); + splitPane.setResizeWeight(0.75); + splitPane.setBackground(Color.BLACK); + splitPane.setDividerSize(1); splitPane.setEnabled(false); contentPane.add(splitPane, BorderLayout.CENTER); + setVisible(true); } - public void setBoardMode(BoardMode bm) { - this.mode = bm; - } - - public void setSelectedSquare(Square sq) { - this.selectedSquare = sq; - } - - public HashMap getBelegung() { - return this.belegungen; - } - /** * Erstellt alle Buttons und fügt sie dem Frame hinzu. */ @@ -111,32 +127,6 @@ public class SpielFrame extends JFrame { panelLinks.revalidate(); panelLinks.repaint(); - // // Bild laden und Cursor im gesamten Frame setzen - // Image image = Toolkit.getDefaultToolkit().getImage(pfad); - // Image scaled = image.getScaledInstance(32, 32, Image.SCALE_SMOOTH); - // Cursor figurCursor = Toolkit.getDefaultToolkit().createCustomCursor(scaled, - // new Point(0, 0), - // "figurCursor"); - // setCursor(figurCursor); - - // }else - // { - // - // // wenn gerade Figur ausgewählt wird... - // buttonChoosed = (JButton) e.getSource(); - // symbolChoosed = belegungen.get(buttonChoosed); - // // System.out.println(symbolChoosed+" wurde gewählt."); - // // setzt cursor auf spielfigur für die animation - // String pfad = "src/main/resources/" + (int) symbolChoosed.toCharArray()[2] + - // ".png"; - // - // // Bild laden und Cursor im gesamten Frame setzen - // Image image = Toolkit.getDefaultToolkit().getImage(pfad); - // Image scaled = image.getScaledInstance(32, 32, Image.SCALE_SMOOTH); - // Cursor figurCursor = Toolkit.getDefaultToolkit().createCustomCursor(scaled, - // new Point(0, 0), - // "figurCursor"); - // setCursor(figurCursor); } private int mirrowedGrid(int i) { @@ -181,6 +171,7 @@ public class SpielFrame extends JFrame { * with new blank ones. */ private void clearButtons() { + buttons.clear(); panelLinks.removeAll(); @@ -207,10 +198,10 @@ public class SpielFrame extends JFrame { for (int i = 0; i < 64; i++) { JButton b = buttons.get(i); if ((i / 8 + i % 8) % 2 == 0) { - logger.info("Helles Feld erstellt." + i); + // logger.info("Helles Feld erstellt." + i); b.setBackground(new Color(90, 90, 90)); } else { - logger.info("Dunkles Feld erstellt." + i); + // logger.info("Dunkles Feld erstellt." + i); b.setBackground(new Color(65, 65, 65)); } } @@ -225,6 +216,7 @@ public class SpielFrame extends JFrame { switch (this.mode) { case BoardMode.normal: + selectables = game.getAllLegalMoveableSquares(); for (Square square : selectables) { @@ -241,7 +233,7 @@ public class SpielFrame extends JFrame { JButton s = buttons.get(mirrowedGrid(selectedSquare.ordinal())); s.setEnabled(true); s.setBackground(new Color(165, 42, 42)); - s.addActionListener(new ButtonToNormalListener(this)); // cancel action + s.addActionListener(new ButtonToNormalListener(this)); selectables = game.getLegalMoveableSquares(selectedSquare); @@ -320,4 +312,248 @@ public class SpielFrame extends JFrame { frame.setVisible(true); } + public int showPromotion() { + final int[] result = { -1 }; + + JDialog dialog = new JDialog(this, "Wähle eine Figur", true); + dialog.setLayout(new GridLayout(2, 2)); + dialog.setSize(300, 200); + + int[] pictures = { 81, 82, 66, 78, 113, 114, 98, 110 }; + + for (int i = 0; i < 4; i++) { + int index = (game.getActivePlayer() - 1) * 4 + i; + JButton jb = new JButton(); + jb.setIcon(new ImageIcon("src/main/resources/" + pictures[index] + ".png")); + int selectedPiece = index; + jb.addActionListener(e -> { + System.out.println("Test"); + result[0] = selectedPiece; + dialog.dispose(); + }); + dialog.add(jb); + } + + dialog.setLocationRelativeTo(null); + dialog.setVisible(true); + + return result[0]; + } + + private JPanel getUiPlayerTwo() { + + JPanel playerTwo = new JPanel(); + playerTwo.setBackground(new Color(90, 90, 90)); + playerTwo.setLayout(new BoxLayout(playerTwo, BoxLayout.Y_AXIS)); + + playerTwo.add(Box.createVerticalStrut(15)); + + JLabel pl2 = new JLabel("Player 2:"); + pl2.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0)); + pl2.setFont(new Font("Calibri", Font.BOLD, 35)); + pl2.setForeground(Color.BLACK); + pl2.setAlignmentX(Component.CENTER_ALIGNMENT); + playerTwo.add(pl2); + + playerTwo.add(Box.createVerticalStrut(10)); + + JLabel clock1 = clock.getClock2(); + playerTwo.add(clock1); + + playerTwo.add(Box.createVerticalStrut(10)); + + // Button zurücknahme und aufgeben für Player 2 + JPanel aufgebenUndo = new JPanel(); + aufgebenUndo.setBackground(new Color(90, 90, 90)); + aufgebenUndo.setLayout(new BoxLayout(aufgebenUndo, BoxLayout.X_AXIS)); + + if (game.isZuruecknahme()) { + undo = new JButton("Zug zurücknehmen"); + undo.setBackground(Color.LIGHT_GRAY); + undo.setForeground(Color.BLACK); + undo.setFont(new Font("Tahoma", Font.BOLD, 16)); + undo.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(undo); + + // Button-Listener + undo.addActionListener(new ButtonUndoMoveListener(this, this.game)); + } + + aufgebenUndo.add(Box.createHorizontalStrut(10)); + + JButton aufgeben = new JButton("Aufgeben"); + aufgeben.setBackground(Color.LIGHT_GRAY); + aufgeben.setForeground(Color.BLACK); + aufgeben.setFont(new Font("Tahoma", Font.BOLD, 16)); + aufgeben.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(aufgeben); + + // Button-Listener + aufgeben.addActionListener(new ButtonAufgebenListener()); + + aufgebenUndo.add(Box.createHorizontalStrut(10)); + + JButton safe = new JButton("Spielstand sichern"); + safe.setBackground(Color.LIGHT_GRAY); + safe.setForeground(Color.BLACK); + safe.setFont(new Font("Tahoma", Font.BOLD, 16)); + safe.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(safe); + + // Button-Listener + safe.addActionListener(new ButtonFileSaverListener(this, this.game)); + + playerTwo.add(aufgebenUndo); + + playerTwo.add(Box.createVerticalStrut(10)); + + return playerTwo; + } + + private JPanel getUiStatistik() { + + JPanel statistik = new JPanel(); + statistik.setBackground(new Color(90, 90, 90)); + statistik.setLayout(new BoxLayout(statistik, BoxLayout.Y_AXIS)); + + ausgabe = new JTextArea(); + ausgabe.setEditable(false); + ausgabe.setBackground(new Color(75, 75, 75)); + ausgabe.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); + ausgabe.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 20)); + ausgabe.setForeground(Color.BLACK); + ausgabe.setText("\n Bisherige Züge:\n"); + + JScrollPane scrollPane = new JScrollPane(ausgabe); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + + statistik.add(scrollPane); + + return statistik; + } + + public void aktualisiereAusgabe() { + StringBuilder sb = new StringBuilder(); + sb.append("\n Bisherige Züge:\n"); + + MoveList l = game.getMoveList(); + for (Move m : l) { + sb.append(" " + game.getUnicodeFromMove(m) + ": " + m.toString() + "\n"); + } + + ausgabe.setText(sb.toString()); + } + + public void deleteLastAusgabe() { + String[] zeilen = ausgabe.getText().split("\n"); + + // es müssen immer mind 5 Zeilen existieren, dass also 1 Zug löschbar ist + if (zeilen.length <= 2) + return; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < zeilen.length - 1; i++) { + sb.append(zeilen[i]).append("\n"); + } + + ausgabe.setText(sb.toString()); + } + + private JPanel getUiPlayerOne() { + + JPanel playerOne = new JPanel(); + playerOne.setBackground(new Color(90, 90, 90)); + playerOne.setLayout(new BoxLayout(playerOne, BoxLayout.Y_AXIS)); + + playerOne.add(Box.createVerticalStrut(10)); + + // Button zurücknahme und aufgeben für Player 1 + JPanel aufgebenUndo = new JPanel(); + aufgebenUndo.setBackground(new Color(90, 90, 90)); + aufgebenUndo.setLayout(new BoxLayout(aufgebenUndo, BoxLayout.X_AXIS)); + + if (game.isZuruecknahme()) { + undo2 = new JButton("Zug zurücknehmen"); + undo2.setBackground(Color.LIGHT_GRAY); + undo2.setForeground(Color.BLACK); + undo2.setFont(new Font("Tahoma", Font.BOLD, 16)); + undo2.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(undo2); + + // Button-Listener + undo2.addActionListener(new ButtonUndoMoveListener(this, this.game)); + + } + + aufgebenUndo.add(Box.createHorizontalStrut(10)); + + JButton aufgeben = new JButton("Aufgeben"); + aufgeben.setBackground(Color.LIGHT_GRAY); + aufgeben.setForeground(Color.BLACK); + aufgeben.setFont(new Font("Tahoma", Font.BOLD, 16)); + aufgeben.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(aufgeben); + + // Button-Listener + aufgeben.addActionListener(new ButtonAufgebenListener()); + + aufgebenUndo.add(Box.createHorizontalStrut(10)); + + JButton safe = new JButton("Spielstand sichern"); + safe.setBackground(Color.LIGHT_GRAY); + safe.setForeground(Color.BLACK); + safe.setFont(new Font("Tahoma", Font.BOLD, 16)); + safe.setAlignmentX(Component.CENTER_ALIGNMENT); + aufgebenUndo.add(safe); + + // Button-Listener + safe.addActionListener(new ButtonFileSaverListener(this, this.game)); + + playerOne.add(aufgebenUndo); + + playerOne.add(Box.createVerticalStrut(15)); + + JLabel clock1 = clock.getClock1(); + playerOne.add(clock1); + + playerOne.add(Box.createVerticalStrut(10)); + + JLabel pl2 = new JLabel("Player 1:"); + pl2.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0)); + pl2.setFont(new Font("Calibri", Font.BOLD, 35)); + pl2.setForeground(Color.BLACK); + pl2.setAlignmentX(Component.CENTER_ALIGNMENT); + playerOne.add(pl2); + + return playerOne; + } + + public void setBoardMode(BoardMode bm) { + this.mode = bm; + } + + public void setSelectedSquare(Square sq) { + this.selectedSquare = sq; + } + + public HashMap getBelegung() { + return this.belegungen; + } + + public JButton getUndo() { + return undo; + } + + public JButton getUndo2() { + return undo2; + } + + public BoardMode getMode() { + return mode; + } + + public Clock getClock() { + return clock; + } + } diff --git a/src/main/java/de/mannheim/th/chess/utl/Clock.java b/src/main/java/de/mannheim/th/chess/utl/Clock.java index c575d06..80ea3df 100644 --- a/src/main/java/de/mannheim/th/chess/utl/Clock.java +++ b/src/main/java/de/mannheim/th/chess/utl/Clock.java @@ -5,9 +5,11 @@ package de.mannheim.th.chess.utl; */ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Font; import java.util.concurrent.atomic.AtomicInteger; +import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; @@ -17,17 +19,21 @@ import javax.swing.Timer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import de.mannheim.th.chess.ui.SpielFrame; + public class Clock extends Thread implements Runnable { private volatile boolean whiteToMove = true; private volatile boolean gameHasFinished = false; private static final Logger clockLogger = LogManager.getLogger(Clock.class); private int minutes; - + private StringBuilder clockShower; + private JLabel clock1, clock2; + public Clock(String mode) { + setMode(mode); - //run(); } - + public void pressClock() { whiteToMove = !whiteToMove; if (whiteToMove) { @@ -36,105 +42,118 @@ public class Clock extends Thread implements Runnable { clockLogger.info("Schwarz ist am Zug"); } } - + public void endGame() { gameHasFinished = true; } - + public void run() { - JFrame clockFrame = new JFrame("Clock"); - - JPanel player1Panel = new JPanel(); - player1Panel.setBackground(Color.BLACK); - JPanel player2Panel = new JPanel(); - player2Panel.setBackground(Color.BLACK); - clockFrame.setBounds(1000, 500, 10000, 10000); - clockFrame.setLayout(new BorderLayout()); - JLabel clock1 = new JLabel(" " + minutes + ":00 "); - clock1.setForeground(Color.WHITE); - clock1.setFont(new Font("Arial", Font.BOLD, 50)); - JLabel clock2 = new JLabel(" " + minutes + ":00 "); - clock2.setForeground(Color.WHITE); - clock2.setFont(new Font("Arial", Font.BOLD, 50)); - player1Panel.add(clock1); - player2Panel.add(clock2); - JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, player1Panel, player2Panel); - split.setFont(new Font("Arial", Font.BOLD, 50)); - clockFrame.add(split); +// JFrame clockFrame = new JFrame("Clock"); +// +// JPanel player1Panel = new JPanel(); +// player1Panel.setBackground(Color.BLACK); +// JPanel player2Panel = new JPanel(); +// player2Panel.setBackground(Color.BLACK); +// clockFrame.setBounds(1000, 500, 10000, 10000); +// clockFrame.setLayout(new BorderLayout()); + clock1 = new JLabel("" + minutes + ":00 "); + clock1.setBorder(BorderFactory.createEmptyBorder(0, 40, 0, 0)); + clock1.setForeground(Color.BLACK); + clock1.setFont(new Font("Calibri", Font.BOLD, 40)); + clock1.setAlignmentX(Component.CENTER_ALIGNMENT); + clock2 = new JLabel("" + minutes + ":00 "); + clock2.setBorder(BorderFactory.createEmptyBorder(0, 40, 0, 0)); + clock2.setForeground(Color.BLACK); + clock2.setFont(new Font("Calibri", Font.BOLD, 40)); + clock2.setAlignmentX(Component.CENTER_ALIGNMENT); +// player1Panel.add(clock1); +// player2Panel.add(clock2); +// JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, player1Panel, player2Panel); +// split.setFont(new Font("Arial", Font.BOLD, 50)); +// clockFrame.add(split); + var min1 = new AtomicInteger(minutes); var sec1 = new AtomicInteger(0); var min2 = new AtomicInteger(minutes); var sec2 = new AtomicInteger(0); - clockFrame.pack(); - clockFrame.setVisible(true); var t = new Timer(1000, (ae) -> { - - if (!gameHasFinished) { - - StringBuilder clockShower = new StringBuilder(); - if (whiteToMove) { - if (sec1.intValue() == 00) { - sec1.set(60); - min1.decrementAndGet(); - } - if (min1.intValue() < 10) { - clockShower.append("0"); - } - clockShower.append(min1.get()); - clockShower.append(":"); - if (sec1.intValue() < 10) { - clockShower.append("0"); - } - clockShower.append(sec1.decrementAndGet()); - clock1.setText(clockShower.toString()); - } else { - if (sec2.intValue() == 00) { - sec2.set(60); - min2.decrementAndGet(); + if (!gameHasFinished) { + + clockShower = new StringBuilder(); + if (whiteToMove) { + if (sec1.intValue() == 00) { + sec1.set(60); + min1.decrementAndGet(); + } + if (min1.intValue() < 10) { + clockShower.append("0"); + } + clockShower.append(min1.get()); + clockShower.append(":"); + if (sec1.intValue() < 10) { + clockShower.append("0"); + } + clockShower.append(sec1.decrementAndGet()); + clock1.setText(clockShower.toString()); + + } else { + if (sec2.intValue() == 00) { + sec2.set(60); + min2.decrementAndGet(); + } + if (min2.intValue() < 10) { + clockShower.append("0"); + } + clockShower.append(min2.get()); + clockShower.append(":"); + if (sec2.intValue() < 10) { + clockShower.append("0"); + } + clockShower.append(sec2.decrementAndGet()); + clock2.setText(clockShower.toString()); } - if (min2.intValue() < 10) { - clockShower.append("0"); + //sp.repaint(); + if ((sec1.intValue() == 0 && min1.intValue() == 0) || (sec2.intValue() == 0 && min2.intValue() == 0)) { + endGame(); } - clockShower.append(min2.get()); - clockShower.append(":"); - if (sec2.intValue() < 10) { - clockShower.append("0"); - } - clockShower.append(sec2.decrementAndGet()); - clock2.setText(clockShower.toString()); } - clockFrame.repaint(); - if ((sec1.intValue() == 0 && min1.intValue() == 0) || (sec2.intValue() == 0 && min2.intValue() == 0)) { - endGame(); - } - } }); + }); t.start(); } - public static void main(String[] args) throws InterruptedException { - Clock st = new Clock("classic"); - st.start(); - st.pressClock(); - } - + private void setMode(String mode) { - switch(mode) { + switch (mode.toLowerCase()) { case "blitz": minutes = 5; clockLogger.info("Neue Blitz-Uhr wurde erstellt"); break; - case "rapid": + case "schnellschach": minutes = 10; clockLogger.info("Neue Schnellschach-Uhr wurde erstellt"); break; - case "classic": + case "klassisch": minutes = 120; clockLogger.info("Neue klassische Schachuhr wurde erstellt"); break; } } + + public void switchClock() { + whiteToMove = !whiteToMove; + } + + public JLabel getClock1() { + + return clock1; + } + + public JLabel getClock2() { + + return clock2; + } } \ No newline at end of file diff --git a/src/test/java/de/mannheim/th/chess/domain/GameTest.java b/src/test/java/de/mannheim/th/chess/domain/GameTest.java index cdf123e..9a154e5 100644 --- a/src/test/java/de/mannheim/th/chess/domain/GameTest.java +++ b/src/test/java/de/mannheim/th/chess/domain/GameTest.java @@ -52,4 +52,13 @@ public class GameTest { controllList = Arrays.asList(Square.H1, Square.A1); assertEquals(controllList, game.getAllLegalMoveableSquares()); } + + @Test + void getUnicodeFromMoveTest() { + + Game g = new Game(); + Move m = new Move(Square.A2, Square.A4); + g.getBoard().doMove(m); + assertEquals("♙", g.getUnicodeFromMove(m)); + } } diff --git a/src/test/java/de/mannheim/th/chess/ui/SpielFrameTest.java b/src/test/java/de/mannheim/th/chess/ui/SpielFrameTest.java new file mode 100644 index 0000000..0950947 --- /dev/null +++ b/src/test/java/de/mannheim/th/chess/ui/SpielFrameTest.java @@ -0,0 +1,12 @@ +package de.mannheim.th.chess.ui; + +import org.junit.jupiter.api.Test; + +class SpielFrameTest { + + @Test + void mirrowedGridTest() { + + } + +}