Compare commits

..

No commits in common. "master" and "castling-saved" have entirely different histories.

6 changed files with 306 additions and 537 deletions

View File

@ -1,90 +1,17 @@
package backend;
import java.util.ArrayList;
import java.util.Random;
public class AutoPlayer {
private final Move moveHelper = new Move();
private final Random random = new Random();
/**
* Returns a random legal move for the current player
* @param boardObj The board to find moves for
* @return a valid Move or null if no moves available
*/
public Move computeBestMove(Board boardObj) {
// Create a list of pieces that can move
ArrayList<Piece> candidates = new ArrayList<>();
ArrayList<Piece> allPieces = boardObj.getPieces();
int width = boardObj.getWidth();
int height = boardObj.getHeight();
boolean isWhiteTurn = boardObj.isTurnWhite();
Piece[][] boardArray = new Piece[width][height];
// Find all pieces with legal moves
for (Piece piece : allPieces) {
// Only consider pieces of the current player's color
if (piece.isWhite() == isWhiteTurn) {
clearBoard(boardArray);
for (Piece p : allPieces) {
boardArray[p.getX()][p.getY()] = p;
}
ArrayList<int[]> moves = moveHelper.getValidMoves(
piece, boardArray, width, height, null, boardObj
);
if (!moves.isEmpty()) {
candidates.add(piece);
}
}
}
if (candidates.isEmpty()) return null;
// Select a random piece to move
Piece selected = candidates.get(random.nextInt(candidates.size()));
clearBoard(boardArray);
for (Piece p : allPieces) {
boardArray[p.getX()][p.getY()] = p;
}
ArrayList<int[]> moves = moveHelper.getValidMoves(
selected, boardArray, width, height, null, boardObj
);
// Select a random destination for the piece
int[] target = moves.get(random.nextInt(moves.size()));
Move aiMove = new Move();
aiMove.setFromX(selected.getX());
aiMove.setFromY(selected.getY());
aiMove.setToX(target[0]);
aiMove.setToY(target[1]);
return aiMove;
}
/**
* Clears the given board array by setting all elements to null
*/
private void clearBoard(Piece[][] boardArray) {
for (int x = 0; x < boardArray.length; x++) {
for (int y = 0; y < boardArray[x].length; y++) {
boardArray[x][y] = null;
}
}
}
}
/**
* returns the best Move to try on provided board for active player
* @param board
* @return
*/
public Move computeBestMove(Board board) {
return null;
}
}

View File

