check draw

This commit is contained in:
2025-04-13 12:57:13 +02:00
parent 224a09c711
commit b336784a5d
15 changed files with 108 additions and 26 deletions

View File

@@ -59,7 +59,11 @@ public class CommandExecutor {
} }
private void switchPlayerTurn() { private void switchPlayerTurn() {
this.game.switchPlayerTurn(); if(this.game.switchPlayerTurn()) {
this.dispatcher.onDraw();
this.dispatcher.onGameEnd();
return;
}
this.dispatcher.onPlayerTurn(this.game.getPlayerTurn()); this.dispatcher.onPlayerTurn(this.game.getPlayerTurn());
} }

View File

@@ -42,4 +42,7 @@ public abstract class GameAdaptator implements GameListener {
@Override @Override
public void onMoveNotAllowed(Move move) {} public void onMoveNotAllowed(Move move) {}
@Override
public void onDraw() {}
} }

View File

@@ -10,7 +10,7 @@ import chess.model.Color;
import chess.model.Coordinate; import chess.model.Coordinate;
import chess.model.Move; import chess.model.Move;
public class GameDispatcher implements GameListener{ public class GameDispatcher implements GameListener {
private final List<GameListener> listeners; private final List<GameListener> listeners;
private final ExecutorService executor; private final ExecutorService executor;
@@ -88,6 +88,11 @@ public class GameDispatcher implements GameListener{
asyncForEachCall((l) -> l.onMoveNotAllowed(move)); asyncForEachCall((l) -> l.onMoveNotAllowed(move));
} }
@Override
public void onDraw() {
asyncForEachCall((l) -> l.onDraw());
}
public void stopService() { public void stopService() {
this.executor.shutdown(); this.executor.shutdown();
} }

View File

@@ -11,6 +11,11 @@ public interface GameListener {
*/ */
void onBoardUpdate(); void onBoardUpdate();
/**
* Invoked when a draw occurs (same position is repeated three times)
*/
void onDraw();
/** /**
* Invoked when the game has ended (by a win or a draw) * Invoked when the game has ended (by a win or a draw)
*/ */

View File

@@ -2,6 +2,7 @@ package chess.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import chess.model.visitor.KingIdentifier; import chess.model.visitor.KingIdentifier;
import chess.model.visitor.PawnIdentifier; import chess.model.visitor.PawnIdentifier;
@@ -137,20 +138,6 @@ public class ChessBoard {
} }
public boolean hasAllowedMoves(Color player) { public boolean hasAllowedMoves(Color player) {
// for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
// for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
// Coordinate attackCoords = new Coordinate(i, j);
// Piece attackPiece = pieceAt(attackCoords);
// if (attackPiece == null)
// continue;
// if (attackPiece.getColor() != player)
// continue;
// if (!getAllowedMoves(attackCoords).isEmpty())
// return true;
// }
// }
return !getAllowedMoves(player).isEmpty(); return !getAllowedMoves(player).isEmpty();
} }
@@ -289,6 +276,19 @@ public class ChessBoard {
return null; return null;
} }
public int hashPlayerPieces(Color color) {
int result = 0;
for (int i = 0; i < Coordinate.VALUE_MAX; i++) {
for (int j = 0; j < Coordinate.VALUE_MAX; j++) {
Piece piece = pieceAt(new Coordinate(i, j));
if (piece == null || piece.getColor() != color)
continue;
result = Objects.hash(result, new Coordinate(i, j), piece);
}
}
return result;
}
public Move getLastMove() { public Move getLastMove() {
return this.lastMove; return this.lastMove;
} }

View File

