正如标题所描述的,我想知道我应该如何过滤一个国际象棋棋子的无效步骤。
棋盘用一个Map<Position, BaseChessman>表示,其中Position是一个带有棋盘位置的枚举(A1 - H8),BaseChessman是一个抽象类,Rook、Bishop、King等具体类都继承了这个抽象类。
现在,对于手头的问题,如果我想移动一个棋子,我需要检查移动对于棋子的类型是否有效。
目前,我正在尝试获得棋子"Rook“的所有正确走法。假设"A1“的棋子现在正站在蓝色圆圈所在的位置,我可以过滤掉除"D8”的黑色皇后之外的所有无效移动。我的问题是,应该如何过滤出被另一个棋子阻挡的走法,就像这种情况下,"D7“阻挡了"D8”。我是否可以将某些字段添加到枚举中,以便从枚举中过滤出被另一块阻塞的移动?(如下图所示)
PS:我知道我的实现是有缺陷的,因为我现在没有检查我当前想要移动的部分是否被阻止了。

用枚举表示的板( hashmap是从这个枚举创建的。Key:位置,值: BaseChessman)
(什么是Ghost?它应该是一个“虚拟”类,充当"None“而不是使用null)
public enum Position {
A8(new Rook(BLACK)), B8(new Knight(BLACK)), C8(new Bishop(BLACK)), D8(new King(BLACK)), E8(new Queen(BLACK)), F8(new Bishop(BLACK)), G8(new Knight(BLACK)), H8(new Rook(BLACK)),
A7(new Pawn(BLACK)), B7(new Pawn(BLACK)), C7(new Pawn(BLACK)), D7(new Pawn(BLACK)), E7(new Pawn(BLACK)), F7(new Pawn(BLACK)), G7(new Pawn(BLACK)), H7(new Pawn(BLACK)),
A6(new Ghost(TRANSPARENT)), B6(new Ghost(TRANSPARENT)), C6(new Ghost(TRANSPARENT)), D6(new Ghost(TRANSPARENT)), E6(new Ghost(TRANSPARENT)), F6(new Ghost(TRANSPARENT)), G6(new Ghost(TRANSPARENT)), H6(new Ghost(TRANSPARENT)),
A5(new Ghost(TRANSPARENT)), B5(new Ghost(TRANSPARENT)), C5(new Ghost(TRANSPARENT)), D5(new Ghost(TRANSPARENT)), E5(new Ghost(TRANSPARENT)), F5(new Ghost(TRANSPARENT)), G5(new Ghost(TRANSPARENT)), H5(new Ghost(TRANSPARENT)),
A4(new Ghost(TRANSPARENT)), B4(new Ghost(TRANSPARENT)), C4(new Ghost(TRANSPARENT)), D4(new Ghost(TRANSPARENT)), E4(new Ghost(TRANSPARENT)), F4(new Ghost(TRANSPARENT)), G4(new Ghost(TRANSPARENT)), H4(new Ghost(TRANSPARENT)),
A3(new Ghost(TRANSPARENT)), B3(new Ghost(TRANSPARENT)), C3(new Ghost(TRANSPARENT)), D3(new Ghost(TRANSPARENT)), E3(new Ghost(TRANSPARENT)), F3(new Ghost(TRANSPARENT)), G3(new Ghost(TRANSPARENT)), H3(new Ghost(TRANSPARENT)),
A2(new Pawn(WHITE)), B2(new Pawn(WHITE)), C2(new Pawn(WHITE)), D2(new Pawn(WHITE)), E2(new Pawn(WHITE)), F2(new Pawn(WHITE)), G2(new Pawn(WHITE)), H2(new Pawn(WHITE)),
A1(new Rook(WHITE)), B1(new Knight(WHITE)), C1(new Bishop(WHITE)), D1(new King(WHITE)), E1(new Queen(WHITE)), F1(new Bishop(WHITE)), G1(new Knight(WHITE)), H1(new Rook(WHITE));
private BaseChessman chessman;
private Position(BaseChessman chessman) {
this.chessman = chessman;
}
public BaseChessman getChessman(){
return this.chessman;
}
}我的函数,应该返回该位置的可能移动列表。(当前未使用nextPosition)
private List<Position> getPossibleRookMoves(Color playerColor, Map<Position, BaseChessman> mapOfChessboard, Position currentPosition, Position nextPosition){
String position = currentPosition.toString();
String pos1 = position.substring(0, 1);
String pos2 = position.substring(1, 2);
return mapOfChessboard.keySet()
.stream()
.filter(pos -> (pos.toString().contains(pos1)) || pos.toString().contains(pos2))//Filter out any row and col that does not match "currentPosition"
.filter(pos -> !(pos.toString().equals(position))) //Filter out the spot the piece stands on
.filter(pos -> (pos.getChessman().getColor() != playerColor)) //Filter out spots where same color pieces stands on
.sorted()
.collect(Collectors.toList());
}你将如何解决这个问题?您会切换到2D数组而不是枚举和映射吗?
发布于 2020-06-18 06:02:18
我相信你的数据模型对于问题域是有缺陷的。在你的代码中有很多这样的迹象:必须通过位置名称解码列和行,当它们是真正独立的概念时将它们存储在你的位置枚举中,必须人为地表示一个“空”部分,没有简单的方法来获取两个位置之间的位置。
我建议使用以下模型:
public enum Position {
A1(1, 1), A2(2, 1) ....
private final int column;
private final int row;
}
public class Move {
private final List<Position> path;
}
public enum PieceType {
PAWN, KNIGHT, BISHOP ...
private final Function<Position,Stream<Move>> moveGenerator;
public Stream<Move> getMoves(Position origin) {
return moveGenerator.apply(origin);
}
}
public enum Colour {
WHITE, BLACK;
}
public class Piece {
private final PieceType type;
private final Colour colour;
}
public class Board {
private final EnumMap<Position,Piece> pieces;
public Stream<Move> getLegalMoves() {
return pieces.entrySet().stream()
.flatMap(e -> e.getValue().getType().getMoves(e.getKey()))
.filter(this::isLegal);
}
private boolean isLegal(Move move) {
Piece piece = pieces.get(move.getOrigin());
return (!pieces.containsKey(move.getDestination())
|| pieces.get(move.getDestination()).getColour() != piece.getColour()))
&& move.getIntermediatePositions().noneMatch(pieces::containsKey))
}
}有了这个模型,你不需要为每种类型的棋子都有单独的类,你可以同样对待每一步棋。为了简单起见,我省略了getter方法,并且可能需要额外的方法来获取同一行、列等中的所有位置,以帮助生成移动。
https://stackoverflow.com/questions/62438037
复制相似问题