@ -15,8 +15,7 @@ public class Board {
private ArrayList<int[]> highlightedSquares = new ArrayList<>();
private int[] enPassantTarget = null; // [x,y] coordinates of en passant target square
private Move moveHelper = new Move();
private final AutoPlayer ai = new AutoPlayer();
public Board(int colNum, int lineNum) {
this.width = colNum;
this.height = lineNum;
@ -117,12 +116,22 @@ public class Board {
}
return pieces;
}
public boolean isSelected(int x, int y) {
return hasSelectedPiece && selectedX == x && selectedY == y;
}
public void userTouch(int x, int y) {
if (x < 0 || x >= width || y < 0 || y >= height) return;
@ -161,7 +170,7 @@ public class Board {
board[selectedX][selectedY] = null;
selectedPiece.setX(x);
selectedPiece.setY(y);
selectedPiece.setMoved(true);
selectedPiece.setMoved(true); // Marque la pièce comme ayant bougé
// Déplacement de la tour si roque
@ -205,21 +214,13 @@ public class Board {
// Clear selection & highlights
hasSelectedPiece = false;
highlightedSquares.clear();
if (!turnWhite) {
Move aiMove = ai.computeBestMove(this);
if (aiMove != null) {
playMove(aiMove);
}
}
// Invalid move: just unselect
else {
hasSelectedPiece = false;
highlightedSquares.clear();
}
}
}
}
@ -341,52 +342,6 @@ public class Board {
}
public void playMove(Move move) {
Piece selectedPiece = board[move.getFromX()][move.getFromY()];
if (selectedPiece == null) return;
boolean isEnPassant = selectedPiece.getType() == PieceType.Pawn &&
enPassantTarget != null &&
move.getToX() == enPassantTarget[0] &&
move.getToY() == enPassantTarget[1] &&
board[move.getToX()][move.getToY()] == null;
previousBoard = cloneBoard(board);
board[move.getToX()][move.getToY()] = selectedPiece;
board[move.getFromX()][move.getFromY()] = null;
selectedPiece.setX(move.getToX());
selectedPiece.setY(move.getToY());
selectedPiece.setMoved(true);
if (isEnPassant) {
board[move.getToX()][move.getFromY()] = null;
}
if (selectedPiece.getType() == PieceType.King && Math.abs(move.getToX() - move.getFromX()) == 2) {
if (move.getToX() > move.getFromX()) {
Piece rook = board[7][move.getToY()];
board[5][move.getToY()] = rook;
board[7][move.getToY()] = null;
rook.setX(5);
rook.setMoved(true);
} else {
Piece rook = board[0][move.getToY()];
board[3][move.getToY()] = rook;
board[0][move.getToY()] = null;
rook.setX(3);
rook.setMoved(true);
}
}
enPassantTarget = null;
if (selectedPiece.getType() == PieceType.Pawn &&
Math.abs(move.getToY() - move.getFromY()) == 2) {
enPassantTarget = new int[]{move.getToX(), (move.getFromY() + move.getToY()) / 2};
}
turnWhite = !turnWhite;
turnNumber++;
hasSelectedPiece = false;
highlightedSquares.clear();
// TODO
}
}

View File

@ -143,41 +143,4 @@ public class Move {
private boolean inBounds(int x, int y, int width, int height) {
return x >= 0 && x < width && y >= 0 && y < height;
}
private int fromX;
private int fromY;
private int toX;
private int toY;
public int getFromX() {
return fromX;
}
public void setFromX(int fromX) {
this.fromX = fromX;
}
public int getFromY() {
return fromY;
}
public void setFromY(int fromY) {
this.fromY = fromY;
}
public int getToX() {
return toX;
}
public void setToX(int toX) {
this.toX = toX;
}
public int getToY() {
return toY;
}
public void setToY(int toY) {
this.toY = toY;
}
}

View File

