Проблема, которую я вижу здесь, состоит в том, что у вас есть Piece.field
и Field.piece
в качестве общедоступных свойств.Это означает, что другие могут устанавливать эти свойства без обновления соответствующего.
Кроме того, когда вы перемещаете фигуру из одного поля в другое, вы не удаляете фигуру из предыдущего поля, и мы позволяем фигурампереместиться на занятые квадраты, что приведет к тому, что несколько фрагментов будут ссылаться на одно и то же поле, но поле будет ссылаться только на последний фрагмент, размещенный там.приватный установщик), заставляя клиентов вызывать соответствующий метод Set
или Move
для их изменения.Затем в этом методе мы можем убедиться, что поле, в которое мы перемещаемся, не занято (если оно есть, мы просто выкидываем исключение - клиент должен сначала проверить это перед вызовом Move
), и что мы очищаем Piece
из Field
, из которого мы переехали.
Работу по проверке можно выполнить в классе Field
или Piece
, либо в обоих.Я помещаю все это в класс Field
, чтобы упростить вещи.
Тем не менее, есть проблемы с этим.Вы можете вызвать Field.SetPiece(piece)
напрямую (вместо Piece.MoveTo(field);
), что оставит кусок со значением null
для Field
.Так что это лишь небольшое улучшение, но не идеальное решение.См. Ниже для лучшей идеи.
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;
}
}
Подумав немного больше об этом, я думаю, что лучшее решение было бы иметь класс GameManager
, который обрабатывает все проверки и перемещения, итогда мы можем сделать классы Field
и Piece
"немыми".
Это имеет смысл, поскольку перед установкой Piece
для Field
необходимо выполнить гораздо больше проверок.Можно ли переместить эту фигуру в локацию (т. Е. Если король находится под контролем, и это не блокирует его, то это не разрешено).Является ли Field
допустимым местом приземления для фигуры на основе правил перемещения фигуры (то есть горизонтальное положение для слона не допускается)?Есть ли что-нибудь, блокирующее путь части, чтобы добраться до места назначения?Занят ли пункт назначения другой частью, принадлежащей тому же игроку?Много вещей для оценки перед перемещением фигуры.
Кроме того, это позволит нам повторно использовать классы Piece
и Field
в других типах игр, которые могут иметь другой набор правил и другойGameManager
чтобы обеспечить их соблюдение.