首页 > 解决方案 > 一种优雅的方式来计算每个位置中每种类型的数量

问题描述

我有一个抽象类,它有 1 个属性,如下所示:

PieceColor {
    WHITE, BLACK
}

abstract class Piece {
    PieceColor color

    abstract char getAbbr();
}

此类棋子已由 Bishop Knight Rook King Queen 和 Pawn 类扩展。这些类中的每一个都有一个名为 getAbbr() 的方法,它返回 Piece 的缩写 KQBNRP。

现在我有一个Map<Piece, Tile> piecePlacements代表特定时间当前在棋盘上的所有棋子。

我需要计算有多少种类型的棋子,比如白车、黑皇后等。但是这样做的正常方法太长了,而且很难看。我就是这样做的...

//0: White pieces, 1: Black pieces; 0-5: KQRBNP
    int[][] pieceCount = new int[2][6];

    for(Piece piece : piecePlacements.keySet()) {
        switch (piece.getAbbr()) {
            case 'K' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][0]++;
                } else {
                    pieceCount[1][0]++;
                }
                break;
            case 'Q' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][1]++;
                } else {
                    pieceCount[1][1]++;
                }
                break;
            case 'R' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][2]++;
                } else {
                    pieceCount[1][2]++;
                }
                break;
            case 'B' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][3]++;
                } else {
                    pieceCount[1][3]++;
                }
                break;
            case 'N' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][4]++;
                } else {
                    pieceCount[1][4]++;
                }
                break;
            case 'P' :
                if (piece.color == PieceColor.WHITE) {
                    pieceCount[0][5]++;
                } else {
                    pieceCount[1][5]++;
                }
                break;
         }
    }

必须有一种更优雅的方法,它需要更少的代码行。我的意思是如果有超过 6 种类型的碎片和 2 种颜色会怎样。我不能像这样继续在 switch 语句中添加案例吗?但我不知道如何使它更优雅。

标签: java

解决方案


执行此操作的正常方法是使用枚举enum器(在 Java中调用)。枚举器允许您定义一组值,它们会自动完成所有其余的工作,例如在后台为每个值分配一个唯一的 ID。这是一个简单的例子:

public enum PieceType {
    KING,
    QUEEN,
    ROOK,
    BISHOP,
    KNIGHT,
    PAWN;
}

然后你可以在Piece课堂上使用它。我还将添加适当的封装,这是您应该遵循的。

public class Piece {
    private final PieceType type;
    private final boolean isBlack;

    public Piece(PieceType type, boolean isBlack) {
        this.type = type;
        this.isBlack = isBlack;
    }

    public PieceType getType() {
        return type;
    }

    public boolean isBlack() {
        return isBlack;
    }
}

现在我们已经完成了所有设置,编写 for 循环变得微不足道:

for (Piece piece : piecePlacements) {
    pieceCount[piece.isBlack() ? 1 : 0][piece.getType().ordinal()]++;
}

对于第一个维度的索引,我们使用三元运算符。这允许我们编写条件表达式而无需写出整个 if 语句。在这种情况下,如果piece.isBlack()为真,则插入 的索引1,否则插入 的索引0

对于第二维的索引,我们使用ordinal()方法。这是所有枚举器都隐含的特殊方法。它返回给定枚举器值的唯一 ID,而且好的部分是,您不必担心它是如何得出该 ID 的。它会自动完成这一切。


推荐阅读