@ -77,76 +77,66 @@ public class JPanelChessBoard extends JPanel {
myGame = simu;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(0, 100, 0)); // Dark green background
if(pieceSelectorMode) {
g.drawImage(
spriteSheet,
0,
0,
Math.round(5*cellWidth()),
Math.round(2*cellHeight()),
null
);
return;
}
if (myGame != null) {
// Define green theme colors
Color lightGreen = new Color(234, 235, 200); // Light green squares
Color darkGreen = new Color(119, 149, 86); // Dark green squares
Color highlightYellow = new Color(247, 247, 105); // Highlight color
Color selectBlue = new Color(66, 135, 245); // Selection color
// Draw chess board squares
float cellWidth = cellWidth();
float cellHeight = cellHeight();
for(int x=0; x<myGame.getWidth(); x++) {
for (int y=0; y<myGame.getHeight(); y++) {
boolean isSelect = myGame.isSelected(x,y);
boolean isHighlight = myGame.isHighlighted(x,y);
// Set square color
if(isSelect) {
g.setColor(selectBlue);
}
else if(isHighlight) {
g.setColor(highlightYellow);
}
else {
g.setColor((x + y) % 2 == 0 ? lightGreen : darkGreen);
}
g.fillRect(
Math.round(x*cellWidth),
Math.round(y*cellHeight),
Math.round(cellWidth),
Math.round(cellHeight)
);
}
}
// Draw grid lines (optional)
g.setColor(new Color(0, 80, 0)); // Darker green for grid lines
for(int x=0; x<myGame.getWidth(); x++) {
int graphX = Math.round(x*cellWidth);
g.drawLine(graphX, 0, graphX, this.getHeight());
}
for (int y=0; y<myGame.getHeight(); y++) {
int graphY = Math.round(y*cellHeight);
g.drawLine(0, graphY, this.getWidth(), graphY);
}
// Draw pieces
for (Piece piece : myGame.getPieces()) {
drawPiece(g, piece);
}
}
super.paintComponent(g);
this.setBackground(Color.black);
if(pieceSelectorMode) {
g.drawImage(
spriteSheet,
0,
0,
Math.round(5*cellWidth()),
Math.round(2*cellHeight()),
null
);
return;
}
if (myGame != null) {
// Draw Interface from state of simulator
float cellWidth = cellWidth();
float cellHeight = cellHeight();
g.setColor(Color.white);
for(int x=0; x<myGame.getWidth();x++) {
for (int y=0; y<myGame.getHeight(); y++) {
boolean isSelect = myGame.isSelected(x,y);
boolean isHighlight = myGame.isHighlighted(x,y);
if(isSelect) {
g.setColor(Color.blue);
}
if(isHighlight) {
g.setColor(Color.yellow);
}
if((x+y)%2==1 || isSelect || isHighlight) {
g.fillRect(
Math.round(x*cellWidth),
Math.round(y*cellHeight),
Math.round(cellWidth),
Math.round(cellHeight)
);
}
if(isHighlight || isSelect) {
g.setColor(Color.white);
}
}
}
g.setColor(Color.gray);
for(int x=0; x<myGame.getWidth();x++) {
int graphX = Math.round(x*cellWidth);
g.drawLine(graphX, 0, graphX, this.getHeight());
}
for (int y=0; y<myGame.getHeight(); y++) {
int graphY = Math.round(y*cellHeight);
g.drawLine(0, graphY, this.getWidth(), graphY);
}
for (Piece piece : myGame.getPieces()) {
drawPiece(g,piece);
}
}
}
private void drawPiece(Graphics g, Piece piece) {

View File

@ -1,6 +1,5 @@
package windowInterface;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
@ -33,257 +32,238 @@ 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 Game game;
private JLabel actionLabel;
private JCheckBox chckbxBlackAI;
private JCheckBox chckbxWhiteAI;
private JPanelChessBoard chessBoard;
private WelcomePanel welcomePanel;
private CardLayout cardLayout;
private JPanel mainPanel;
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));
actionLabel = new JLabel("Waiting For Start");
panelTop.add(actionLabel);
JPanel panelTop = new JPanel();
contentPane.add(panelTop, BorderLayout.NORTH);
JPanel panelRight = new JPanel();
contentPane.add(panelRight, BorderLayout.EAST);
panelRight.setLayout(new GridLayout(4,1));
JButton btnGo = new JButton("Start/Restart");
btnGo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicButtonStart();
}
});
panelTop.add(btnGo);
actionLabel = new JLabel("Waiting For Start");
panelTop.add(actionLabel);
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);
JButton btnGo = new JButton("Start/Restart");
btnGo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicButtonStart();
}
});
panelTop.add(btnGo);
JButton btnSave = new JButton("Save To File");
btnSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicSaveToFileButton();
}
});
panelRight.add(btnSave);
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);
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();
}
});
panelTop.add(btnUndo);
chckbxWhiteAI = new JCheckBox("WhiteAI");
chckbxWhiteAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(true);
}
});
panelTop.add(chckbxWhiteAI);
chckbxBlackAI = new JCheckBox("BlackAI");
chckbxBlackAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(false);
}
});
panelTop.add(chckbxBlackAI);
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);
// Create card layout for switching panels
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
// Create panels
welcomePanel = new WelcomePanel(this);
chessBoard = new JPanelChessBoard(this);
// Add panels to card layout
mainPanel.add(welcomePanel, "welcome");
mainPanel.add(chessBoard, "game");
// Show welcome screen first
cardLayout.show(mainPanel, "welcome");
// Add main panel to frame
contentPane.add(mainPanel, BorderLayout.CENTER);
}
public void showGameBoard() {
cardLayout.show(mainPanel, "game");
instantiateSimu(); // Initialize the game
}
JButton btnUndo = new JButton("Undo");
btnUndo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicUndoButton();
}
public void setStepBanner(String s) {
turnLabel.setText(s);
}
});
panelTop.add(btnUndo);
chckbxWhiteAI = new JCheckBox("WhiteAI");
chckbxWhiteAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(true);
}
public void setBorderBanner(String s) {
borderLabel.setText(s);
}
});
panelTop.add(chckbxWhiteAI);
chckbxBlackAI = new JCheckBox("BlackAI");
chckbxBlackAI.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clicAIToggle(false);
}
public JPanelChessBoard getPanelDessin() {
return chessBoard;
}
public void instantiateSimu() {
if(game == null) {
game = new Game(this);
chessBoard.setGame(game);
game.start();
}
}
});
panelTop.add(chckbxBlackAI);
public void clicButtonStart() {
this.instantiateSimu();
game.setDefaultSetup();
}
public void clickButtonAdder() {
chessBoard.toggleAdderMode();
}
public void clickButtonSelector() {
chessBoard.togglePieceSelector();
}
panelDraw = new JPanelChessBoard(this);
contentPane.add(panelDraw, BorderLayout.CENTER);
}
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;
chessBoard.setGame(game);
this.repaint();
}
}
public void setStepBanner(String s) {
turnLabel.setText(s);
}
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(chessBoard.isPieceAdderMode()?"Adding Piece":
(chessBoard.isPieceSelectorMode()?"Selecting Piece to Add":
"Playing"));
this.repaint();
}
public void eraseLabels() {
this.setStepBanner("Turn : X");
}
}
public void setBorderBanner(String s) {
borderLabel.setText(s);
}
public JPanelChessBoard getPanelDessin() {
return panelDraw;
}
public void instantiateSimu() {
if(game==null) {
game = new Game(this);
panelDraw.setGame(game);
game.start();
}
}
public void clicButtonStart() {
this.instantiateSimu();
game.setDefaultSetup();
}
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");
}
}

