如果我在C中保留一个代表国际象棋棋盘的数组,我可能会用以下大致类似的项目填充它:
enum CHESSPIECE {
none = 0,
pawn, knight, bishop, rook, queen, king,
type_mask = 7,
white = 8,
white_pawn, white_knight, white_bishop, white_rook, white_queen, white_king,
black = 16,
black_pawn, black_kight, black_bishop, black_rook, black_queen, black_king,
color_mask = 24
} chessPiece;
因此允许逻辑看起来像:
if (board[i][j] & color_mask == currentColor)
{
impossibleMove = true; // or some-such
}
在Java中,我只是发现按位&对枚举的操作不受支持,而且,相当可怕的EnumSet不容易应用,因为一件作品不能是黑白,也不是白车王。
所以我的想法是:
public enum ChessPieceId {
None (null, null),
Pawn (null, null),
Knight (null, null),
Bishop (null, null),
Rook (null, null),
Queen (null, null),
King (null, null),
Type_Mask (null, null),
White (null, null),
White_Pawn (ChessPieceId.White, ChessPieceId.Pawn),
White_Knight (ChessPieceId.White, ChessPieceId.Knight),
White_Bishop (ChessPieceId.White, ChessPieceId.Bishop),
White_Rook (ChessPieceId.White, ChessPieceId.Rook),
White_Queen (ChessPieceId.White, ChessPieceId.Queen),
White_King (ChessPieceId.White, ChessPieceId.King),
SkipA (null, null),
Black (null, null),
Black_Pawn (ChessPieceId.Black, ChessPieceId.Pawn),
Black_Knight (ChessPieceId.Black, ChessPieceId.Knight),
Black_Bishop (ChessPieceId.Black, ChessPieceId.Bishop),
Black_Rook (ChessPieceId.Black, ChessPieceId.Rook),
Black_Queen (ChessPieceId.Black, ChessPieceId.Queen),
Black_King (ChessPieceId.Black, ChessPieceId.King),
SkipB (null, null),
Color_Mask (null, null);
private final ChessPieceId color;
private final ChessPieceId type;
ChessPieceId(ChessPieceId pColor, ChessPieceId pType){
this.color = pColor;
this.type = pType;
}
ChessPieceId color() { return color; }
ChessPieceId type() { return type; }
// & operator should be built in. I considered an EnumSet but...
ChessPieceId and(ChessPieceId pSecond) {
switch(ChessPieceId.this.ordinal() & pSecond.ordinal()) {
case 0: //None.ordinal() etc. [if only Java were smarter]
return None;
case 1: return Pawn;
case 2: return Knight;
case 3: return Bishop;
case 4: return Rook;
case 5: return Queen;
case 6: return King;
case 7: return Type_Mask;
case 8: return White;
case 9: return White_Pawn;
case 10: return White_Knight;
case 11: return White_Rook;
case 12: return White_Bishop;
case 13: return White_Queen;
case 14: return White_King;
//case 15: return SkipA;
case 16: return Black;
case 17: return Black_Pawn;
case 18: return Black_Knight;
case 19: return Black_Rook;
case 20: return Black_Bishop;
case 21: return Black_Queen;
case 22: return Black_King;
//case 23: return SkipB;
case 24: return Color_Mask;
default:
return None;
}
}
}
显然,我只需要一个或另一个(和操作,或初始值)。如果我可以在它自己的定义中使用枚举类型,那肯定会很棒,但我不能。所以像这样的行:
Bishop (null, ChessPieceId.Bishop),
...
White (ChessPieceId.White, null),
出去了。
我的问题是什么?有没有更好的方式让我失踪。我也可以将序数的int解析为枚举定义的值,避免整个case语句吗?
答案 0 :(得分:3)
在Card
上的Sun教程中的Enum
示例中,它们代表一副牌为两个Enum
s - Rank
和Suit
。这与你的问题是同构的。请参阅http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html。
请注意,您可以通过定义适当的构造函数来增加Enum
您想要的任何额外值,因此您也不会受序数值的约束。
答案 1 :(得分:2)
为棋子定义一个课程是不是有意义?
然后你可以在其中粘贴两个枚举。想象一下。
答案 2 :(得分:1)
为什么你坚持使用枚举?它显然不是合适的工具。
我会有一个Token接口,并在类中实现它的颜色和类型(类型和颜色是两个不同的枚举)。你甚至可以为不同类型的作品设置多个实现,这样你就可以直接在课堂上运用它的运动行为....
答案 3 :(得分:1)
只是建模建议......
我可能从一个具有抽象canMoveTo()方法的ChessPiece对象开始。它会被典当,主教,国王所覆盖......白/黑是该作品的一个属性。
所以从你的代码中,它总是遵循相同的模式,piece.canMoveTo(x1,y1);或piece.move(x1,y1);
总是考虑让你的对象做某事 - 而不是从外部(来自另一个对象)操作对象的属性。
至于枚举问题,我不会担心优化解决方案,直到你有一个很好的通用解决方案编码,你发现它不是快/小/酷足以满足你的要求。事实证明,使用枚举甚至不适合您的最终模型。我甚至会稍微留下按位操作。
编辑:
我听过一些非常强大的论据,说明为Java的sub-int减慢了一切。例如,使用字节数组或位域。如果你绝对需要它们的空间,很好,但不要使用它们,因为你认为它们会让你的代码更快 - 它们只是搞乱缓存和优化例程。
例如,声明变量“byte b;”仍然占用ram中的整个int,但每次访问时都会强制执行额外的屏蔽操作和其他验证。我不确定同样的事情是否适用于位操作,但是你想要做的事情真的让我觉得过早优化 - 一个最大的编程邪恶。