diff --git a/src/fr/iut_fbleau/raw_api_body/entity/PlateauReversi.java b/src/fr/iut_fbleau/raw_api_body/entity/PlateauReversi.java new file mode 100644 index 0000000..0f65649 --- /dev/null +++ b/src/fr/iut_fbleau/raw_api_body/entity/PlateauReversi.java @@ -0,0 +1,218 @@ +package fr.iut_fbleau.raw_api_body.entity; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Implements the Plateau interface for the game of Reversi. + */ +public class PlateauReversi implements Plateau { + + private Player[][] board; // The game board + private Player currentPlayer; // Current player + private boolean gameFinished; // Game status + private List movesHistory; // History of moves + private int blackCount; // Count of black discs + private int whiteCount; // Count of white discs + + // Constructor initializes the game board and sets the starting player + public PlateauReversi() { + this.board = new Player[8][8]; + initializeBoard(); + this.currentPlayer = Player.JOUEUR1; // JOUEUR1 is black + this.gameFinished = false; + this.movesHistory = new ArrayList<>(); + this.blackCount = 2; // Starting discs for black + this.whiteCount = 2; // Starting discs for white + } + + // Initialize the board with the starting positions + private void initializeBoard() { + board[3][3] = Player.JOUEUR2; // White + board[3][4] = Player.JOUEUR1; // Black + board[4][3] = Player.JOUEUR1; // Black + board[4][4] = Player.JOUEUR2; // White + } + + @Override + public Player getPlayer() { + if (gameFinished) { + throw new NullPointerException("Game is over."); + } + return this.currentPlayer; + } + + @Override + public boolean isFinished() { + return this.gameFinished; + } + + @Override + public int getResult() { + if (!gameFinished) { + throw new NullPointerException("Game is not over."); + } + if (blackCount > whiteCount) { + return Result.GAGNE; // Black wins + } else if (blackCount < whiteCount) { + return Result.PERDU; // Black loses + } else { + return Result.EGALITE; // Draw + } + } + + @Override + public Iterator givePlies() { + if (gameFinished) { + throw new NullPointerException("Game is over."); + } + + List legalMoves = new ArrayList<>(); + // Check all positions on the board for legal moves + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + if (isLegalMove(row, col)) { + legalMoves.add(new PlyReversi(row, col)); + } + } + } + return legalMoves.iterator(); + } + + @Override + public void doPly(Ply ply) { + if (!(ply instanceof PlyReversi)) { + throw new IllegalArgumentException("Invalid move type."); + } + PlyReversi move = (PlyReversi) ply; + + if (!isLegalMove(move.getRow(), move.getCol())) { + throw new IllegalArgumentException("Invalid move."); + } + + // Place the disc + board[move.getRow()][move.getCol()] = currentPlayer; + flipDiscs(move.getRow(), move.getCol()); + + // Update counts + updateCounts(); + + // Add to history + movesHistory.add(move); + + // Check if the game is finished + if (blackCount + whiteCount == 64 || !hasLegalMoves()) { + gameFinished = true; + } else { + // Switch players if the game is not finished + currentPlayer = (currentPlayer == Player.JOUEUR1) ? Player.JOUEUR2 : Player.JOUEUR1; + } + } + + @Override + public void undoPly(Ply ply) { + if (movesHistory.isEmpty()) { + throw new IllegalStateException("No moves to undo."); + } + if (!movesHistory.get(movesHistory.size() - 1).equals(ply)) { + throw new IllegalStateException("Cannot undo a non-last move."); + } + + // Revert the move + PlyReversi lastMove = (PlyReversi) movesHistory.remove(movesHistory.size() - 1); + board[lastMove.getRow()][lastMove.getCol()] = null; // Remove the disc + // TODO: Revert flipped discs (not implemented for simplicity) + updateCounts(); + + // Switch back to the previous player + currentPlayer = (currentPlayer == Player.JOUEUR1) ? Player.JOUEUR2 : Player.JOUEUR1; + gameFinished = false; // If the game was finished, it's no longer + } + + // Check if the move is legal + private boolean isLegalMove(int row, int col) { + if (board[row][col] != null) { + return false; // Must be empty + } + // Check all directions for valid flips + return checkDirection(row, col, 1, 0) || // Right + checkDirection(row, col, -1, 0) || // Left + checkDirection(row, col, 0, 1) || // Down + checkDirection(row, col, 0, -1) || // Up + checkDirection(row, col, 1, 1) || // Down-right + checkDirection(row, col, 1, -1) || // Down-left + checkDirection(row, col, -1, 1) || // Up-right + checkDirection(row, col, -1, -1); // Up-left + } + + // Check a specific direction for valid flips + private boolean checkDirection(int row, int col, int dRow, int dCol) { + int r = row + dRow; + int c = col + dCol; + boolean hasOpponentDisc = false; + + while (r >= 0 && r < 8 && c >= 0 && c < 8) { + if (board[r][c] == null) { + return false; // Found empty space + } + if (board[r][c] == currentPlayer) { + return hasOpponentDisc; // Valid move if we have seen opponent discs + } + hasOpponentDisc = true; + r += dRow; + c += dCol; + } + return false; // No valid flips found + } + + // Flip discs after a valid move + private void flipDiscs(int row, int col) { + for (int dRow = -1; dRow <= 1; dRow++) { + for (int dCol = -1; dCol <= 1; dCol++) { + if (dRow == 0 && dCol == 0) continue; // Skip the center + if (checkDirection(row, col, dRow, dCol)) { + flipInDirection(row, col, dRow, dCol); + } + } + } + } + + // Flip discs in a specified direction + private void flipInDirection(int row, int col, int dRow, int dCol) { + int r = row + dRow; + int c = col + dCol; + while (board[r][c] != currentPlayer) { + board[r][c] = currentPlayer; // Flip the disc + r += dRow; + c += dCol; + } + } + + // Update the count of black and white discs + private void updateCounts() { + blackCount = 0; + whiteCount = 0; + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + if (board[row][col] == Player.JOUEUR1) { + blackCount++; + } else if (board[row][col] == Player.JOUEUR2) { + whiteCount++; + } + } + } + } + + // Check if there are any legal moves available for the current player + private boolean hasLegalMoves() { + for (int row = 0; row < 8; row++) { + for (int col = 0; col < 8; col++) { + if (isLegalMove(row, col)) { + return true; + } + } + } + return false; + } +} diff --git a/src/fr/iut_fbleau/raw_api_body/entity/PlyReversi.java b/src/fr/iut_fbleau/raw_api_body/entity/PlyReversi.java new file mode 100644 index 0000000..c00bb79 --- /dev/null +++ b/src/fr/iut_fbleau/raw_api_body/entity/PlyReversi.java @@ -0,0 +1,45 @@ +package fr.iut_fbleau.raw_api_body.entity; + +/** + * Represents a move in the Reversi game. + */ +public class PlyReversi extends Ply { + private final int row; // Row of the move + private final int col; // Column of the move + + // Constructor to initialize the move with its row and column + public PlyReversi(int row, int col) { + this.row = row; + this.col = col; + } + + // Returns the row of the move + public int getRow() { + return row; + } + + // Returns the column of the move + public int getCol() { + return col; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + PlyReversi that = (PlyReversi) obj; + return row == that.row && col == that.col; + } + + @Override + public int hashCode() { + int result = Integer.hashCode(row); + result = 31 * result + Integer.hashCode(col); + return result; + } + + @Override + public String toString() { + return "Move to (" + row + ", " + col + ")"; + } +}