我觉得我的项目可以进行一些认真的重组,但我不知道从哪里开始。我不确定我是否通过在一个地方做很多不同的事情而使一切变得比需要的更加复杂,或者它是否本质上很复杂。
我最关心的是检查一个举动是否会限制玩家自己的国王。截至目前,我正在执行移动,然后检查国王是否处于检查状态,如果是,我通过反转移动类型的逻辑来撤消移动,并向游戏抛出一个错误以在那里进行处理。就简单性和可维护性而言,我真的不认为这是最好的方法。我将不胜感激任何意见,谢谢!
public Move movePiece(Position position, Position destination, boolean isWhiteTurn) throws IllegalMoveException {
ChessPiece thisPiece = confirmPiece(position, isWhiteTurn); // Confirms the piece exists and is correct team
validateMove(thisPiece, position, destination); // Confirms the validity of the move for the piece
ChessPiece otherPiece = getPiece(destination);
Move.MoveType moveType = determineMoveType(thisPiece, position, otherPiece, destination);
Move.CheckType checkType = determineCheckType(thisPiece, otherPiece);
try {
performMove(thisPiece, position, otherPiece, destination, moveType); // Handles own king in check
} catch (IllegalMoveException e) {
undoMove(thisPiece, position, otherPiece, destination, moveType);
throw new IllegalMoveException("Move puts own king in check");
}
...
}
private void performMove(ChessPiece thisPiece, Position position, ChessPiece otherPiece,
Position destination, Move.MoveType moveType) throws IllegalMoveException {
if (moveType == Move.MoveType.CASTLE) {
performCastle(thisPiece, position, otherPiece, destination);
}
else if (moveType == Move.MoveType.EN_PASSANT) {
performEnPassant(thisPiece, position, otherPiece, destination);
}
else if (otherPiece != null) {
capturePiece(otherPiece);
movePiece(thisPiece, position, destination);
}
else {
movePiece(thisPiece, position, destination);
}
Position kingPos = findKingPos(thisPiece.isWhite());
if (isAttacked(!thisPiece.isWhite(), kingPos)) {
throw new IllegalMoveException("Move puts own king in check");
}
}
private void undoMove(ChessPiece thisPiece, Position position, ChessPiece otherPiece, Position destination, Move.MoveType moveType) {
if (moveType == Move.MoveType.CASTLE) {
undoCastle(thisPiece, position, otherPiece, destination);
}
if (moveType == Move.MoveType.EN_PASSANT) {
undoEnPassant(thisPiece, position, otherPiece, destination);
}
else {
undoMove(thisPiece, position, destination);
if (otherPiece != null) {
undoCapture(otherPiece, destination);
}
}
}
private void capturePiece(ChessPiece piece) {
Position position = piece.getPosition();
removePiece(position);
if (piece.isWhite()) {
whitePieces.remove(position);
blackCaptured.add(piece);
} else {
blackPieces.remove(position);
whiteCaptured.add(piece);
}
}
private void movePiece(ChessPiece piece, Position position, Position destination) {
if (getPiece(destination) != null) {
throw new IllegalArgumentException("There is a piece there");
}
removePiece(position);
setPiece(piece, destination);
if (piece.isWhite()) {
whitePieces.remove(position);
whitePieces.put(destination, piece);
} else {
blackPieces.remove(position);
blackPieces.put(destination, piece);
}
}
private void undoMove(ChessPiece piece, Position position, Position destination) {
movePiece(piece, destination, position);
}
private void undoCapture(ChessPiece piece, Position position) {
setPiece(piece, position);
if (piece.isWhite()) {
whitePieces.put(position, piece);
blackCaptured.remove(piece);
} else {
blackPieces.put(position, piece);
whiteCaptured.remove(piece);
}
}
private void performCastle(ChessPiece thisPiece, Position position, ChessPiece otherPiece, Position destination) {
if (thisPiece instanceof King) {
if (destination.col() == 0) {
performQueenSideCastle(thisPiece, position, otherPiece, destination);
} else {
performKingSideCastle(thisPiece, position, otherPiece, destination);
}
} else {
if (destination.col() == 0) {
performQueenSideCastle(otherPiece, destination, thisPiece, position);
} else {
performKingSideCastle(otherPiece, destination, thisPiece, position);
}
}
}
private void undoCastle(ChessPiece thisPiece, Position position, ChessPiece otherPiece, Position destination) {
if (thisPiece instanceof King) {
if (destination.col() == 0) {
undoQueenSideCastle(thisPiece, position, otherPiece, destination);
} else {
undoKingSideCastle(thisPiece, position, otherPiece, destination);
}
} else {
if (destination.col() == 0) {
undoQueenSideCastle(otherPiece, destination, thisPiece, position);
} else {
undoKingSideCastle(otherPiece, destination, thisPiece, position);
}
}
}
private void performQueenSideCastle(ChessPiece king, Position kingPosition, ChessPiece rook, Position rookPosition) {
if (king.isWhite()) {
movePiece(king, kingPosition, new Position(0, 2));
movePiece(rook, rookPosition, new Position(0, 3));
} else {
movePiece(king, kingPosition, new Position(7, 2));
movePiece(rook, rookPosition, new Position(7, 3));
}
}
private void undoQueenSideCastle(ChessPiece king, Position kingPosition, ChessPiece rook, Position rookPosition) {
if (king.isWhite()) {
undoMove(king, kingPosition, new Position(0, 2));
undoMove(rook, rookPosition, new Position(0, 3));
} else {
undoMove(king, kingPosition, new Position(7, 2));
undoMove(rook, rookPosition, new Position(7, 3));
}
}
private void performKingSideCastle(ChessPiece king, Position kingPosition, ChessPiece rook, Position rookPosition) {
if (king.isWhite()) {
movePiece(king, kingPosition, new Position(0, 6));
movePiece(rook, rookPosition, new Position(0, 5));
} else {
movePiece(king, kingPosition, new Position(7, 6));
movePiece(rook, rookPosition, new Position(7, 5));
}
}
private void undoKingSideCastle(ChessPiece king, Position kingPosition, ChessPiece rook, Position rookPosition) {
if (king.isWhite()) {
undoMove(king, kingPosition, new Position(0, 6));
undoMove(rook, rookPosition, new Position(0, 5));
} else {
undoMove(king, kingPosition, new Position(7, 6));
undoMove(rook, rookPosition, new Position(7, 5));
}
}
private void performEnPassant(ChessPiece thisPiece, Position position, ChessPiece otherPiece, Position destination) {
movePiece(thisPiece, position, destination);
capturePiece(otherPiece);
}
private void undoEnPassant(ChessPiece thisPiece, Position position, ChessPiece otherPiece, Position destination) {
undoMove(thisPiece, position, destination);
undoCapture(otherPiece, otherPiece.getPosition());
}
public record Move(Position position, Position destination, ChessPiece movedPiece, ChessPiece capturedPiece, Move.MoveType moveType, Move.CheckType checkType) {
public enum MoveType {
NORMAL, CASTLE, EN_PASSANT, PROMOTION
}
public enum CheckType {
NONE, CHECK, STALEMATE, CHECKMATE
}
}
└── src
├── controller
│ └── Game.java
├── model
│ ├── Bishop.java
│ ├── Board.java
│ ├── ChessPiece.java
│ ├── King.java
│ ├── Knight.java
│ ├── Pawn.java
│ ├── Queen.java
│ └── Rook.java
└── util
├── ChessPieceFactory.java
├── IllegalMoveException.java
├── Move.java
└── Position.java
一个主要问题是您的异常称为
IllegalMoveException
,但顶级中的捕获代码假定由于国王被移动而导致这是无效的移动。你不应该这样做 - 如果这是一个无效的移动,则撤消该移动,并让该异常冒出来。不要将该异常扔进垃圾箱,然后创建一个新的异常,并注明“它一定是在限制你自己的国王”。
“移动,然后检查,如果失败,则取消移动”的原则不一定是坏主意。如果您真的想在这方面走得更远,请选择不可变的数据模型。你不用移动棋盘上的棋子——而是构建一个新棋盘。这就是字符串的工作原理:
String x = "Hello!";
x.toLowerCase();
System.out.println(x); // prints Hello!, with uppercase
那是因为字符串是不可变的。
toLowerCase()
不会改变你调用它的字符串,它会产生一个新的字符串。你必须写x = x.toLowerCase()
。你可以用同样的方式进行设置。它“更昂贵”,因为您以这种方式复制大量棋盘,但国际象棋棋盘并不是那么大,它可以让您做有趣的事情,例如使用棋盘对象作为地图中的键,这样您可以记住您所做的任何点值计算。请注意,“轮到谁了”是棋盘的一部分。
这样,您就可以按照移动“建议”的方式生成新板,并检查该新板的有效性。如果它无效,就扔掉它并继续。如果有效,请将“这是当前板”替换为新生成的板,然后从那里开始。这也意味着您可以跟踪游戏(毕竟,这是一系列棋盘状态)。