Compare commits

...

3 Commits

Author SHA1 Message Date
cleme c1210f2141 restart enabled 2025-04-22 16:11:16 +02:00
cleme 29dacdaf3c restart function enabled 2025-04-22 16:08:51 +02:00
cleme 11a8971e18 . 2025-04-20 23:04:06 +02:00
5 changed files with 344 additions and 250 deletions

View File

@ -209,7 +209,7 @@ public class Board {
}
else {
if (isHighlighted(x, y)) {
Piece capturedPiece = clickedPiece; // Peut être null pour en passant
Piece capturedPiece = clickedPiece; // Peut <20>tre null pour en passant
Move move = new Move(selectedX, selectedY, x, y, selectedPiece, capturedPiece);
playMove(move);
@ -242,7 +242,7 @@ public class Board {
if (pieceToMove == null || pieceToMove.getType() != move.getPieceMoved().getType() || pieceToMove.isWhite() != move.getPieceMoved().isWhite()) {
System.err.println("playMove Error: Mismatch between move data and piece found at source square (" + move.getFromX() + "," + move.getFromY() + "). Aborting move.");
return;
return;
}
boolean isEnPassantCapture = false;
@ -270,7 +270,7 @@ public class Board {
}
}
if (!removed) {
System.err.println("playMove Warning: Could not remove captured piece " + capturedPiece.getType() + " at (" + move.getToX() + "," + move.getToY() + ")");
System.err.println("playMove Warning: Could not remove captured piece " + capturedPiece.getType() + " at (" + move.getToX() + "," + move.getToY() + ")");
}
}
@ -282,6 +282,11 @@ public class Board {
System.out.println("En Passant target set at (" + this.enPassantTargetX + "," + this.enPassantTargetY + ")");
}
// G<>rer le roque
if (pieceToMove.getType() == PieceType.King && Math.abs(move.getToX() - move.getFromX()) == 2) {
handleCastling(move);
}
moveHistory.addMove(move);
this.turnNumber++;
@ -291,6 +296,27 @@ public class Board {
System.out.println("Turn " + this.turnNumber + ". " + (this.isTurnWhite ? "White" : "Black") + " to move.");
}
private void handleCastling(Move move) {
Piece king = move.getPieceMoved();
int fromX = move.getFromX();
int toX = move.getToX();
int y = move.getFromY();
if (toX == fromX + 2) {
// Roque c<>t<EFBFBD> roi
Piece rook = getPieceAt(fromX + 3, y);
if (rook != null && rook.getType() == PieceType.Rook) {
rook.setPosition(fromX + 1, y);
}
} else if (toX == fromX - 2) {
// Roque c<>t<EFBFBD> dame
Piece rook = getPieceAt(fromX - 4, y);
if (rook != null && rook.getType() == PieceType.Rook) {
rook.setPosition(fromX - 1, y);
}
}
}
public boolean undoLastMove() {
return moveHistory.undoLastMove();
}
@ -332,4 +358,4 @@ public class Board {
// TODO: Add saving of enPassantTargetX/Y
return null;
}
}
}

View File

