1

チェス盤を表す配列を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;
        }
    }
}

明らかに、必要なのはどちらか一方(and操作または初期化された値)だけです。また、独自の定義で列挙型を使用できれば素晴らしいのですが、できません。したがって、次のような行:

    Bishop          (null, ChessPieceId.Bishop),
    ...
    White           (ChessPieceId.White, null),

出ています。

私の質問は何でしたか?私が行方不明になっているより良い方法はありますか?また、序数のi​​ntをenumで定義された値に解析して、caseステートメント全体を回避することはできますか?

4

4 に答える 4

3

Cardsに関するSunチュートリアルの例ではEnum、カードのデッキを2つEnumのs-Rankおよび。として表しSuitます。これはあなたの問題と同型です。http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.htmlを参照してください。

適切なコンストラクターを定義することで、任意の追加値でを拡張できるため、Enum順序値にも拘束されないことに注意してください。

于 2010-02-08T20:40:42.857 に答える
2

チェスの駒のクラスを定義するのは理にかなっていますか?

次に、 2つの列挙型をその中に貼り付けることができます。想像してみろ。

于 2010-02-08T20:41:12.723 に答える
1

なぜ列挙型の使用を主張するのですか?それは明らかに適切なツールではありません。

Tokenインターフェイスがあり、その色とタイプ(タイプと色は2つの異なる列挙型)を持つクラスに実装されています。さまざまなタイプのピースに対して複数の実装を作成して、クラス自体にその移動動作を直接入れることができるようにすることもできます。

于 2010-02-08T20:42:22.540 に答える
1

モデリングの提案だけ...

おそらく、抽象的な canMoveTo() メソッドを持つ ChessPiece オブジェクトから始めるでしょう。ポーン、ビショップ、キングなどによって上書きされます... 白/黒は駒の属性です。

したがって、コードからは、常に同じパターン piece.canMoveTo(x1,y1); に従います。または piece.move(x1,y1);

外部から (別のオブジェクトから) オブジェクトの属性を操作するのではなく、常にオブジェクトに何かを要求するという観点から考えてください。

列挙型の問題に関しては、コード化された優れた汎用ソリューションがあり、要件を満たすのに十分な速度/小型/クールではないことがわかるまで、ソリューションの最適化について心配することはありません。列挙型を使用しても、最終的なモデルに適合しないことが判明する場合があります。少しの間、ビット単位の操作を除外することさえあります。

編集:

Java の sub-int を使用すると、すべてがかなり遅くなるというかなり強力な議論を聞いたことがあります。たとえば、バイト配列またはビットフィールドを使用します。スペースのためにそれらが絶対に必要な場合は問題ありませんが、コードを高速化すると思うので使用しないでください。キャッシュと最適化ルーチンを台無しにするだけです。

たとえば、変数「byte b;」を宣言します。それでもRAMでint全体を占有しますが、アクセスするたびに追加のマスキング操作と追加の検証を強制します. 同じことがビット操作に当てはまるかどうかはわかりませんが、あなたがやろうとしていることは、私には時期尚早の最適化のように感じられます。これはプログラミングの最大の悪の 1 つです。

于 2010-02-08T20:47:12.570 に答える