diff --git a/OOP_2B6_PROJECT/src/backend/AutoPlayer.java b/OOP_2B6_PROJECT/src/backend/AutoPlayer.java index c3e0892..e86b525 100644 --- a/OOP_2B6_PROJECT/src/backend/AutoPlayer.java +++ b/OOP_2B6_PROJECT/src/backend/AutoPlayer.java @@ -15,160 +15,53 @@ public class AutoPlayer { int px = p.getX(); int py = p.getY(); - ArrayList candidateMoves = generatePossibleMoves(p, board); - for (int[] move : candidateMoves) { - int nx = move[0]; - int ny = move[1]; - Piece target = board.getPieceAt(nx, ny); - - Board simulated = new Board(board); - simulated.playMove(new Move(p, px, py, nx, ny, target)); - - int score = evaluateBoard(simulated, aiColor); - if (score > bestScore) { - bestScore = score; - bestMove = new Move(p, px, py, nx, ny, target); - } - } - } - } - return bestMove; - } - - private ArrayList generatePossibleMoves(Piece piece, Board board) { - ArrayList moves = new ArrayList<>(); - int x = piece.getX(); - int y = piece.getY(); - boolean isWhite = piece.isWhite(); - - switch (piece.getType()) { - case Pawn: - int dir = isWhite ? -1 : 1; - int oneStepY = y + dir; - int twoStepY = y + 2 * dir; - if (inBounds(x, oneStepY, board) && board.getPieceAt(x, oneStepY) == null) { - moves.add(new int[] { x, oneStepY }); - if ((isWhite && y == 6) || (!isWhite && y == 1)) { - if (board.getPieceAt(x, twoStepY) == null) { - moves.add(new int[] { x, twoStepY }); - } - } - } - for (int dx = -1; dx <= 1; dx += 2) { - int nx = x + dx; - if (inBounds(nx, oneStepY, board)) { - Piece target = board.getPieceAt(nx, oneStepY); - if (target != null && target.isWhite() != isWhite) { - moves.add(new int[] { nx, oneStepY }); - } - } - } - break; - - case Knight: - int[][] knightMoves = { { 2, 1 }, { 1, 2 }, { -1, 2 }, { -2, 1 }, - { -2, -1 }, { -1, -2 }, { 1, -2 }, { 2, -1 } }; - for (int[] d : knightMoves) { - int nx = x + d[0]; - int ny = y + d[1]; - if (inBounds(nx, ny, board)) { - Piece target = board.getPieceAt(nx, ny); - if (target == null || target.isWhite() != isWhite) - moves.add(new int[] { nx, ny }); - } - } - break; - - case Bishop: - addSlideMoves(moves, board, piece, 1, 1); - addSlideMoves(moves, board, piece, 1, -1); - addSlideMoves(moves, board, piece, -1, 1); - addSlideMoves(moves, board, piece, -1, -1); - break; - - case Rook: - addSlideMoves(moves, board, piece, 1, 0); - addSlideMoves(moves, board, piece, -1, 0); - addSlideMoves(moves, board, piece, 0, 1); - addSlideMoves(moves, board, piece, 0, -1); - break; - - case Queen: - for (int dx = -1; dx <= 1; dx++) { - for (int dy = -1; dy <= 1; dy++) { - if (dx != 0 || dy != 0) { - addSlideMoves(moves, board, piece, dx, dy); - } - } - } - break; - - case King: for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; - int nx = x + dx; - int ny = y + dy; - if (inBounds(nx, ny, board)) { - Piece target = board.getPieceAt(nx, ny); - if (target == null || target.isWhite() != isWhite) { - moves.add(new int[] { nx, ny }); + int nx = px + dx; + int ny = py + dy; + + if (nx >= 0 && ny >= 0 && nx < board.getWidth() && ny < board.getHeight()) { + Piece target = getPieceAt(pieces, nx, ny); + if (target == null || target.isWhite() != aiColor) { + int score = (target != null) ? pieceValue(target) : 0; + if (score > bestScore) { + bestScore = score; + bestMove = new Move(p, px, py, nx, ny, target); + } } } } } - break; - } - return moves; - } - - private void addSlideMoves(ArrayList moves, Board board, Piece piece, int dx, int dy) { - int x = piece.getX(); - int y = piece.getY(); - boolean isWhite = piece.isWhite(); - int nx = x + dx; - int ny = y + dy; - - while (inBounds(nx, ny, board)) { - Piece p = board.getPieceAt(nx, ny); - if (p == null) { - moves.add(new int[] { nx, ny }); - } else { - if (p.isWhite() != isWhite) - moves.add(new int[] { nx, ny }); - break; } - nx += dx; - ny += dy; } - } - private boolean inBounds(int x, int y, Board board) { - return x >= 0 && y >= 0 && x < board.getWidth() && y < board.getHeight(); - } - - private int evaluateBoard(Board board, boolean aiColor) { - int score = 0; - for (Piece p : board.getPieces()) { - int value = pieceValue(p); - score += p.isWhite() == aiColor ? value : -value; - } - return score; + return bestMove; } private int pieceValue(Piece piece) { switch (piece.getType()) { - case Pawn: return 10; + case Pawn: return 1; case Knight: - case Bishop: return 30; - case Rook: return 50; - case Queen: return 90; - case King: return 900; + case Bishop: return 3; + case Rook: return 5; + case Queen: return 9; + case King: return 1000; default: return 0; } } + + private Piece getPieceAt(ArrayList list, int x, int y) { + for (Piece p : list) { + if (p.getX() == x && p.getY() == y) return p; + } + return null; + } } +<<<<<<< HEAD //pour maieul push bbh fhfgv +======= +>>>>>>> branch 'master' of https://gitarero.ecam.fr/ilian.bensefia/OOP_2B6_PROJECT.git diff --git a/OOP_2B6_PROJECT/src/backend/Board.java b/OOP_2B6_PROJECT/src/backend/Board.java index 7c4c66f..4773bf8 100644 --- a/OOP_2B6_PROJECT/src/backend/Board.java +++ b/OOP_2B6_PROJECT/src/backend/Board.java @@ -10,7 +10,6 @@ public class Board { private ArrayList pieces; private int turnNumber = 0; private boolean turnIsWhite = true; - private boolean gameOver = false; private Integer selectedX = null; private Integer selectedY = null; @@ -18,31 +17,20 @@ public class Board { private Stack moveHistory = new Stack<>(); + // Indique si la partie est terminée (échec et mat) + private boolean gameOver = false; + public Board(int colNum, int lineNum) { this.width = colNum; this.height = lineNum; this.pieces = new ArrayList<>(); } - public int getWidth() { - return this.width; - } - - public int getHeight() { - return this.height; - } - - public int getTurnNumber() { - return turnNumber; - } - - public boolean isTurnWhite() { - return turnIsWhite; - } - - public boolean isGameOver() { - return gameOver; - } + public int getWidth() { return width; } + public int getHeight() { return height; } + public int getTurnNumber() { return turnNumber; } + public boolean isTurnWhite() { return turnIsWhite; } + public boolean isGameOver() { return gameOver; } public void setPiece(boolean isWhite, PieceType type, int x, int y) { pieces.removeIf(p -> p.getX() == x && p.getY() == y); @@ -50,6 +38,7 @@ public class Board { } public void populateBoard() { + gameOver = false; pieces.clear(); setPiece(true, PieceType.Rook, 0, 7); setPiece(true, PieceType.Knight, 1, 7); @@ -60,7 +49,6 @@ public class Board { setPiece(true, PieceType.Knight, 6, 7); setPiece(true, PieceType.Rook, 7, 7); for (int x = 0; x < 8; x++) setPiece(true, PieceType.Pawn, x, 6); - setPiece(false, PieceType.Rook, 0, 0); setPiece(false, PieceType.Knight, 1, 0); setPiece(false, PieceType.Bishop, 2, 0); @@ -73,12 +61,15 @@ public class Board { } public void cleanBoard() { + gameOver = false; pieces.clear(); selectedX = null; selectedY = null; highlightedPositions.clear(); + if (isInCheck(turnIsWhite)) { + System.out.println("Échec !"); + } moveHistory.clear(); - gameOver = false; } public ArrayList getPieces() { @@ -87,7 +78,6 @@ public class Board { public void userTouch(int x, int y) { if (gameOver) return; - Piece clickedPiece = getPieceAt(x, y); if (selectedX == null || selectedY == null) { @@ -99,6 +89,7 @@ public class Board { } else { Piece selectedPiece = getPieceAt(selectedX, selectedY); if (selectedPiece != null && selectedPiece.isWhite() == turnIsWhite) { +<<<<<<< HEAD // simulate move Board simulation = new Board(this); @@ -132,6 +123,24 @@ public class Board { if (isCheckmate(!turnIsWhite)) { gameOver = true; } +======= + Piece captured = getPieceAt(x, y); + // Détection de la capture du roi (sécuritaire) + if (captured != null && captured.getType() == PieceType.King) { + gameOver = true; + System.out.println("Game over: King captured."); + } + pieces.removeIf(p -> p.getX() == x && p.getY() == y); + pieces.removeIf(p -> p.getX() == selectedX && p.getY() == selectedY); + pieces.add(new Piece(selectedPiece.isWhite(), selectedPiece.getType(), x, y)); + moveHistory.push(new Move(selectedPiece, selectedX, selectedY, x, y, captured)); + turnNumber++; + turnIsWhite = !turnIsWhite; + // Détection d'échec et mat + if (isInCheck(turnIsWhite) && !hasLegalMoves(turnIsWhite)) { + gameOver = true; + System.out.println("Game over: Checkmate."); +>>>>>>> branch 'master' of https://gitarero.ecam.fr/ilian.bensefia/OOP_2B6_PROJECT.git } } @@ -144,67 +153,17 @@ public class Board { public void undoLastMove() { - if (!moveHistory.isEmpty()) { - Move lastMove = moveHistory.pop(); - pieces.removeIf(p -> p.getX() == lastMove.getToX() && p.getY() == lastMove.getToY()); - pieces.add(new Piece( - lastMove.getMovedPiece().isWhite(), - lastMove.getMovedPiece().getType(), - lastMove.getFromX(), - lastMove.getFromY() - )); - if (lastMove.getCapturedPiece() != null) { - pieces.add(lastMove.getCapturedPiece()); - } - turnNumber--; - turnIsWhite = !turnIsWhite; - selectedX = null; - selectedY = null; - highlightedPositions.clear(); - gameOver = false; - } - } - - public boolean isCheckmate(boolean forWhite) { - for (Piece piece : pieces) { - if (piece.isWhite() == forWhite) { - ArrayList moves = getLegalMovesFor(piece); - for (int[] move : moves) { - Board copy = new Board(this); - Piece captured = copy.getPieceAt(move[0], move[1]); - copy.pieces.removeIf(p -> p.getX() == piece.getX() && p.getY() == piece.getY()); - copy.pieces.removeIf(p -> p.getX() == move[0] && p.getY() == move[1]); - copy.pieces.add(new Piece(piece.isWhite(), piece.getType(), move[0], move[1])); - if (!copy.isKingInCheck(forWhite)) { - return false; - } - } - } - } - return isKingInCheck(forWhite); - } - - public boolean isKingInCheck(boolean isWhite) { - Piece king = null; - for (Piece p : pieces) { - if (p.getType() == PieceType.King && p.isWhite() == isWhite) { - king = p; - break; - } - } - if (king == null) return true; - - for (Piece enemy : pieces) { - if (enemy.isWhite() != isWhite) { - ArrayList moves = getLegalMovesFor(enemy); - for (int[] pos : moves) { - if (pos[0] == king.getX() && pos[1] == king.getY()) { - return true; - } - } - } - } - return false; + if (moveHistory.isEmpty()) return; + Move lastMove = moveHistory.pop(); + pieces.removeIf(p -> p.getX() == lastMove.getToX() && p.getY() == lastMove.getToY()); + pieces.add(new Piece(lastMove.getMovedPiece().isWhite(), lastMove.getMovedPiece().getType(), lastMove.getFromX(), lastMove.getFromY())); + if (lastMove.getCapturedPiece() != null) pieces.add(lastMove.getCapturedPiece()); + turnNumber--; + turnIsWhite = !turnIsWhite; + selectedX = null; + selectedY = null; + highlightedPositions.clear(); + gameOver = false; } public boolean isSelected(int x, int y) { @@ -212,9 +171,7 @@ public class Board { } public boolean isHighlighted(int x, int y) { - for (int[] pos : highlightedPositions) { - if (pos[0] == x && pos[1] == y) return true; - } + for (int[] pos : highlightedPositions) if (pos[0] == x && pos[1] == y) return true; return false; } @@ -225,110 +182,77 @@ public class Board { private ArrayList getLegalMovesFor(Piece piece) { ArrayList moves = new ArrayList<>(); - int x = piece.getX(); - int y = piece.getY(); + int x = piece.getX(), y = piece.getY(); boolean isWhite = piece.isWhite(); - switch (piece.getType()) { case Pawn: int dir = isWhite ? -1 : 1; - int startRow = isWhite ? 6 : 1; - int oneStepY = y + dir; - int twoStepY = y + 2 * dir; - - if (inBounds(x, oneStepY) && getPieceAt(x, oneStepY) == null) { - moves.add(new int[]{x, oneStepY}); - if (y == startRow && getPieceAt(x, twoStepY) == null) { - moves.add(new int[]{x, twoStepY}); + int start = isWhite ? 6 : 1; + if (inBounds(x, y + dir) && getPieceAt(x, y + dir) == null) { + moves.add(new int[]{x, y + dir}); + if (y == start && inBounds(x, y + 2 * dir) && getPieceAt(x, y + 2 * dir) == null) + moves.add(new int[]{x, y + 2 * dir}); + } + for (int dx : new int[]{-1, 1}) { + if (inBounds(x + dx, y + dir)) { + Piece p = getPieceAt(x + dx, y + dir); + if (p != null && p.isWhite() != isWhite) moves.add(new int[]{x + dx, y + dir}); } } - - if (inBounds(x - 1, oneStepY)) { - Piece left = getPieceAt(x - 1, oneStepY); - if (left != null && left.isWhite() != isWhite) - moves.add(new int[]{x - 1, oneStepY}); - } - - if (inBounds(x + 1, oneStepY)) { - Piece right = getPieceAt(x + 1, oneStepY); - if (right != null && right.isWhite() != isWhite) - moves.add(new int[]{x + 1, oneStepY}); - } break; - case Rook: addSlideMoves(moves, piece, 1, 0); addSlideMoves(moves, piece, -1, 0); addSlideMoves(moves, piece, 0, 1); addSlideMoves(moves, piece, 0, -1); break; - case Bishop: addSlideMoves(moves, piece, 1, 1); addSlideMoves(moves, piece, 1, -1); addSlideMoves(moves, piece, -1, 1); addSlideMoves(moves, piece, -1, -1); break; - case Queen: - for (int dx = -1; dx <= 1; dx++) { - for (int dy = -1; dy <= 1; dy++) { - if (dx != 0 || dy != 0) { + for (int dx = -1; dx <= 1; dx++) + for (int dy = -1; dy <= 1; dy++) + if (dx != 0 || dy != 0) addSlideMoves(moves, piece, dx, dy); - } - } - } break; - case Knight: - int[][] deltas = { - {2, 1}, {1, 2}, {-1, 2}, {-2, 1}, - {-2, -1}, {-1, -2}, {1, -2}, {2, -1} - }; - for (int[] d : deltas) { - int nx = x + d[0]; - int ny = y + d[1]; + int[][] d = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}}; + for (int[] dd : d) { + int nx = x + dd[0], ny = y + dd[1]; if (inBounds(nx, ny)) { Piece p = getPieceAt(nx, ny); - if (p == null || p.isWhite() != isWhite) - moves.add(new int[]{nx, ny}); + if (p == null || p.isWhite() != isWhite) moves.add(new int[]{nx, ny}); } } break; - case King: - for (int dx = -1; dx <= 1; dx++) { + for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) { if (dx == 0 && dy == 0) continue; - int nx = x + dx; - int ny = y + dy; + int nx = x + dx, ny = y + dy; if (inBounds(nx, ny)) { Piece p = getPieceAt(nx, ny); - if (p == null || p.isWhite() != isWhite) - moves.add(new int[]{nx, ny}); + if (p == null || p.isWhite() != isWhite) moves.add(new int[]{nx, ny}); } } - } break; } - return moves; } private void addSlideMoves(ArrayList moves, Piece piece, int dx, int dy) { - int x = piece.getX(); - int y = piece.getY(); - boolean isWhite = piece.isWhite(); - int nx = x + dx; - int ny = y + dy; - + int x = piece.getX(), y = piece.getY(); + boolean white = piece.isWhite(); + int nx = x + dx, ny = y + dy; while (inBounds(nx, ny)) { Piece p = getPieceAt(nx, ny); if (p == null) { moves.add(new int[]{nx, ny}); } else { - if (p.isWhite() != isWhite) - moves.add(new int[]{nx, ny}); + if (p.isWhite() != white) moves.add(new int[]{nx, ny}); break; } nx += dx; @@ -340,13 +264,44 @@ public class Board { return x >= 0 && y >= 0 && x < width && y < height; } - public Piece getPieceAt(int x, int y) { - for (Piece p : pieces) { - if (p.getX() == x && p.getY() == y) return p; - } + private Piece getPieceAt(int x, int y) { + for (Piece p : pieces) if (p.getX() == x && p.getY() == y) return p; return null; } + private boolean isInCheck(boolean whiteKing) { + Piece king = null; + for (Piece p : pieces) if (p.getType() == PieceType.King && p.isWhite() == whiteKing) { king = p; break; } + if (king == null) return false; + int kx = king.getX(), ky = king.getY(); + for (Piece p : pieces) { + if (p.isWhite() != whiteKing) { + for (int[] m : getLegalMovesFor(p)) if (m[0] == kx && m[1] == ky) return true; + } + } + return false; + } + + public boolean hasLegalMoves(boolean white) { + for (Piece p : pieces) { + if (p.isWhite() == white) { + for (int[] m : getLegalMovesFor(p)) { + Board copy = new Board(this); + Piece captured = copy.getPieceAt(m[0], m[1]); + copy.pieces.removeIf(pc -> pc.getX() == m[0] && pc.getY() == m[1]); + copy.pieces.removeIf(pc -> pc.getX() == p.getX() && pc.getY() == p.getY()); + copy.pieces.add(new Piece(p.isWhite(), p.getType(), m[0], m[1])); + if (!copy.isInCheck(white)) return true; + } + } + } + return false; + } + + public boolean isCheckmate(boolean whiteKing) { + return isInCheck(whiteKing) && !hasLegalMoves(whiteKing); + } + public String[] toFileRep() { String[] output = new String[height + 1]; for (int y = 0; y < height; y++) { @@ -354,11 +309,7 @@ public class Board { for (int x = 0; x < width; x++) { Piece p = getPieceAt(x, y); if (x > 0) row.append(","); - if (p == null) { - row.append(""); - } else { - row.append(p.isWhite() ? "w" : "b").append(p.getType().getSummary()); - } + row.append(p == null ? "" : (p.isWhite() ? "w" : "b") + p.getType().getSummary()); } output[y] = row.toString(); } @@ -381,6 +332,7 @@ public class Board { } } turnIsWhite = array[8].equalsIgnoreCase("W"); + gameOver = false; } public Board(Board board) { @@ -390,28 +342,32 @@ public class Board { this.turnNumber = board.getTurnNumber(); this.turnIsWhite = board.isTurnWhite(); this.moveHistory = new Stack<>(); + this.gameOver = board.isGameOver(); } public void playMove(Move move) { if (move == null || gameOver) return; + Piece captured = move.getCapturedPiece(); + if (captured != null && captured.getType() == PieceType.King) { + gameOver = true; + System.out.println("Game over: King captured."); + } pieces.removeIf(p -> p.getX() == move.getToX() && p.getY() == move.getToY()); pieces.removeIf(p -> p.getX() == move.getFromX() && p.getY() == move.getFromY()); - pieces.add(new Piece( - move.getMovedPiece().isWhite(), - move.getMovedPiece().getType(), - move.getToX(), - move.getToY() - )); + pieces.add(new Piece(move.getMovedPiece().isWhite(), move.getMovedPiece().getType(), move.getToX(), move.getToY())); moveHistory.push(move); turnNumber++; turnIsWhite = !turnIsWhite; selectedX = null; selectedY = null; highlightedPositions.clear(); - - if (isCheckmate(!turnIsWhite)) { + if (isInCheck(turnIsWhite) && !hasLegalMoves(turnIsWhite)) { gameOver = true; + System.out.println("Game over: Checkmate."); } } } +<<<<<<< HEAD // loadhg +======= +>>>>>>> branch 'master' of https://gitarero.ecam.fr/ilian.bensefia/OOP_2B6_PROJECT.git