@ -68,7 +68,7 @@ public class Move {
moves.add(x + "," + y);
}
private static boolean isValidPosition(Board board, int x, int y) {
static boolean isValidPosition(Board board, int x, int y) {
return x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight();
}
@ -129,7 +129,6 @@ public class Move {
}
}
// *** D<>but Modification En Passant ***
// V<>rifier la capture en passant
int enPassantTargetX = board.getEnPassantTargetX();
int enPassantTargetY = board.getEnPassantTargetY();
@ -148,10 +147,8 @@ public class Move {
}
}
}
// *** Fin Modification En Passant ***
}
private static void calculateKnightMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
int[][] knightMoves = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
@ -180,20 +177,57 @@ public class Move {
if (isValidPosition(board, nextX, nextY)) {
Piece target = getPieceAt(board, nextX, nextY);
if (target == null || target.isWhite() != piece.isWhite()) {
addMove(nextX, nextY, validMoves);
addMove(nextX, nextY, validMoves);
}
}
}
}
// TODO: Ajouter calcul du roque ici
// Ajouter calcul du roque ici
calculateCastlingMoves(board, piece, x, y, validMoves);
}
@Override
public String toString() {
String captureStr = (pieceCaptured != null) ? "x" + pieceCaptured.getType().getSummary() : "";
return pieceMoved.getType().getSummary() +
"(" + fromX + "," + fromY + ")" +
"-" + captureStr +
"(" + toX + "," + toY + ")";
}
}
private static void calculateCastlingMoves(Board board, Piece piece, int x, int y, Set<String> validMoves) {
if (piece.getType() != PieceType.King || piece.hasMoved()) {
return;
}
// Roque c<>t<EFBFBD> roi
if (canCastleKingside(board, piece, x, y)) {
addMove(x + 2, y, validMoves);
}
// Roque c<>t<EFBFBD> dame
if (canCastleQueenside(board, piece, x, y)) {
addMove(x - 2, y, validMoves);
}
}
private static boolean canCastleKingside(Board board, Piece king, int x, int y) {
Piece rook = board.getPieceAt(x + 3, y);
return rook != null && rook.getType() == PieceType.Rook && !rook.hasMoved() &&
board.getPieceAt(x + 1, y) == null && board.getPieceAt(x + 2, y) == null &&
!isKingInCheck(board, king.isWhite());
}
private static boolean canCastleQueenside(Board board, Piece king, int x, int y) {
Piece rook = board.getPieceAt(x - 4, y);
return rook != null && rook.getType() == PieceType.Rook && !rook.hasMoved() &&
board.getPieceAt(x - 1, y) == null && board.getPieceAt(x - 2, y) == null && board.getPieceAt(x - 3, y) == null &&
!isKingInCheck(board, king.isWhite());
}
private static boolean isKingInCheck(Board board, boolean isWhite) {
// Impl<70>mentez la logique pour v<>rifier si le roi est en <20>chec
// Cela n<>cessite de v<>rifier tous les mouvements possibles des pi<70>ces adverses
return false;
}
@Override
public String toString() {
String captureStr = (pieceCaptured != null) ? "x" + pieceCaptured.getType().getSummary() : "";
return pieceMoved.getType().getSummary() +
"(" + fromX + "," + fromY + ")" +
"-" + captureStr +
"(" + toX + "," + toY + ")";
}
}

View File

