2 回答

TA貢獻1853條經驗 獲得超6個贊
我在這里看到的問題是你有公共財產。這意味著其他人可以設置這些屬性,而無需更新相應的屬性。Piece.fieldField.piece
此外,當您將一個片段從一個字段移動到另一個字段時,您不會從上一個字段中刪除該片段,并且我們允許片段移動到占用的正方形,這將導致多個片段引用同一字段,但該字段將僅引用放置在那里的最后一個片段。
為了解決這些問題,我將屬性設置為只讀(使用私有 setter),強制客戶端調用相應的或方法來更改它們。然后,在此方法中,我們可以驗證要移動到的字段是否未被占用(如果是,我們只需拋出一個異常 - 客戶端必須在調用之前首先檢查這一點),并且我們從中清除。SetMoveMovePieceField
驗證工作可以在 或 類中完成,也可以同時在兩者中完成。我把它們都放在課堂上,以簡化事情。FieldPieceField
即使如此,這也存在問題。您可以直接調用(而不是 ),這將使該片段的值為 。所以這只是一個小小的改進,但不是理想的解決方案。請參閱下文以獲取更好的想法。Field.SetPiece(piece)Piece.MoveTo(field);nullField
public class Field
{
public Piece Piece { get; private set; }
public bool Occupied => Piece != null;
public void ClearPiece()
{
// Remove this field from the piece
if (Piece?.Field == this) Piece.MoveTo(null);
// Remove the piece from this field
Piece = null;
}
public void SetPiece(Piece piece)
{
if (piece != null)
{
if (Occupied)
{
throw new InvalidOperationException(
$"Field is already occupied by {Piece}.");
}
// Remove piece from the piece's previous field
if (piece.Field?.Piece == piece)
{
piece.Field.ClearPiece();
}
}
Piece = piece;
}
}
public class Piece
{
public Field Field { get; private set; }
public void MoveTo(Field field)
{
field.SetPiece(this);
Field = field;
}
}
在對此進行了更多思考之后,我認為更好的解決方案是擁有一個處理所有驗證和移動的類,然后我們可以使和類“愚蠢”。GameManagerFieldPiece
這是有道理的,因為在 上設置 a 之前,還有很多驗證要做。是否可以將此部分移動到該位置(即,如果國王正在檢查并且這不會阻止它,那么就不允許這樣做)。根據棋子的移動規則(即不允許主教的水平位置),棋子的有效著陸點是否有效?是否有任何東西阻擋了到達目的地的路徑?目的地是否被屬于同一玩家的另一塊棋子占據?在移動一塊之前,需要評估很多事情。PieceFieldField
此外,這將允許我們在其他類型的游戲中重用 和 類,這些游戲可能具有不同的規則集,并且執行它們也不同。PieceFieldGameManager

TA貢獻1816條經驗 獲得超4個贊
不!這與循環依賴的概念有關。雖然應用于模塊,但這很可能被視為此類模塊的前身。
更具體地說,這是相互遞歸對象的理想示例。從概念上講,如果替換(半偽代碼)
public class Field
{
public Piece piece {
public Field field {
public Piece piece {
...
}
}
}
}
這是因為對象是相互定義的。然后從理論上講,你可以做這樣的事情
this.field.piece.field.piece...
- 2 回答
- 0 關注
- 147 瀏覽
添加回答
舉報