From 60d2d64a55dd4ed13b23bad0890668a34421fb4a Mon Sep 17 00:00:00 2001 From: cleme Date: Thu, 27 Mar 2025 14:01:09 +0100 Subject: [PATCH] init repo --- .classpath | 6 + .gitignore | 1 + .project | 17 ++ default.board | 9 + pieces.png | Bin 0 -> 954 bytes src/Main.java | 22 ++ src/backend/AutoPlayer.java | 17 ++ src/backend/Board.java | 209 +++++++++++++++++ src/backend/Game.java | 128 ++++++++++ src/backend/Move.java | 43 ++++ src/backend/Piece.java | 33 +++ src/backend/PieceType.java | 28 +++ src/windowInterface/JPanelChessBoard.java | 196 ++++++++++++++++ src/windowInterface/MyInterface.java | 269 ++++++++++++++++++++++ 14 files changed, 978 insertions(+) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 default.board create mode 100644 pieces.png create mode 100644 src/Main.java create mode 100644 src/backend/AutoPlayer.java create mode 100644 src/backend/Board.java create mode 100644 src/backend/Game.java create mode 100644 src/backend/Move.java create mode 100644 src/backend/Piece.java create mode 100644 src/backend/PieceType.java create mode 100644 src/windowInterface/JPanelChessBoard.java create mode 100644 src/windowInterface/MyInterface.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..af6f9dc --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..36aec10 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + ChessFramework + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/default.board b/default.board new file mode 100644 index 0000000..8d83268 --- /dev/null +++ b/default.board @@ -0,0 +1,9 @@ +BR,BN,BB,BQ,BK,BB,BN,BR +BP,BP,BP,BP,BP,BP,BP,BP + , , , , , , , + , , , , , , , + , , , , , , , + , , , , , , , +WP,WP,WP,WP,WP,WP,WP,WP +WR,WN,WB,WQ,WK,WB,WN,WR +W diff --git a/pieces.png b/pieces.png new file mode 100644 index 0000000000000000000000000000000000000000..01cc2f8e0723c40907fcafb30d2044adb1dbd2ff GIT binary patch literal 954 zcmV;r14aCaP)Px&bV)=(RA_n93+CyBv1*&Oq{|ll?3Z58QD>Akp8lm*j5papY>-F z_|!G7(E+F0t>l*zXgEm&ZX>9f!1N&qw-hUoZ8N-SbSxaZQZ4>gfJ_4KfM-5!RAwmJ zMI2yF^HZ4sCXebFxEx$X2W8v9$LS)4Z@xqo@XOd44k-syX8#}){C6-GEbrN>nHrbpkZqDvUnK2wjy?t@5Rq@NFzyDK7;PhNe%$nS?gU#z?WPf0 z=Bh{9D_%50EY8Tmu^pC9C;6oj)D`T4XjaOO$^;XQ5ZQ&5aq|iC@qZ7s^`d)qG970lGuj~I+H*dh?h7i*(5ku$?%p{z4<&P9=274 zgXq}=KDD{39dO#*N`5DSnpAR7{v54Ix!65KGqwpIS0_1l@pkYLe#J+}w~8l>Q`XTg{0sZ)wNvYW cJN8}q0;pW6z5*s-O#lD@07*qoM6N<$g2Ji5hX4Qo literal 0 HcmV?d00001 diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..870cae7 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,22 @@ +import backend.Board; +import backend.Move; +import backend.Piece; +import backend.PieceType; +import windowInterface.MyInterface; + + +public class Main { + + + public static void main(String[] args) { + // testing : + Board testBoard = new Board(8, 8); + testBoard.populateBoard(); + System.out.println(testBoard.toString()); + + // launches graphical interface : + MyInterface mjf = new MyInterface(); + mjf.setVisible(true); + } + +} diff --git a/src/backend/AutoPlayer.java b/src/backend/AutoPlayer.java new file mode 100644 index 0000000..a988a22 --- /dev/null +++ b/src/backend/AutoPlayer.java @@ -0,0 +1,17 @@ +package backend; + +public class AutoPlayer { + + + /** + * returns the best Move to try on provided board for active player + * @param board + * @return + */ + public Move computeBestMove(Board board) { + + return null; + } + + +} diff --git a/src/backend/Board.java b/src/backend/Board.java new file mode 100644 index 0000000..ef8b459 --- /dev/null +++ b/src/backend/Board.java @@ -0,0 +1,209 @@ +package backend; + +import java.util.ArrayList; + +public class Board { + + private int width; + private int height; + private ArrayList pieces; + private int selectedX; + private int selectedY; + private int turnNumber; + private boolean isTurnWhite; + public int getSelectedX () { + return selectedX; + } + public int getSelectedY() { + return selectedY; + } + + + + public Board(int colNum, int lineNum) { // constructor to get width and height + this.width = colNum;//TODO + this.height = lineNum; + this.pieces = new ArrayList<>(); // Initialize the pieces list + } + + public int getWidth() { // returns width of the board (x axis) + return this.width; //TODO + } + + public int getHeight() { + return this.height;//TODO + } + + public int getTurnNumber() { + //TODO + return turnNumber; + } + + public boolean isTurnWhite() { + //TODO + return isTurnWhite; + } + + public void setPiece(boolean isWhite, PieceType type, int x, int y) { + if (x < 0 || x >= width || y < 0 || y >= height) {//TODO + return; //ignore invalid positions + } + pieces.removeIf(piece -> piece.getX() == x && piece.getY() == y); + pieces.add(new Piece(x, y, type, isWhite)); + } + + public void populateBoard() { + cleanBoard();//TODO + + for (int x= 0; x < 8; x++) { + setPiece(true, PieceType.Pawn, x, 6); + } + + setPiece(true, PieceType.Rook, 0, 7); + setPiece(true, PieceType.Knight, 1, 7); + setPiece(true, PieceType.Bishop, 2, 7); + setPiece(true, PieceType.Queen, 3, 7); + setPiece(true, PieceType.King, 4, 7); + setPiece(true, PieceType.Bishop, 5, 7); + setPiece(true, PieceType.Knight, 6, 7); + setPiece(true, PieceType.Rook, 7, 7); + + for (int x = 0; x < 8; x++) { + setPiece(false, PieceType.Pawn, x, 1); + } + setPiece(false, PieceType.Rook, 0, 0); + setPiece(false, PieceType.Knight, 1, 0); + setPiece(false, PieceType.Bishop, 2, 0); + setPiece(false, PieceType.Queen, 3, 0); + setPiece(false, PieceType.King, 4, 0); + setPiece(false, PieceType.Bishop, 5, 0); + setPiece(false, PieceType.Knight, 6, 0); + setPiece(false, PieceType.Rook, 7, 0); + } + + public void cleanBoard() { + pieces.clear();//TODO + selectedX = -1; + selectedY = -1; + turnNumber = 0; + isTurnWhite = true; + } + + public String toString() { + String[][] boardRep = new String[height][width]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + boardRep[y][x] = ".";//TODO + } + } + for (Piece piece : pieces) { + String symbol = piece.getType().getSummary(); + symbol = piece.isWhite() ? symbol.toUpperCase() : symbol.toLowerCase(); + boardRep[piece.getY()][piece.getX()] = symbol; + } + + StringBuilder sb = new StringBuilder(); + for (int y = 0; y< height; y++) { + for (int x =0; x < width; x++) { + sb.append(boardRep[y][x]).append(" "); + } + sb.append("\n"); + } + return sb.toString(); + } + + + public ArrayList getPieces() { + //ArrayList pieces = new ArrayList<>(); + return new ArrayList<>(pieces);//TODO + + //return pieces; + } + + public void userTouch(int x, int y) { + if (x < 0 || x >= width || y < 0 || y >= height) { + return; + } + + if (selectedX == -1 && selectedY == -1) { + Piece piece = getPieceAt(x, y); + if (piece != null ) { + selectedX = x; + selectedY = y; + } + } else { + + if (selectedX == x && selectedY == y) { + selectedX = -1; + selectedY = -1; + } else { + + Piece selectedPiece = getPieceAt(selectedX, selectedY); + if (selectedPiece != null) { + Piece pieceAtDestination = getPieceAt(x, y); + Move move = new Move(selectedX, selectedY, x ,y , selectedPiece, pieceAtDestination); + playMove(move); + selectedX = -1; + selectedY = -1; + } + } + } + } + + public boolean isSelected(int x, int y) { + //TODO + return selectedX == x && selectedY == y; + } + + /* saving-loading feature :*/ + + public String[] toFileRep() { + //TODO + return null; + } + + public Board(String[] array) { + //TODO + + } + + /* The following methods require more work ! */ + + public boolean isHighlighted(int x, int y) { + //TODO + return false; + } + + public void undoLastMove() { + //TODO + + } + + public Board(Board board) { + //TODO + + } + + public void playMove(Move move) { + // Remove any piece at the destination + pieces.removeIf(piece -> piece.getX() == move.getToX() && piece.getY() == move.getToY()); + // Remove the piece at the starting position + pieces.removeIf(piece -> piece.getX() == move.getFromX() && piece.getY() == move.getFromY()); + // Add the piece at the destination + Piece pieceMoved = move.getPieceMoved(); + pieces.add(new Piece(move.getToX(), move.getToY(), pieceMoved.getType(), pieceMoved.isWhite())); + // Update turn information + turnNumber++; + isTurnWhite = !isTurnWhite; + } + + private Piece getPieceAt(int x, int y) { + for (Piece piece : pieces) { + if (piece.getX() == x && piece.getY() == y) { + return piece; + } + } + return null; + } + +} diff --git a/src/backend/Game.java b/src/backend/Game.java new file mode 100644 index 0000000..3b21ad6 --- /dev/null +++ b/src/backend/Game.java @@ -0,0 +1,128 @@ +package backend; + +import windowInterface.MyInterface; + +public class Game extends Thread { + + private AutoPlayer aiPlayer; + private Board board; + + private MyInterface mjf; + private int COL_NUM = 8; + private int LINE_NUM = 8; + private int loopDelay = 250; + boolean[] activationAIFlags; + + public Game(MyInterface mjfParam) { + mjf = mjfParam; + board = new Board(COL_NUM, LINE_NUM); + loopDelay = 250; + LINE_NUM = 8; + COL_NUM = 8; + activationAIFlags = new boolean[2]; + aiPlayer = new AutoPlayer(); + } + + public int getWidth() { + return board.getWidth(); + } + + public int getHeight() { + return board.getHeight(); + } + + public void run() { + while(true) { + aiPlayerTurn(); + mjf.update(board.getTurnNumber(), board.isTurnWhite()); + try { + Thread.sleep(loopDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private boolean isAITurn() { + return activationAIFlags[board.isTurnWhite()?1:0]; + } + + private void aiPlayerTurn() { + if(isAITurn()) { + board.playMove(aiPlayer.computeBestMove(new Board(board))); + } + } + + public void clickCoords(int x, int y) { + int width = this.getWidth(); + int height = this.getHeight(); + if(0>x || 0>y || x>width || y>height) { + System.out.println("Click out of bounds"); + return; + } + if(!isAITurn()) { + + if (board.getSelectedX() == -1 && board.getSelectedY() == -1) { + Piece piece = null; + for (Piece p : board.getPieces()) { + if (p.getX() == x && p.getY() == y) { + piece = p; + break; + } + } + if (piece != null) { + + boolean isWhiteTurn = board.isTurnWhite(); + if (piece.isWhite() != isWhiteTurn) { + System.out.println("Cannot select a" + (piece.isWhite() ? "white" : "black") + "piece on" + (isWhiteTurn ? "White" : "Black") + "'s turn"); + return; + } + } + + } + board.userTouch(x, y); + } + } + + public void setPiece(boolean isWhite, PieceType type, int x, int y) { + board.setPiece(isWhite, type, x, y); + } + + public String[] getFileRepresentation() { + return board.toFileRep(); + } + + public void setLoopDelay(int delay) { + this.loopDelay = delay; + } + + public void setDefaultSetup() { + board.cleanBoard(); + board.populateBoard(); + } + + public void setBoard(String[] array) { + board = new Board(array); + } + + public Iterable getPieces() { + return board.getPieces(); + } + + public boolean isSelected(int x, int y) { + return board.isSelected(x, y); + } + + public boolean isHighlighted(int x, int y) { + return board.isHighlighted(x, y); + } + + public void undoLastMove() { + board.undoLastMove(); + } + + public void toggleAI(boolean isWhite) { + this.activationAIFlags[isWhite?1:0] = !this.activationAIFlags[isWhite?1:0]; + } + +} diff --git a/src/backend/Move.java b/src/backend/Move.java new file mode 100644 index 0000000..4896b00 --- /dev/null +++ b/src/backend/Move.java @@ -0,0 +1,43 @@ +package backend; + +public class Move { + private int fromX; + private int fromY; + private int toX; + private int toY; + private Piece pieceMoved; + private Piece pieceCaptured; + + public Move(int fromX, int fromY, int toX, int toY, Piece pieceMoved, Piece pieceCaptured) { + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + this.pieceMoved = pieceMoved; + this.pieceCaptured = pieceCaptured; + } + + public int getFromX() { + return fromX; + } + + public int getFromY() { + return fromY; + } + + public int getToX() { + return toX; + } + + public int getToY() { + return toY; + } + + public Piece getPieceMoved() { + return pieceMoved; + } + + public Piece getPieceCaptured() { + return pieceCaptured; + } +} diff --git a/src/backend/Piece.java b/src/backend/Piece.java new file mode 100644 index 0000000..710efb3 --- /dev/null +++ b/src/backend/Piece.java @@ -0,0 +1,33 @@ +package backend; + +public class Piece { + + private int x; + private int y; + private PieceType type; + private boolean isWhite; + + public Piece(int x, int y, PieceType type, boolean isWhite) { + this.x = x; + this.y = y; + this.type = type; + this.isWhite = isWhite; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public PieceType getType() { + return this.type; + } + + public boolean isWhite() { + return this.isWhite; + } + +} diff --git a/src/backend/PieceType.java b/src/backend/PieceType.java new file mode 100644 index 0000000..baceab1 --- /dev/null +++ b/src/backend/PieceType.java @@ -0,0 +1,28 @@ +package backend; + +public enum PieceType { + Pawn, Rook, Knight, Bishop, Queen, King; + + public String getSummary() { + if(this == PieceType.Knight) { + return "N"; + } + return this.name().substring(0, 1); + } + + public static PieceType fromSummary(char c) { + if(c=='P') { + return PieceType.Pawn; + }else if(c=='N') { + return PieceType.Knight; + }else if(c=='B') { + return PieceType.Bishop; + }else if(c=='R') { + return PieceType.Rook; + }else if(c=='K') { + return PieceType.King; + } + return PieceType.Queen; + } + +} diff --git a/src/windowInterface/JPanelChessBoard.java b/src/windowInterface/JPanelChessBoard.java new file mode 100644 index 0000000..78a68de --- /dev/null +++ b/src/windowInterface/JPanelChessBoard.java @@ -0,0 +1,196 @@ +package windowInterface; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.JPanel; + +import backend.Game; +import backend.Piece; +import backend.PieceType; + +public class JPanelChessBoard extends JPanel { + + private static final long serialVersionUID = 1L; + private Game myGame; + private MyInterface interfaceGlobal; + private BufferedImage spriteSheet; + private int PIECE_WIDTH = 16; //in spritesheet + private int PIECE_HEIGHT = 16; //in spritesheet + private int MARGIN = 6; + + private boolean pieceSelectorMode; + private boolean selectedPieceIsWhite; + private PieceType selectedPieceType; + private boolean pieceAdderMode; + + public JPanelChessBoard(MyInterface itf) { + super(); + myGame = null; + interfaceGlobal = itf; + selectedPieceIsWhite = true; + selectedPieceType = PieceType.Pawn; + pieceSelectorMode = false; + try { + spriteSheet = ImageIO.read(new File("pieces.png")); + } catch (IOException e) { + e.printStackTrace(); + } + pieceSelectorMode = false; + pieceAdderMode = false; + addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent me) { + // System.out.println(me); + if(pieceSelectorMode) { + int x = Math.round(me.getX()/cellWidth()); + selectedPieceType = PieceType.values()[5-x]; + selectedPieceIsWhite = (me.getY() > cellHeight()); + pieceSelectorMode = false; + } else { + if(myGame == null) { + interfaceGlobal.instantiateSimu(); + } + int x = (me.getX()*myGame.getWidth())/getWidth(); + int y = (me.getY()*myGame.getHeight())/getHeight(); + if(pieceAdderMode) { + //TODO + myGame.setPiece(selectedPieceIsWhite,selectedPieceType, x, y); + pieceAdderMode = false; + } else { + myGame.clickCoords(x,y); + } + } + repaint(); + } + }); + } + + + public void setGame(Game simu) { + myGame = simu; + } + + @Override + protected void paintComponent(Graphics g) { + 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 lines = new LinkedList(); + 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"); + } + +}