帮助消除朋友/内部人士

发布于 2024-08-01 23:47:45 字数 808 浏览 9 评论 0原文

我经常看到人们说“如果你需要朋友/内部,那么你的设计就是错误的”,有人可以告诉我如何重新设计以下代码以消除 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; }
}

I often see people say things like "if you need friend/internal then your design is wrong", could someone tell me how to redesign the following code to eliminate the internal in ChessPiece.Location?

It's currently used so that adding a piece to ChessBoard sets the ChessPiece.Location property to match, obviously making it public would be even worse than internal and making it private would prevent ChessBoard from updating the Location. Thanks for any insights.

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; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如若梦似彩虹 2024-08-08 23:47:45

我个人认为棋子知道它的位置很奇怪——这似乎是棋盘的功能,而不是棋子本身的功能。 (棋子被拿走并离开桌子后,它的位置是什么?它通常仍然是一个有效的棋子......)

我将位置/移动逻辑放入 ChessBoard 中,并存储一个 Dictionary 为每个有效棋子的位置。

I personally think it's strange that the ChessPiece knows it's location - that seems like a function of the ChessBoard, not the piece itself. (What location is a chess piece after it's taken and off the table? It'd normally still be a valid piece...)

I'd put the location/movement logic into the ChessBoard, and store a Dictionary<ChessPiece, Coord> for the location of each valid chess piece.

纸伞微斜 2024-08-08 23:47:45

我的第一个想法是

  • 板只是一个
  • 具有公共只读功能的容器
    不可变的位置属性
  • 初始位置在片段中设置
    构造
  • 通过调用 a 来改变 位置
    对一块进行移动操作

My first thoughts would be

  • board is just a container
  • piece has a public read-only
    immutable position property
  • Initial position is set in piece
    construction
  • Position is changed by invoking a
    move operation on a piece
月寒剑心 2024-08-08 23:47:45

我经常看到人们说“如果你需要朋友/内部,那么你的设计就是错误的”

我认为这很愚蠢。 语言中存在“Friend”和“Internal”是有充分理由的。

消除ChessPiece.Location的内部

,这将导致无法更新 ChessPiece.Location。

如果 ChessPiece 对游戏有足够的了解来更新自己的位置,那就没问题了,例如:

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 搜索。

另一种可能性是棋盘将每个棋子存储在棋盘拥有的二维数组中。 为了移动棋子,棋盘将棋子放入阵列中的不同位置; 当一个棋子想要报告它的位置时,它会在数组中搜索自己。

虽然上述替代方案,但我并不是说它们一定是好的或更好的解决这个问题的方法:我不认为我想将游戏策略编码为每个部分的实现细节; 相反,我可能有一些非私有的方法来让其他类更新每块的位置。

I often see people say things like "if you need friend/internal then your design is wrong"

I think that's silly. Friend and internal exist in the language for good reason.

eliminate the internal in ChessPiece.Location

That would make it impossible to update the ChessPiece.Location.

That would be OK if the ChessPiece knew enough about the game to update its own Location, for example:

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();
    }
}

For further details there's an OO principle called "tell don't ask" which you can Google for.

Another possibility is for the Board to store each ChessPiece in a 2-D array owned by the board. To move a piece, the Board puts the piece in a different slot in the array; and when a piece wants to report its location, it searches for itself in the array.

ALthough the above are alternatives, I'm not saying that they're necessarily good or better solutions for this problem: I don't think I'd want to encode game strategy as an implementation detail of each piece; instead I might have some non-private way to let some other class update the Location of each piece.

岁月如刀 2024-08-08 23:47:45

我非常同意史蒂夫的观点。 内部和朋友在该语言中是有原因的,但这不一定是一个例子。

就我个人而言,我会在这件作品上放置一个 Move(Coord) 方法。 这样,棋子就可以验证其自身动作的有效性(另外,您可以使用派生类来实现专门的逻辑,即兵与骑士)。 坐标应该是不可变的(坐标不移动并且应该是不可变的,棋子移动到新的坐标)。

你不应该能够在任何时候在棋盘上放置一个棋子,这会将你对棋步有效性的责任转移到你的调用类。 如果您需要设置自定义板,请创建一个具有新起始位置的新板。

我也不同意战略方法。 我确实同意策略模式在这里很好,但不一定要内置到作品中。 我会将策略转移到特定于棋子的策略类别中。 这样,您的棋子和棋盘就变得简单、干净,可用于人对人游戏,并可扩展用于人对 CPU 游戏

I agree strongly with Steve. Internal and friend are in the language for a reason, but this isn't necessarily an example of it.

Personally I'd put a Move(Coord) method on the piece. That way the piece can validate the validity of its own moves (plus you can use derived classes for specialized logic, i.e. for pawn vs knight). Coord should be immutable (the coordinate doesn't move and should be immutable, the piece moves to a new coordinate).

You shouldn't be able to just set a piece on the board at any point, that moves your responsibility for the validity of a move to your calling class. If you need to set up custom boards, create a new board with a new starting position.

I'd also disagree about the strategy approach. I do agree a strategy pattern is good here, but it shouldn't necessarily be built into the piece. I would move the strategy into piece-specific strategy classes. This way your pieces and board are simple, clean and usable for a person-vs-person game and extended for a person-vs-cpu game

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文