View File

@ -1,46 +0,0 @@
package windowInterface;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class WelcomePanel extends JPanel {
private JButton startButton;
private MyInterface mainInterface;
public WelcomePanel(MyInterface mainInterface) {
this.mainInterface = mainInterface;
setLayout(new BorderLayout());
setBackground(new Color(0, 100, 0)); // Dark green background
// Create title label
JLabel titleLabel = new JLabel("Chess Game", SwingConstants.CENTER);
titleLabel.setFont(new Font("Serif", Font.BOLD, 48));
titleLabel.setForeground(Color.WHITE);
titleLabel.setBorder(BorderFactory.createEmptyBorder(50, 0, 30, 0));
// Create subtitle label
JLabel subtitleLabel = new JLabel("Let the game begin!", SwingConstants.CENTER);
subtitleLabel.setFont(new Font("Serif", Font.ITALIC, 24));
subtitleLabel.setForeground(new Color(234, 235, 200)); // Light green
// Create start button
startButton = new JButton("Start Game");
startButton.setFont(new Font("SansSerif", Font.BOLD, 18));
startButton.setBackground(new Color(119, 149, 86)); // Dark green
startButton.setForeground(Color.WHITE);
startButton.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
startButton.addActionListener(e -> mainInterface.showGameBoard());
// Center panel for button
JPanel buttonPanel = new JPanel();
buttonPanel.setOpaque(false);
buttonPanel.add(startButton);
// Add components
add(titleLabel, BorderLayout.NORTH);
add(subtitleLabel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
}
}