@ -45,7 +45,7 @@ public class MoveHistory {
board.getEnPassantTargetY()
);
moveRecords.add(record);
System.out.println("MoveHistory: Added move from (" + move.getFromX() + "," + move.getFromY() +
System.out.println("MoveHistory: Added move from (" + move.getFromX() + "," + move.getFromY() +
") to (" + move.getToX() + "," + move.getToY() + ")");
}
@ -64,7 +64,7 @@ public class MoveHistory {
MoveRecord lastRecord = moveRecords.remove(moveRecords.size() - 1);
Move lastMove = lastRecord.getMove();
System.out.println("MoveHistory: Undoing move from (" + lastMove.getFromX() + "," + lastMove.getFromY() +
System.out.println("MoveHistory: Undoing move from (" + lastMove.getFromX() + "," + lastMove.getFromY() +
") to (" + lastMove.getToX() + "," + lastMove.getToY() + ")");
// Restore the piece to its original position
@ -80,7 +80,7 @@ public class MoveHistory {
boolean wasEnPassantCapture = false;
if (pieceCaptured != null) {
// Check if this was an en passant capture
if (lastMove.getToX() == lastRecord.getEnPassantTargetX() &&
if (lastMove.getToX() == lastRecord.getEnPassantTargetX() &&
lastMove.getToY() == lastRecord.getEnPassantTargetY() &&
lastMove.getPieceCaptured() == null) {
// For en passant, the captured pawn is at (toX, fromY)
@ -120,4 +120,4 @@ public class MoveHistory {
}
return true;
}
}
}

View File

@ -8,6 +8,7 @@ public class Piece {
private int y;
private final PieceType type;
private final boolean isWhite;
private boolean hasMoved;
public Piece(int x, int y, PieceType type, boolean isWhite) {
if (type == null) {
@ -17,14 +18,19 @@ public class Piece {
this.y = y;
this.type = type;
this.isWhite = isWhite;
this.hasMoved = false;
}
public int getX() { return this.x; }
public int getY() { return this.y; }
public PieceType getType() { return this.type; }
public boolean isWhite() { return this.isWhite; }
public boolean hasMoved() { return hasMoved; }
void setPosition(int newX, int newY) {
if (this.x != newX || this.y != newY) {
this.hasMoved = true;
}
this.x = newX;
this.y = newY;
}
@ -57,7 +63,7 @@ public class Piece {
case King:
return dx <= 1 && dy <= 1;
default:
System.err.println("Erreur: Type de pièce inconnu dans canMoveTo: " + this.type);
System.err.println("Erreur: Type de pi<70>ce inconnu dans canMoveTo: " + this.type);
return false;
}
}
@ -82,7 +88,7 @@ public class Piece {
return false;
}
private boolean isPathClear(int fromX, int fromY, int toX, int toY, Board board) {
private boolean isPathClear(int fromX, int fromY, int toX, int toY, Board board) {
int dx = toX - fromX;
int dy = toY - fromY;
int steps = Math.max(Math.abs(dx), Math.abs(dy));
@ -118,4 +124,4 @@ public class Piece {
public int hashCode() {
return Objects.hash(x, y, type, isWhite);
}
}
}

View File

@ -1,268 +1,296 @@
package windowInterface;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.SwingUtilities;
import backend.Game;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JCheckBox;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.awt.event.ActionEvent;
import javax.swing.JList;
import javax.swing.AbstractListModel;
import javax.swing.JToggleButton;
import javax.swing.JRadioButton;
import javax.swing.JCheckBox;
public class MyInterface extends JFrame {
private static final long serialVersionUID = -6840815447618468846L;
private JPanel contentPane;
private JLabel turnLabel;
private JLabel borderLabel;
private JLabel speedLabel;
private JPanelChessBoard panelDraw;
private Game game;
private JLabel actionLabel;
private JCheckBox chckbxBlackAI;
private JCheckBox chckbxWhiteAI;
private static final long serialVersionUID = -6840815447618468846L;
private JPanel contentPane;
private JLabel turnLabel;
private JLabel borderLabel;
private JLabel speedLabel;
private JPanelChessBoard panelDraw;
private Game game;
private JLabel actionLabel;
private JCheckBox chckbxBlackAI;
private JCheckBox chckbxWhiteAI;
/**
* Create the frame.
*/
public MyInterface() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(10, 10, 650, 650);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
/**
* Create the frame.
*/
public MyInterface() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(10, 10, 650, 650);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panelTop = new JPanel();
contentPane.add(panelTop, BorderLayout.NORTH);
JPanel panelRight = new JPanel();
contentPane.add(panelRight, BorderLayout.EAST);
panelRight.setLayout(new GridLayout(4,1));
JPanel panelTop = new JPanel();
contentPane.add(panelTop, BorderLayout.NORTH);
JPanel panelRight = new JPanel();
contentPane.add(panelRight, BorderLayout.EAST);
panelRight.setLayout(new GridLayout(4, 1));
actionLabel = new JLabel("Waiting For Start");
panelTop.add(actionLabel);
actionLabel = new JLabel("Waiting For Start");
panelTop.add(actionLabel);
JButton btnGo = new JButton("Start/Restart");
btnGo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicButtonStart();
}
});
panelTop.add(btnGo);
JButton btnGo = new JButton("Start/Restart");
btnGo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicButtonStart();
}
});
panelTop.add(btnGo);
turnLabel = new JLabel("Turn : X");
panelTop.add(turnLabel);
JButton btnLoad = new JButton("Load File");
btnLoad.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicLoadFileButton();
}
});
panelRight.add(btnLoad);
turnLabel = new JLabel("Turn : X");
panelTop.add(turnLabel);
JButton btnSave = new JButton("Save To File");
btnSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicSaveToFileButton();
}
});
panelRight.add(btnSave);
JButton btnLoad = new JButton("Load File");
btnLoad.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicLoadFileButton();
}
});
panelRight.add(btnLoad);
JButton btnAdder = new JButton("Add Piece");
btnAdder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clickButtonAdder();
}
});
panelRight.add(btnAdder);
JButton btnPieceSelector = new JButton("Piece Select");
btnPieceSelector.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clickButtonSelector();
}
});
panelRight.add(btnPieceSelector);
JButton btnSave = new JButton("Save To File");
btnSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicSaveToFileButton();
}
});
panelRight.add(btnSave);
JButton btnUndo = new JButton("Undo");
btnUndo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicUndoButton();
}
JButton btnAdder = new JButton("Add Piece");
btnAdder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clickButtonAdder();
}
});
panelRight.add(btnAdder);
});
panelTop.add(btnUndo);
chckbxWhiteAI = new JCheckBox("WhiteAI");
chckbxWhiteAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(true);
}
JButton btnPieceSelector = new JButton("Piece Select");
btnPieceSelector.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clickButtonSelector();
}
});
panelRight.add(btnPieceSelector);
});
panelTop.add(chckbxWhiteAI);
chckbxBlackAI = new JCheckBox("BlackAI");
chckbxBlackAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(false);
}
JButton btnUndo = new JButton("Undo");
btnUndo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicUndoButton();
}
});
panelTop.add(btnUndo);
});
panelTop.add(chckbxBlackAI);
chckbxWhiteAI = new JCheckBox("WhiteAI");
chckbxWhiteAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(true);
}
});
panelTop.add(chckbxWhiteAI);
panelDraw = new JPanelChessBoard(this);
contentPane.add(panelDraw, BorderLayout.CENTER);
}
chckbxBlackAI = new JCheckBox("BlackAI");
chckbxBlackAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(false);
}
});
panelTop.add(chckbxBlackAI);
public void setStepBanner(String s) {
turnLabel.setText(s);
}
panelDraw = new JPanelChessBoard(this);
contentPane.add(panelDraw, BorderLayout.CENTER);
}
public void setBorderBanner(String s) {
borderLabel.setText(s);
}
public void setStepBanner(String s) {
turnLabel.setText(s);
}
public JPanelChessBoard getPanelDessin() {
return panelDraw;
}
public void instantiateSimu() {
if(game==null) {
game = new Game(this);
panelDraw.setGame(game);
game.start();
}
}
public void setBorderBanner(String s) {
borderLabel.setText(s);
}
public void clicButtonStart() {
this.instantiateSimu();
}
public void clickButtonAdder() {
panelDraw.toggleAdderMode();
}
public void clickButtonSelector() {
panelDraw.togglePieceSelector();
}
public JPanelChessBoard getPanelDessin() {
return panelDraw;
}
private void clicUndoButton() {
if(game == null) {
System.out.println("error : can't undo while no game present");
} else {
game.undoLastMove();
}
public void instantiateSimu() {
// If a game already exists, stop it cleanly
if (game != null) {
// Disable AI to prevent interference
if (chckbxWhiteAI.isSelected()) {
game.toggleAI(true);
chckbxWhiteAI.setSelected(false);
}
if (chckbxBlackAI.isSelected()) {
game.toggleAI(false);
chckbxBlackAI.setSelected(false);
}
}
public void clicAIToggle(boolean isWhite) {
if(game == null) {
System.out.println("error : can't activate AI while no game present");
if(isWhite) {
chckbxWhiteAI.setSelected(false);
}else {
chckbxBlackAI.setSelected(false);
}
} else {
game.toggleAI(isWhite);
}
}
public void clicLoadFileButton() {
Game loadedSim = new Game(this);
String fileName=SelectFile();
LinkedList<String> lines = new LinkedList<String>();
if (fileName.length()>0) {
try {
BufferedReader fileContent = new BufferedReader(new FileReader(fileName));
String line = fileContent.readLine();
int colorID = 0;
while (line != null) {
lines.add(line);
line = fileContent.readLine();
}
loadedSim.setBoard(Arrays.stream(lines.toArray()).map(Object::toString).toArray(String[]::new));
fileContent.close();
} catch (Exception e) {
e.printStackTrace();
}
game = loadedSim;
panelDraw.setGame(game);
this.repaint();
}
}
// Interrupt the game thread
game.interrupt();
try {
game.join(); // Wait for the thread to fully stop
} catch (InterruptedException e) {
System.err.println("Interrupted while waiting for game thread to stop: " + e.getMessage());
Thread.currentThread().interrupt(); // Restore interrupted status
}
}
public void clicSaveToFileButton() {
String fileName=SelectFile();
if (fileName.length()>0) {
String[] content = game.getFileRepresentation();
writeFile(fileName, content);
}
}
public String SelectFile() {
String s;
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("Choose a file");
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.setAcceptAllFileFilterUsed(true);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
s=chooser.getSelectedFile().toString();
} else {
System.out.println("No Selection ");
s="";
}
return s;
}
public void writeFile(String fileName, String[] content) {
FileWriter csvWriter;
try {
csvWriter = new FileWriter(fileName);
for (String row : content) {
csvWriter.append(row);
csvWriter.append("\n");
}
csvWriter.flush();
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void update(int turnCount, boolean turnIsWhite) {
turnLabel.setText("Turn : "+turnCount+", "+ (turnIsWhite?"White":"Black"));
actionLabel.setText(panelDraw.isPieceAdderMode()?"Adding Piece":
(panelDraw.isPieceSelectorMode()?"Selecting Piece to Add":
"Playing"));
this.repaint();
}
public void eraseLabels() {
this.setStepBanner("Turn : X");
}
// Reset UI state
if (panelDraw.isPieceAdderMode()) {
panelDraw.toggleAdderMode();
}
if (panelDraw.isPieceSelectorMode()) {
panelDraw.togglePieceSelector();
}
}
// Create a new game
game = new Game(this);
panelDraw.setGame(game);
// Reset the board to the default setup
game.setDefaultSetup();
// Start the new game thread on the EDT to ensure synchronization
SwingUtilities.invokeLater(() -> {
game.start();
// Force an immediate UI update
panelDraw.repaint();
update(game.getTurnNumber(), game.isWhiteTurn());
});
}
public void clicButtonStart() {
this.instantiateSimu();
}
public void clickButtonAdder() {
panelDraw.toggleAdderMode();
}
public void clickButtonSelector() {
panelDraw.togglePieceSelector();
}
private void clicUndoButton() {
if (game == null) {
System.out.println("error: can't undo while no game present");
} else {
game.undoLastMove();
}
}
public void clicAIToggle(boolean isWhite) {
if (game == null) {
System.out.println("error: can't activate AI while no game present");
if (isWhite) {
chckbxWhiteAI.setSelected(false);
} else {
chckbxBlackAI.setSelected(false);
}
} else {
game.toggleAI(isWhite);
}
}
public void clicLoadFileButton() {
Game loadedSim = new Game(this);
String fileName = SelectFile();
LinkedList<String> lines = new LinkedList<String>();
if (fileName.length() > 0) {
try {
BufferedReader fileContent = new BufferedReader(new FileReader(fileName));
String line = fileContent.readLine();
int colorID = 0;
while (line != null) {
lines.add(line);
line = fileContent.readLine();
}
loadedSim.setBoard(Arrays.stream(lines.toArray()).map(Object::toString).toArray(String[]::new));
fileContent.close();
} catch (Exception e) {
e.printStackTrace();
}
game = loadedSim;
panelDraw.setGame(game);
this.repaint();
}
}
public void clicSaveToFileButton() {
String fileName = SelectFile();
if (fileName.length() > 0) {
String[] content = game.getFileRepresentation();
writeFile(fileName, content);
}
}
public String SelectFile() {
String s;
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("Choose a file");
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.setAcceptAllFileFilterUsed(true);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
s = chooser.getSelectedFile().toString();
} else {
System.out.println("No Selection ");
s = "";
}
return s;
}
public void writeFile(String fileName, String[] content) {
FileWriter csvWriter;
try {
csvWriter = new FileWriter(fileName);
for (String row : content) {
csvWriter.append(row);
csvWriter.append("\n");
}
csvWriter.flush();
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void update(int turnCount, boolean turnIsWhite) {
turnLabel.setText("Turn: " + turnCount + ", " + (turnIsWhite ? "White" : "Black"));
actionLabel.setText(panelDraw.isPieceAdderMode() ? "Adding Piece" :
(panelDraw.isPieceSelectorMode() ? "Selecting Piece to Add" : "Playing"));
this.repaint();
}
public void eraseLabels() {
this.setStepBanner("Turn: X");
}
}