Merge branch 'master' of

https://gitarero.ecam.fr/yohan.montagne/OOP_2B2_Project.git
This commit is contained in:
marce 2025-05-13 16:19:55 +02:00
commit 33fe6e1ed2
10 changed files with 602 additions and 218 deletions

View File

@ -0,0 +1,47 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class Bishop extends Piece {
public Bishop(boolean isWhite, int x, int y) {
super(isWhite, PieceType.Bishop, x, y);
}
@Override
public PieceType getType() {
return PieceType.Bishop;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int[][] directions = {
{-1, -1}, {-1, 1}, {1, -1}, {1, 1}
};
for (int[] dir : directions) {
int r = row + dir[0];
int c = col + dir[1];
while (board.isInBounds(r, c)) {
Piece target = board.getPieceAt(r, c);
if (target == null) {
moves.add(new Move(this, row, col, r, c));
} else {
if (target.isWhite() != this.isWhite)
moves.add(new Move(this, row, col, r, c));
break;
}
r += dir[0];
c += dir[1];
}
}
return moves;
}
@Override
public Piece clone() {
return new Bishop(this.isWhite, this.x, this.y);
}
}

View File

@ -1,4 +1,8 @@
package backend;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import java.util.ArrayList;
import java.util.LinkedList;
@ -6,36 +10,39 @@ import java.util.LinkedList;
public class Board {
private int Width;
private int Height;
private ArrayList <Piece> pieces;
private int turnNumber = 0;
private boolean turnIsWhite = true;
private Integer selectedX = null;
private Integer selectedY = null;
private ArrayList<int[]> highlightedPositions = new ArrayList<>();
private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
private int Width;
private int Height;
private ArrayList <Piece> pieces;
private int turnNumber = 0;
private boolean turnIsWhite = true;
private Integer selectedX = null;
private Integer selectedY = null;
private ArrayList<int[]> highlightedPositions = new ArrayList<>();
private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
/* ====== AUDIO STATE ====== */
private Clip moveClip;
private boolean soundEnabled = false;
public Board(int colNum, int lineNum) {
this.Width=colNum;
this.Height=lineNum;
this.pieces= new ArrayList <> ();
initMoveSound();
}
public int getWidth() {
@ -47,21 +54,41 @@ private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
}
public int getTurnNumber() {
return turnNumber;
}
public boolean isTurnWhite() {
return turnIsWhite;
}
public void setPiece(boolean isWhite, PieceType type, int x, int y) {
pieces.add(new Piece(isWhite, type, x, y));
// Create a new instance of the specific piece type
Piece newPiece;
switch (type) {
case Pawn:
newPiece = new Pawn(isWhite, x, y);
break;
case King:
newPiece = new King(isWhite, x, y);
break;
case Queen:
newPiece = new Queen(isWhite, x, y);
break;
case Rook:
newPiece = new Rook(isWhite, x, y);
break;
case Bishop:
newPiece = new Bishop(isWhite, x, y);
break;
case Knight:
newPiece = new Knight(isWhite, x, y);
break;
default:
throw new IllegalArgumentException("Unknown piece type");
}
pieces.add(newPiece);
}
public void populateBoard() {
@ -87,158 +114,175 @@ private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
for (int i=0;i<8;i++) {
setPiece(false,PieceType.Pawn,i,6);
}
}
public void cleanBoard() {
pieces.clear();
selectedX = null;
selectedY = null;
pieces.clear();
selectedX = null;
selectedY = null;
}
public ArrayList<Piece> getPieces() {
return pieces;
return pieces;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int y = 0; y < Height; y++) {
for (int x = 0; x < Width; x++) {
Piece pieceAtPos = null;
for (Piece p : pieces) {
if (p.getX() == x && p.getY() == y) {
pieceAtPos = p;
break;
}
}
for (int y = 0; y < Height; y++) {
for (int x = 0; x < Width; x++) {
Piece pieceAtPos = null;
for (Piece p : pieces) {
if (p.getX() == x && p.getY() == y) {
pieceAtPos = p;
break;
}
}
if (pieceAtPos != null) {
char colorChar = pieceAtPos.isWhite() ? 'W' : 'B';
String typeChar = pieceAtPos.getType().getSummary();
sb.append(colorChar).append(typeChar);
} else {
sb.append(", ");
}
if (pieceAtPos != null) {
char colorChar = pieceAtPos.isWhite() ? 'W' : 'B';
String typeChar = pieceAtPos.getType().getSummary();
sb.append(colorChar).append(typeChar);
} else {
sb.append(", ");
}
sb.append(" ");
}
sb.append("\n");
}
sb.append(" ");
}
sb.append("\n");
}
sb.append("Turn: ").append(turnIsWhite ? "White" : "Black");
sb.append(" (Turn number: ").append(turnNumber).append(")\n");
sb.append("Turn: ").append(turnIsWhite ? "White" : "Black");
sb.append(" (Turn number: ").append(turnNumber).append(")\n");
return sb.toString();
return sb.toString();
}
public void userTouch(int x, int y) {
if (selectedX == null && selectedY == null) {
Piece pieceAtPos = getPieceAt(x, y);
if (pieceAtPos != null) {
selectedX = x;
selectedY = y;
}
} else {
if (selectedX == x && selectedY == y) {
selectedX = null;
selectedY = null;
} else {
Piece pieceToMove = getPieceAt(selectedX, selectedY);
if (pieceToMove != null) {
Piece pieceAtDestination = getPieceAt(x, y);
if (pieceAtDestination == null ||
pieceAtDestination.isWhite() != pieceToMove.isWhite()) {
saveStateToHistory();
if (pieceAtDestination != null) {
pieces.remove(pieceAtDestination);
}
pieces.remove(pieceToMove);
pieces.add(new Piece(pieceToMove.isWhite(), pieceToMove.getType(), x, y));
turnNumber++;
turnIsWhite = !turnIsWhite;
}
selectedX = null;
selectedY = null;
}
}
}
}
if (selectedX == null && selectedY == null) {
Piece pieceAtPos = getPieceAt(x, y);
if (pieceAtPos != null) {
selectedX = x;
selectedY = y;
}
} else {
if (selectedX == x && selectedY == y) {
selectedX = null;
selectedY = null;
} else {
Piece pieceToMove = getPieceAt(selectedX, selectedY);
if (pieceToMove != null) {
Piece pieceAtDestination = getPieceAt(x, y);
if (pieceAtDestination == null ||
pieceAtDestination.isWhite() != pieceToMove.isWhite()) {
saveStateToHistory();
if (pieceAtDestination != null) {
pieces.remove(pieceAtDestination);
}
pieces.remove(pieceToMove);
// Create a new instance of the specific piece type
Piece newPiece = makeNewPiece(pieceToMove.getType(),
pieceToMove.isWhite, x, y);
pieces.add(newPiece);
playMoveSound();
turnNumber++;
turnIsWhite = !turnIsWhite;
}
}
selectedX = null;
selectedY = null;
}
}
}
private Piece makeNewPiece(PieceType type, boolean isWhite, int x, int y) {
Piece newPiece;
switch (type) {
case Pawn:
newPiece = new Pawn(isWhite, x, y);
break;
case King:
newPiece = new King(isWhite, x, y);
break;
case Queen:
newPiece = new Queen(isWhite, x, y);
break;
case Rook:
newPiece = new Rook(isWhite, x, y);
break;
case Bishop:
newPiece = new Bishop(isWhite, x, y);
break;
case Knight:
newPiece = new Knight(isWhite, x, y);
break;
default:
throw new IllegalArgumentException("Unknown piece type");
}
return newPiece;
}
private void saveStateToHistory() {
ArrayList<Piece> clonedList = new ArrayList<>();
for(int i =0; i<pieces.size();i++) {
Piece pieceToCopy = pieces.get(i);
Piece copy = new Piece(
pieceToCopy.isWhite(),
Piece copy = makeNewPiece(
pieceToCopy.getType(),
pieceToCopy.isWhite(),
pieceToCopy.getX(),
pieceToCopy.getY());
clonedList.add(copy);
}
boardHistory.add(clonedList);
}
boardHistory.add(clonedList);
}
private Piece getPieceAt(int x, int y) {
for (Piece piece : pieces) {
if (piece.getX() == x && piece.getY() == y) {
return piece;
}
}
return null;
public Piece getPieceAt(int x, int y) {
for (Piece piece : pieces) {
if (piece.getX() == x && piece.getY() == y) {
return piece;
}
}
return null;
}
public boolean isSelected(int x, int y) {
return selectedX != null && selectedY != null && selectedX == x && selectedY == y;
return selectedX != null && selectedY != null && selectedX == x && selectedY == y;
}
/* saving-loading feature :*/
public String[] toFileRep() {
String[] lines = new String[Height + 1];
for (int y = 0; y < Height; y++) {
StringBuilder row = new StringBuilder();
for (int x = 0; x < Width; x++) {
Piece p = getPieceAt(x, y);
if (p != null) {
row.append (p.isWhite() ? "W" : "B").append(p.getType().getSummary());
}
row.append(x < Width - 1? "," : "");
}
lines[y] = row.toString();
}
lines[Height] = isTurnWhite() ? "W" : "B";
return lines;
String[] lines = new String[Height + 1];
for (int y = 0; y < Height; y++) {
StringBuilder row = new StringBuilder();
for (int x = 0; x < Width; x++) {
Piece p = getPieceAt(x, y);
if (p != null) {
row.append (p.isWhite() ? "W" : "B").append(p.getType().getSummary());
}
row.append(x < Width - 1? "," : "");
}
lines[y] = row.toString();
}
lines[Height] = isTurnWhite() ? "W" : "B";
return lines;
}
public Board(String[] array) {
@ -267,8 +311,8 @@ private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
turnIsWhite = false;
}
}
/* The following methods require more work ! */
public boolean isHighlighted(int x, int y) {
@ -277,50 +321,82 @@ private LinkedList<ArrayList<Piece>> boardHistory = new LinkedList<>();
}
public void undoLastMove() {
pieces = boardHistory.getLast();
boardHistory.removeLast();
pieces = boardHistory.getLast();
boardHistory.removeLast();
}
public Board(Board board) {
//TODO
}
public void playMove(Move move) {
//TODO
}
public ArrayList<Move> getAllLegalMoves(boolean isWhite) {
ArrayList<Move> moves = new ArrayList<>();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Piece piece = getPieceAt(row, col);
if (piece != null && piece.isWhite() == isWhite) {
//LinkedList<Move> pieceMoves = piece.getLegalMoves(this, row, col); // This method must exist in Piece
//moves.addAll(pieceMoves);
}
}
}
public ArrayList<Move> getAllLegalMoves(boolean isWhite) {
ArrayList<Move> moves = new ArrayList<>();
return moves;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Piece piece = getPieceAt(row, col);
if (piece != null && piece.isWhite() == isWhite) {
//LinkedList<Move> pieceMoves = piece.getLegalMoves(this, row, col); // This method must exist in Piece
//moves.addAll(pieceMoves);
}
}
}
return moves;
}
public ArrayList<Piece> getAllPieces() {
ArrayList<Piece> pieces = new ArrayList<>();
public ArrayList<Piece> getAllPieces() {
ArrayList<Piece> pieces = new ArrayList<>();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Piece p = getPieceAt(row, col);
if (p != null) {
pieces.add(p);
}
}
}
return pieces;
}
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Piece p = getPieceAt(row, col);
if (p != null) {
pieces.add(p);
}
}
}
return pieces;
}
public boolean isInBounds(int row, int col) {
return row >= 0 && row < 8 && col >= 0 && col < 8;
}
private void initMoveSound() {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(
Board.class.getResource("/sounds/move.wav"));
if (ais == null) { // resource not found
System.err.println("move.wav not on class-path!");
return;
}
moveClip = AudioSystem.getClip();
moveClip.open(ais);
soundEnabled = true; // <<< MISSING LINE
System.out.println("Move-sound loaded OK");
} catch (Exception e) {
e.printStackTrace();
soundEnabled = false;
}
}
private void playMoveSound() {
if (!soundEnabled || moveClip == null) return;
if (moveClip.isRunning()) {
moveClip.stop();
}
moveClip.setFramePosition(0);
moveClip.start();
}
}