@@ -1,5 +1,7 @@
package chess.model; package chess.model;
import java.util.Objects;
public class Coordinate { public class Coordinate {
private final int x; private final int x;
private final int y; private final int y;
@@ -42,4 +44,9 @@ public class Coordinate {
public String toString() { public String toString() {
return "(" + this.x + ", " + this.y + ")"; return "(" + this.x + ", " + this.y + ")";
} }
@Override
public int hashCode() {
return Objects.hash(this.x, this.y);
}
} }

View File

@@ -1,5 +1,7 @@
package chess.model; package chess.model;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack; import java.util.Stack;
import chess.controller.PlayerCommand; import chess.controller.PlayerCommand;
@@ -9,6 +11,7 @@ public class Game {
private final ChessBoard board; private final ChessBoard board;
private Color playerTurn; private Color playerTurn;
private final Stack<PlayerCommand> movesHistory; private final Stack<PlayerCommand> movesHistory;
private final Map<Color, Map<Integer, Integer>> traitsPos;
public enum GameStatus { public enum GameStatus {
Check, CheckMate, OnGoing, Pat; Check, CheckMate, OnGoing, Pat;
@@ -17,6 +20,9 @@ public class Game {
public Game(ChessBoard board) { public Game(ChessBoard board) {
this.board = board; this.board = board;
this.movesHistory = new Stack<>(); this.movesHistory = new Stack<>();
this.traitsPos = new HashMap<>();
this.traitsPos.put(Color.Black, new HashMap<>());
this.traitsPos.put(Color.White, new HashMap<>());
} }
public ChessBoard getBoard() { public ChessBoard getBoard() {
@@ -31,8 +37,26 @@ public class Game {
this.playerTurn = Color.White; this.playerTurn = Color.White;
} }
public void switchPlayerTurn() { /**
*
* @param color the current player turn
* @return true if a draw should be declared
*/
private boolean saveTraitPiecesPos(Color color) {
int piecesHash = this.board.hashPlayerPieces(color);
Integer count = this.traitsPos.get(color).get(piecesHash);
this.traitsPos.get(color).put(piecesHash, count == null ? 1 : count + 1);
return count == null ? false : count == (3 - 1);
}
/**
*
* @return true if a draw should occur
*/
public boolean switchPlayerTurn() {
boolean draw = saveTraitPiecesPos(this.playerTurn);
playerTurn = Color.getEnemy(playerTurn); playerTurn = Color.getEnemy(playerTurn);
return draw;
} }
public GameStatus checkGameStatus() { public GameStatus checkGameStatus() {

View File

@@ -15,4 +15,9 @@ public class Bishop extends Piece {
return visitor.visitPiece(this); return visitor.visitPiece(this);
} }
@Override
public int hashCode() {
return 0;
}
} }

View File

@@ -14,4 +14,9 @@ public class King extends Piece {
public <T> T accept(PieceVisitor<T> visitor) { public <T> T accept(PieceVisitor<T> visitor) {
return visitor.visitPiece(this); return visitor.visitPiece(this);
} }
@Override
public int hashCode() {
return 1;
}
} }

View File

@@ -14,4 +14,9 @@ public class Knight extends Piece {
public <T> T accept(PieceVisitor<T> visitor) { public <T> T accept(PieceVisitor<T> visitor) {
return visitor.visitPiece(this); return visitor.visitPiece(this);
} }
@Override
public int hashCode() {
return 2;
}
} }

View File

@@ -18,4 +18,9 @@ public class Pawn extends Piece {
public int multiplier() { public int multiplier() {
return getColor() == Color.White ? 1 : -1; return getColor() == Color.White ? 1 : -1;
} }
@Override
public int hashCode() {
return 3;
}
} }

View File

@@ -14,4 +14,9 @@ public class Queen extends Piece {
public <T> T accept(PieceVisitor<T> visitor) { public <T> T accept(PieceVisitor<T> visitor) {
return visitor.visitPiece(this); return visitor.visitPiece(this);
} }
@Override
public int hashCode() {
return 4;
}
} }

View File

@@ -14,4 +14,9 @@ public class Rook extends Piece {
public <T> T accept(PieceVisitor<T> visitor) { public <T> T accept(PieceVisitor<T> visitor) {
return visitor.visitPiece(this); return visitor.visitPiece(this);
} }
@Override
public int hashCode() {
return 5;
}
} }

View File

@@ -252,4 +252,9 @@ public class Console implements GameListener {
public void onMoveNotAllowed(Move move) { public void onMoveNotAllowed(Move move) {
System.out.println("Move not allowed."); System.out.println("Move not allowed.");
} }
@Override
public void onDraw() {
System.out.println("Repeated positions!");
}
} }

View File

@@ -200,9 +200,7 @@ public class Window extends JFrame implements GameListener {
@Override @Override
public void onWin(chess.model.Color color) { public void onWin(chess.model.Color color) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this, "Victory of " + color); JOptionPane.showMessageDialog(this, "Victory of " + color);
});
} }
@Override @Override
@@ -223,16 +221,12 @@ public class Window extends JFrame implements GameListener {
@Override @Override
public void onPatSituation() { public void onPatSituation() {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this, "Pat. It's a draw!"); JOptionPane.showMessageDialog(this, "Pat. It's a draw!");
});
} }
@Override @Override
public void onSurrender(chess.model.Color color) { public void onSurrender(chess.model.Color color) {
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this, color + " has surrendered."); JOptionPane.showMessageDialog(this, color + " has surrendered.");
});
} }
@Override @Override
@@ -299,4 +293,9 @@ public class Window extends JFrame implements GameListener {
drawInvalid(move); drawInvalid(move);
} }
@Override
public void onDraw() {
JOptionPane.showMessageDialog(this, "Same position was repeated three times. It's a draw!");
}
} }