forked from fauvet/API_BUT5.5
othello/reversi
This commit is contained in:
parent
8d5bc6b0a7
commit
9d418b6286
218
src/fr/iut_fbleau/raw_api_body/entity/PlateauReversi.java
Normal file
218
src/fr/iut_fbleau/raw_api_body/entity/PlateauReversi.java
Normal file
@ -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<Ply> 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<Ply> givePlies() {
|
||||||
|
if (gameFinished) {
|
||||||
|
throw new NullPointerException("Game is over.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Ply> 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;
|
||||||
|
}
|
||||||
|
}
|
45
src/fr/iut_fbleau/raw_api_body/entity/PlyReversi.java
Normal file
45
src/fr/iut_fbleau/raw_api_body/entity/PlyReversi.java
Normal file
@ -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 + ")";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user