View File

@ -0,0 +1,41 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class King extends Piece {
public King(boolean isWhite, int x, int y) {
super(isWhite, PieceType.King, x, y);
}
@Override
public PieceType getType() {
return PieceType.King;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int[] d = {-1, 0, 1};
for (int dr : d) {
for (int dc : d) {
if (dr == 0 && dc == 0) continue;
int r = row + dr;
int c = col + dc;
if (board.isInBounds(r, c)) {
Piece p = board.getPieceAt(r, c);
if (p == null || p.isWhite() != this.isWhite)
moves.add(new Move(this, row, col, r, c));
}
}
}
return moves;
}
@Override
public Piece clone() {
return new King(this.isWhite, this.x, this.y);
}
}

View File

@ -0,0 +1,41 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class Knight extends Piece {
public Knight(boolean isWhite, int x, int y) {
super(isWhite, PieceType.Knight, x, y);
}
@Override
public PieceType getType() {
return PieceType.Knight;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int[][] offsets = {
{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2},
{1, -2}, {1, 2}, {2, -1}, {2, 1}
};
for (int[] offset : offsets) {
int r = row + offset[0];
int c = col + offset[1];
if (board.isInBounds(r, c)) {
Piece p = board.getPieceAt(r, c);
if (p == null || p.isWhite() != this.isWhite)
moves.add(new Move(this, row, col, r, c));
}
}
return moves;
}
@Override
public Piece clone() {
return new Knight(this.isWhite, this.x, this.y);
}
}

