From bffb1ff60fec8b8b15c89dd3036f5fbc74b9c634 Mon Sep 17 00:00:00 2001 From: stuckd Date: Tue, 17 Jun 2025 14:54:11 +0200 Subject: [PATCH] refactor move highlighting --- .classpath | 19 +- .project | 13 +- .../de/mannheim/th/chess/domain/Game.java | 15 + .../de/mannheim/th/chess/ui/SpielFrame.java | 399 +++++++++++------- 4 files changed, 291 insertions(+), 155 deletions(-) diff --git a/.classpath b/.classpath index e571fe4..4e7f670 100644 --- a/.classpath +++ b/.classpath @@ -36,7 +36,22 @@ - - + + + + + + + + + + + + + + + + + diff --git a/.project b/.project index a2ac3b0..c614d18 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - Schach + SchachMVN @@ -20,4 +20,15 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + + + 1750157105125 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + 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 f880fa8..63e9bf5 100644 --- a/src/main/java/de/mannheim/th/chess/domain/Game.java +++ b/src/main/java/de/mannheim/th/chess/domain/Game.java @@ -7,6 +7,7 @@ import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.Square; 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.utl.Clock; @@ -104,7 +105,21 @@ public class Game { } + public List getAllLegalMoveableSquares() { + return this.board.legalMoves().stream() + .map(move -> move.getFrom()) + .collect(Collectors.toList()); + } + + public List getLegalMoveableSquares(Square square) { + return this.board.legalMoves().stream() + .filter(move -> move.getFrom() == square) + .map(move -> move.getTo()) + .collect(Collectors.toList()); + } + public String toFEN() { + board.toString(); return board.getFen(); } } 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 e4ed32d..ce041d6 100644 --- a/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java +++ b/src/main/java/de/mannheim/th/chess/ui/SpielFrame.java @@ -2,6 +2,7 @@ package de.mannheim.th.chess.ui; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter.Red; import com.github.bhlangonijr.chesslib.Board; import com.github.bhlangonijr.chesslib.File; @@ -53,6 +54,14 @@ public class SpielFrame extends JFrame { private boolean playerWhite = true; private boolean moveFinished = false; + private BoardMode mode; + private Square selectedSquare; + + enum BoardMode { + normal, + pieceSelected, + } + /** * Launch the application. Die Main-Methode für den WindowBuilder. */ @@ -75,6 +84,7 @@ public class SpielFrame extends JFrame { public SpielFrame() { game = new Game(); + mode = BoardMode.normal; setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 1920, 1080); @@ -108,168 +118,217 @@ public class SpielFrame extends JFrame { * Erstellt alle Buttons und fügt sie dem Frame hinzu. */ private void erstelleBrett() { - for (int i = 0; i < 64; i++) { - JButton b = new JButton(); - b.setFocusPainted(false); - b.setFont(new Font("Arial", Font.PLAIN, 30)); - if ((i / 8 + i % 8) % 2 == 0) { - logger.info("Helles Feld erstellt." + i); - b.setBackground(new Color(90, 90, 90)); - } else { - logger.info("Dunkles Feld erstellt." + i); - b.setBackground(new Color(65, 65, 65)); - } + clearButtons(); + setDefaultBackground(); - b.setForeground(Color.WHITE); - b.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); - b.addActionListener(new ActionListener() { + List selectables; - @Override - public void actionPerformed(ActionEvent e) { + switch (this.mode) { + case BoardMode.normal: + selectables = game.getAllLegalMoveableSquares(); - // setzt alle Roten Felder zurück - for (JButton b : farben.keySet()) { + System.out.println(selectables); - if (b.getBackground().equals(new Color(230, 100, 100))) { - - b.setBackground(farben.get(b)); + for (Square square : selectables) { + final Square currentSquare = square; // ActionListener need it to be final + JButton b = buttons.get(63 - square.ordinal()); + b.setEnabled(true); + b.setBackground(Color.green); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("switch to selected"); + mode = BoardMode.pieceSelected; + selectedSquare = currentSquare; + erstelleBrett(); } - } - - // wenn weiß dran - if (playerWhite) { - - // wenn gerade Figur ausgewählt wird... - buttonChoosed = (JButton) e.getSource(); - symbolChoosed = belegungen.get(buttonChoosed); - - // 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); - - // filtert möglichen Züge heraus - int position = positions.get(buttonChoosed); - - clickableButtons = game - .getLegalMoves( - Square.encode(Rank.allRanks[7 - position / 8], File.allFiles[position % 8])) - .stream().peek(System.out::println).map(m -> m.getTo()).peek(System.out::println) - .map(s -> 56 - s.getRank().ordinal() * 8 + s.getFile().ordinal()) - .collect(Collectors.toList()); - - // filtert mögliche Züge und nicht mögliche Züge in eine Map aus Listen - Map> buttonsSeperated = buttons.stream() - .collect(Collectors.partitioningBy(b -> clickableButtons.contains(buttons.indexOf(b)))); - - for (Boolean list : buttonsSeperated.keySet()) { - - if (list) { - // alle möglichen felder rot markieren - for (JButton b : positions.keySet()) { - // wenn button ein möglicher zug ist - if (clickableButtons.contains(positions.get(b))) { - farben.put(b, b.getBackground()); // damit sich gemerkt werden kann welches feld welche farbe vorher - // hatte - b.setBackground(new Color(230, 100, 100)); - - } - } - - } else { - // den rest der buttons ausser die möglichen züge deaktivieren - List andere = buttonsSeperated.get(list); - - for (JButton b : andere) { - if (!belegungen.get(b).split("-")[0].equals("w")) { - b.setEnabled(false); - } - } - } - } - - // alle weisen squares deaktivieren, damit dannach klar ist wer dran ist - for (JButton b : belegungen.keySet()) { - if (belegungen.get(b).split("-")[0].equals("b")) { - b.setEnabled(false); - } - } - - } 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); - - // filtert möglichen Züge heraus - int position = positions.get(buttonChoosed); - List clickableButtons = new ArrayList<>(); - clickableButtons = game - .getLegalMoves( - Square.encode(Rank.allRanks[7 - position / 8], File.allFiles[position % 8])) - .stream().peek(System.out::println).map(m -> m.getTo()).peek(System.out::println) - .map(s -> 56 - s.getRank().ordinal() * 8 + s.getFile().ordinal()) - .collect(Collectors.toList()); - - for (JButton b : positions.keySet()) { - // wenn button ein möglicher zug ist - if (clickableButtons.contains(positions.get(b))) { - b.setBackground(new Color(230, 100, 100)); - } - } - - // alle schwarzen squares deaktivieren, damit dannach klar ist wer dran ist - for (JButton b : belegungen.keySet()) { - if (belegungen.get(b).split("-")[0].equals("w")) { - b.setEnabled(false); - } - } - - } - - // alle anderen Buttons nicht ckickbar zu machen - - // Button Icon zurücksetzen - - // Buttonposition merken (in MoveListe oder so) - - // wenn Button platzierd werden soll... - - // neuen Button in Moveliste eintragen - - // Icon ändern - - // Modus auf auswählen setzen und spielerwechsel markieren - - // spielerwechsel - if (moveFinished) - playerWhite = !playerWhite; - + }); } - }); - panelLinks.add(b); - buttons.add(b); - positions.put(b, i); + break; + + case BoardMode.pieceSelected: + JButton s = buttons.get(63 - selectedSquare.ordinal()); + s.setEnabled(true); + s.setBackground(Color.orange); + s.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mode = BoardMode.normal; + selectedSquare = null; + erstelleBrett(); + } + }); // cancel action + + selectables = game.getLegalMoveableSquares(selectedSquare); + + for (Square square : selectables) { + JButton b = buttons.get(63 - square.ordinal()); + b.setEnabled(true); + b.setBackground(Color.RED); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + System.out.println("switch to normal"); + mode = BoardMode.normal; + erstelleBrett(); + } + }); + } + + break; + default: + break; } + for (JButton b : this.buttons) { + panelLinks.add(b); + } + + // int i = 0;i<64;i++) + // { + // + // // wenn gerade Figur ausgewählt wird... + // buttonChoosed = (JButton) e.getSource(); + // symbolChoosed = belegungen.get(buttonChoosed); + // + // // 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); + // + // // filtert möglichen Züge heraus + // int position = positions.get(buttonChoosed); + // + // clickableButtons = game + // .getLegalMoves( + // Square.encode(Rank.allRanks[7 - position / 8], File.allFiles[position % 8])) + // .stream().peek(System.out::println).map(m -> + // m.getTo()).peek(System.out::println) + // .map(s -> 56 - s.getRank().ordinal() * 8 + s.getFile().ordinal()) + // .collect(Collectors.toList()); + // + // // filtert mögliche Züge und nicht mögliche Züge in eine Map aus Listen + // Map> buttonsSeperated = buttons.stream() + // .collect(Collectors.partitioningBy(b -> + // clickableButtons.contains(buttons.indexOf(b)))); + // + // for (Boolean list : buttonsSeperated.keySet()) { + // + // if (list) { + // // alle möglichen felder rot markieren + // for (JButton b : positions.keySet()) { + // // wenn button ein möglicher zug ist + // if (clickableButtons.contains(positions.get(b))) { + // farben.put(b, b.getBackground()); // damit sich gemerkt werden kann welches + // feld welche farbe vorher + // // hatte + // b.setBackground(new Color(230, 100, 100)); + // + // } + // } + // + // } else { + // // den rest der buttons ausser die möglichen züge deaktivieren + // List andere = buttonsSeperated.get(list); + // + // for (JButton b : andere) { + // if (!belegungen.get(b).split("-")[0].equals("w")) { + // b.setEnabled(false); + // } + // } + // } + // } + // + // // alle weisen squares deaktivieren, damit dannach klar ist wer dran ist + // for (JButton b : belegungen.keySet()) { + // if (belegungen.get(b).split("-")[0].equals("b")) { + // b.setEnabled(false); + // } + // } + // + // }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); + // + // // filtert möglichen Züge heraus + // int position = positions.get(buttonChoosed); + // List clickableButtons = new ArrayList<>(); + // clickableButtons = game + // .getLegalMoves( + // Square.encode(Rank.allRanks[7 - position / 8], File.allFiles[position % 8])) + // .stream().peek(System.out::println).map(m -> + // m.getTo()).peek(System.out::println) + // .map(s -> 56 - s.getRank().ordinal() * 8 + s.getFile().ordinal()) + // .collect(Collectors.toList()); + // + // for (JButton b : positions.keySet()) { + // // wenn button ein möglicher zug ist + // if (clickableButtons.contains(positions.get(b))) { + // b.setBackground(new Color(230, 100, 100)); + // } + // } + // + // // alle schwarzen squares deaktivieren, damit dannach klar ist wer dran ist + // for (JButton b : belegungen.keySet()) { + // if (belegungen.get(b).split("-")[0].equals("w")) { + // b.setEnabled(false); + // } + // } + // + // } + // + // // alle anderen Buttons nicht ckickbar zu machen + // + // // Button Icon zurücksetzen + // + // // Buttonposition merken (in MoveListe oder so) + // + // // wenn Button platzierd werden soll... + // + // // neuen Button in Moveliste eintragen + // + // // Icon ändern + // + // // Modus auf auswählen setzen und spielerwechsel markieren + // + // // spielerwechsel + // if(moveFinished)playerWhite=!playerWhite; + // + // } + // + // }); + + // panelLinks.add(b); + // buttons.add(b); + // positions.put(b, i); + // + // } + ladeBrett(); } @@ -287,7 +346,8 @@ public class SpielFrame extends JFrame { int leerfelder = Character.getNumericValue(fen[j]); for (int k = 0; k < leerfelder; k++) { belegungen.put(buttons.get(i), "n-n"); - buttons.get(i).setEnabled(false); // erstmal deaktivieren, weil leere Felder nicht ckickbar sein sollten. + // buttons.get(i).setEnabled(false); // erstmal deaktivieren, weil leere Felder + // nicht ckickbar sein sollten. i++; } continue; @@ -303,4 +363,39 @@ public class SpielFrame extends JFrame { } } + + private void clearButtons() { + buttons.clear(); + panelLinks.removeAll(); + + for (int i = 0; i < 64; i++) { + JButton b = new JButton(); + + b.setEnabled(false); + + // style + b.setFocusPainted(false); + b.setFont(new Font("Arial", Font.PLAIN, 30)); + + b.setForeground(Color.WHITE); + b.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); + b.setName(i + ""); + + buttons.add(b); + } + } + + private void setDefaultBackground() { + 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); + b.setBackground(new Color(90, 90, 90)); + } else { + logger.info("Dunkles Feld erstellt." + i); + b.setBackground(new Color(65, 65, 65)); + } + } + } + }