我有一个具有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语句添加案例吗?但是我不知道如何使它更优雅。
为每个片段的颜色和角色定义枚举。
使用错误的名称Enum#ordinal
获取其定义内每个枚举对象的位置的索引号。使用该数字作为数组的索引。
for ( Piece piece : pieces ) // `Piece` is class with two member fields: a `Color` enum object and a `Role` enum object.
{
pieceCount // Your two-dimensional array.
[ piece.color().ordinal() ] // Get the `Piece` object’s `Color` enum object’s definition position.
[ piece.role().ordinal() ] // Get the `Piece` object’s `Role` enum object’s definition position.
++ // Using those two index numbers as index into your arrays, increment the count.
;
}
使用枚举使此任务更加简单。枚举提供了该方法ordinal
,是一个不正确的名称,因为它实际上返回定义枚举对象的顺序的从零开始的索引(而不是从一开始的序数)。我们可以使用该枚举索引号作为数组的索引。
让我们Piece
用一对嵌套枚举Color
和定义您的记录Role
。
一个记录是在Java中16的新功能,一个简短的方式来写一个类,其主要目的是透明的和不可改变的数据通信。编译器隐式创建构造函数,getter,equals
&hashCode
和toString
。该解决方案不是必需的,但非常适合您的Piece
班级。
package work.basil.example.chess;
public record Piece(Color color , Role role)
{
public enum Color
{ WHITE, BLACK }
public enum Role
{ KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN }
}
因此Piece.Color.WHITE.ordinal()
返回0,而BLACK
返回1。
我们需要一些样本数据。
List < Piece > pieces = List.of(
new Piece( Piece.Color.BLACK , Piece.Role.QUEEN ) ,
new Piece( Piece.Color.BLACK , Piece.Role.KNIGHT ) ,
new Piece( Piece.Color.WHITE , Piece.Role.PAWN )
);
我们可以通过询问每个枚举的长度,以软编码的方式定义您的数组。
int[][] pieceCount = new int[ Piece.Color.values().length ][ Piece.Role.values().length ]; // [2][6]
接下来,我们将棋子循环播放。我们要求每一个Piece
对象Color
,并Role
通过调用名不副实枚举成员领域对象的索引位置ordinal()
的方法。
for ( Piece piece : pieces )
{
pieceCount[ piece.color().ordinal() ][ piece.role().ordinal() ]++;
}
这是整个示例应用程序类。
package work.basil.example.chess;
import java.util.Arrays;
import java.util.List;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.demo();
}
private void demo ( )
{
List < Piece > pieces = List.of(
new Piece( Piece.Color.BLACK , Piece.Role.QUEEN ) ,
new Piece( Piece.Color.BLACK , Piece.Role.KNIGHT ) ,
new Piece( Piece.Color.WHITE , Piece.Role.PAWN )
);
int[][] pieceCount = new int[ Piece.Color.values().length ][ Piece.Role.values().length ]; // [2][6]
for ( Piece piece : pieces )
{
pieceCount[ piece.color().ordinal() ][ piece.role().ordinal() ]++;
}
System.out.println( "pieces = " + pieces );
for ( int i = 0 ; i < pieceCount.length ; i++ )
{
System.out.println( Arrays.toString( pieceCount[ i ] ) );
}
}
}
运行时。
pieces = [Piece[color=BLACK, role=QUEEN], Piece[color=BLACK, role=KNIGHT], Piece[color=WHITE, role=PAWN]]
[0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 1, 0]
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句