View File

@ -1,20 +1,51 @@
package backend;
public class Move {
private final Piece piece;
private final int fromX, fromY, toX, toY;
private final Piece movedPiece;
private final int fromRow, fromCol;
private final int toRow, toCol;
private final Piece capturedPiece; // Optional, can be null
public Move(Piece piece, int fromX, int fromY, int toX, int toY) {
this.piece = piece;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
public Move(Piece movedPiece, int fromRow, int fromCol, int toRow, int toCol) {
this(movedPiece, fromRow, fromCol, toRow, toCol, null);
}
public Piece getPiece() { return piece; }
public int getFromX() { return fromX; }
public int getFromY() { return fromY; }
public int getToX() { return toX; }
public int getToY() { return toY; }
public Move(Piece movedPiece, int fromRow, int fromCol, int toRow, int toCol, Piece capturedPiece) {
this.movedPiece = movedPiece;
this.fromRow = fromRow;
this.fromCol = fromCol;
this.toRow = toRow;
this.toCol = toCol;
this.capturedPiece = capturedPiece;
}
public Piece getMovedPiece() {
return movedPiece;
}
public int getFromRow() {
return fromRow;
}
public int getFromCol() {
return fromCol;
}
public int getToRow() {
return toRow;
}
public int getToCol() {
return toCol;
}
public Piece getCapturedPiece() {
return capturedPiece;
}
@Override
public String toString() {
return movedPiece.getType() + " from (" + fromRow + "," + fromCol + ") to (" + toRow + "," + toCol + ")" +
(capturedPiece != null ? " capturing " + capturedPiece.getType() : "");
}
}

View File

@ -0,0 +1,51 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class Pawn extends Piece {
public Pawn(boolean isWhite, int x, int y) {
super(isWhite, PieceType.Pawn, x, y);
}
@Override
public PieceType getType() {
return PieceType.Pawn;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int direction = isWhite ? -1 : 1;
int startRow = isWhite ? 6 : 1;
// Forward 1 square
int forwardRow = row + direction;
if (board.isInBounds(forwardRow, col) && board.getPieceAt(forwardRow, col) == null) {
moves.add(new Move(this, row, col, forwardRow, col));
// Forward 2 squares from starting position
int doubleForwardRow = row + 2 * direction;
if (row == startRow && board.getPieceAt(doubleForwardRow, col) == null) {
moves.add(new Move(this, row, col, doubleForwardRow, col));
}
}
// Diagonal captures
for (int dc = -1; dc <= 1; dc += 2) {
int c = col + dc;
if (board.isInBounds(forwardRow, c)) {
Piece target = board.getPieceAt(forwardRow, c);
if (target != null && target.isWhite() != this.isWhite)
moves.add(new Move(this, row, col, forwardRow, c));
}
}
return moves;
}
@Override
public Piece clone() {
return new Pawn(this.isWhite, this.x, this.y);
}
}

View File

@ -1,35 +1,39 @@
package backend;
public class Piece {
private int x;
private int y;
private PieceType type;
private boolean isWhite;
import java.util.List;
public int getX() {
return x;
}
public abstract class Piece {
protected int x;
protected int y;
protected PieceType type;
protected boolean isWhite;
public int getY() {
return y;
}
public PieceType getType() {
return type;
}
public boolean isWhite() {
return isWhite;
}
public Piece(boolean isWhite, PieceType type, int x, int y){
this.x=x;
this.y=y;
this.isWhite=isWhite;
this.type=type;
}
public Piece(boolean isWhite, PieceType type, int x, int y) {
this.x = x;
this.y = y;
this.type = type;
this.isWhite = isWhite;
}
public int getX() { return x; }
public int getY() { return y; }
public PieceType getType() { return type; }
public boolean isWhite() { return isWhite; }
public abstract List<Move> getLegalMoves(Board board, int row, int col);
public abstract Piece clone();
}

View File

@ -0,0 +1,49 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class Queen extends Piece {
public Queen(boolean isWhite, int x, int y) {
super(isWhite, PieceType.Queen, x, y);
}
@Override
public PieceType getType() {
return PieceType.Queen;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int[][] directions = {
{-1, 0}, {1, 0}, {0, -1}, {0, 1}, // Rook-like
{-1, -1}, {-1, 1}, {1, -1}, {1, 1} // Bishop-like
};
for (int[] dir : directions) {
int r = row + dir[0];
int c = col + dir[1];
while (board.isInBounds(r, c)) {
Piece target = board.getPieceAt(r, c);
if (target == null) {
moves.add(new Move(this, row, col, r, c));
} else {
if (target.isWhite() != this.isWhite) {
moves.add(new Move(this, row, col, r, c));
}
break;
}
r += dir[0];
c += dir[1];
}
}
return moves;
}
@Override
public Piece clone() {
return new Queen(this.isWhite, this.x, this.y);
}
}

View File

@ -0,0 +1,44 @@
package backend;
import java.util.ArrayList;
import java.util.List;
public class Rook extends Piece {
public Rook(boolean isWhite, int x, int y) {
super(isWhite, PieceType.Rook, x, y);
}
@Override
public PieceType getType() {
return PieceType.Rook;
}
@Override
public List<Move> getLegalMoves(Board board, int row, int col) {
List<Move> moves = new ArrayList<>();
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
for (int[] dir : directions) {
int r = row + dir[0], c = col + dir[1];
while (board.isInBounds(r, c)) {
Piece target = board.getPieceAt(r, c);
if (target == null) {
moves.add(new Move(this, row, col, r, c));
} else {
if (target.isWhite() != this.isWhite)
moves.add(new Move(this, row, col, r, c));
break;
}
r += dir[0];
c += dir[1];
}
}
return moves;
}
@Override
public Piece clone() {
return new Rook(this.isWhite, this.x, this.y);
}
}

Binary file not shown.