1

「友達/内部が必要な場合はデザインが間違っている」などとよく言われますが、ChessPiece.Locationの内部を削除するために次のコードを再設計する方法を教えてもらえますか?

これは現在、ChessBoardにピースを追加すると、ChessPiece.Locationプロパティが一致するように設定されるように使用されています。明らかに、パブリックにすることは内部よりも悪く、プライベートにすることでChessBoardがロケーションを更新できなくなります。洞察をありがとう。

public struct Coord
{
   public Coord(int x, int y) { this.X = x; this.Y = y; }
   public int X { get; private set; }
   public int Y { get; private set; }
}

public class ChessBoard
{
   public ChessBoard() { /*[...]*/ }
   public ChessPiece this[int x, int y]
   {
       get
       {
           // Return ChessPiece at this position (or null)
       }
       set
       {
           // Add ChessPiece at this position and set its Location property
       }
}

public class ChessPiece
{
   public ChessPiece() { /*[...]*/ }
   public Coord Location { get; internal set; }
}
4

4 に答える 4

6

個人的には、ChessPieceがその場所を知っているのは奇妙だと思います。これは、駒自体ではなく、ChessBoardの機能のようです。(テーブルから取り出した後のチェスの駒はどこにありますか?通常はまだ有効な駒です...)

場所/移動ロジックをChessBoardにDictionary<ChessPiece, Coord>配置し、有効な各チェスの駒の場所のを保存します。

于 2009-08-16T23:23:56.920 に答える
2

私の最初の考えは

  • ボードは単なるコンテナです
  • ピースには、パブリック読み取り専用の不変の位置プロパティがあります
  • 初期位置はピース構造で設定されます
  • ピースの移動操作を呼び出すことにより、位置が変更されます
于 2009-08-16T23:22:17.937 に答える
0

私はスティーブに強く同意します。内部と友人には理由がありますが、これは必ずしもその例ではありません。

個人的には、作品に Move(Coord) メソッドを配置します。こうすることで、ピースは自身の動きの有効性を検証できます (さらに、派生クラスを特殊なロジック (ポーンとナイトなど) に使用できます)。Coord は不変である必要があります (座標は移動せず、不変である必要があります。ピースは新しい座標に移動します)。

どの時点でもボードにピースをセットすることはできません。これにより、移動の有効性に対する責任が呼び出し元のクラスに移ります。カスタム ボードを設定する必要がある場合は、新しい開始位置で新しいボードを作成します。

また、戦略アプローチについても同意しません。ここでは戦略パターンが優れていることに同意しますが、必ずしもそれを作品に組み込む必要はありません。戦略をピース固有の戦略クラスに移動します。このようにして、ピースとボードはシンプルでクリーンで、個人対個人のゲームに使用でき、個人対 CPU のゲームに拡張されます

于 2009-08-17T20:49:14.590 に答える
0

「友人/内部が必要な場合、設計が間違っている」などと言う人をよく見かけます。

ばかげていると思います。フレンドと内部が言語に存在するのには正当な理由があります。

ChessPiece.Location の internal を削除します

これにより、ChessPiece.Location を更新できなくなります。

ChessPiece がゲームについて十分に知っていて、それ自体の Location を更新できる場合は問題ありません。たとえば、次のようになります。

public class ChessPiece
{
  public ChessPiece() { /*[...]*/ }
  public Coord Location { get; }
  //a measure of how good it would be to move this piece
  public int GoodnessOfBestMove
  {
    get
    {
      //calculate what self's best possible move is
      ... todo ...
    }
  }
  //an instruction to go head and do that move
  public void Move()
  {
    //do self's self-calculated best move, by updating self's private Location
    ... todo ...
  }
}

class Strategy
{
    void Move()
    {
      ChessPiece bestChessPiece = null;
      foreach (ChessPiece chessPiece in chestPieces)
      {
        if ((bestChessPiece == null) ||
          (chessPiece.GoodnessOfBestMove > bestChessPiece.GoodnessOfBestMove))
        {
          //found a better piece to move
          bestChessPiece = chessPiece;
        }
      }
      //found the best piece to move, so now tell it to move itself
      bestChessPiece.Move();
    }
}

詳細については、Google で検索できる「tell don't ask」と呼ばれる OO の原則があります。

もう 1 つの可能性は、ボードが所有する 2 次元配列に各 ChessPiece を格納することです。ピースを移動するために、ボードは配列内の別のスロットにピースを置きます。ピースがその位置を報告する必要がある場合は、配列内で自分自身を検索します。

上記は代替手段ですが、必ずしもこの問題に対する優れた解決策であると言っているわけではありません。ゲーム戦略を各部分の実装の詳細としてエンコードしたいとは思いません。代わりに、他のクラスが各ピースの場所を更新できるようにする非公開の方法があるかもしれません。

于 2009-08-17T00:02:02.320 に答える