Я бы не использовал ссылки делегатов в качестве способа моделирования вращений , если одна из основных целей состоит в том, чтобы иметь возможность выполнять повтор / отмену.Я хотел бы рассмотреть возможность создания модели данных для каждой ротации и сохранить список этих шагов ротации.Каждый шаг может иметь свой собственный связанный делегат Redo / Undo, который позволяет кому-либо просматривать список (с любого конца), чтобы понять, какие операции были выполнены, и либо повторить, либо отменить их.
Одно дополнительное преимущество данных-ориентированный подход к моделированию таких преобразований заключается в том, что он потенциально может уменьшить количество похожих (но немного отличающихся) версий ваших RotateXXX( )
методов.
РЕДАКТИРОВАТЬ: решение вашего вопроса о том, что такое формарешение может занять.
Самое простое, что можно сделать, - это сохранить Tuple<Action,Action>
, представляющий каждую пару операций поворота / поворота в виде парных делегатов.Тем не менее, я хотел бы рассмотреть возможность использования явной структуры данных, которая описывает операцию поворота, возможно, в конечном счете, включая такие вещи, как описательное имя, атрибуты направления / грани и т. Д.Я бы также изменил ваши методы RotateXXX
, чтобы они были статическими методами Cube
, и принял бы экземпляр куба в качестве параметра.Это позволило бы моделировать операции вращения внешне для экземпляра Cube
.
public sealed class Rotation
{
private readonly Action<Cube> _RotateAction;
private readonly Action<Cube> _UnrotateAction; // used for undo or backtracking
private Rotation( Action<Cube> rotateAction, Action<Cube> unrotateAction )
{
_RotateAction = rotateAction;
_UnrotateAction = unrotateAction;
}
public void Rotate( Cube cube ) { _RotateAction( cube ); }
public void Unrotate( Cube cube ) { _Unrotate( cube ); }
public static readonly RotateFrontFaceClockswise =
new Rotation( Cube.RotateFrontFaceClockwise
Cube.RotateFrontFaceCounterClockwise );
public static readonly RotateFrontFaceCounterClockwise =
new Rotation( Cube.RotateFrontFaceCounterClockwise,
Cube.RotateFrontFaceClockwise );
public static readonly RotateLeftFaceClockwise =
new Rotation( Cube.RotateLeftFaceClockwise,
Cube.RotateLeftFaceCounterClockwise );
public static readonly RotateLeftFaceCounterClockwise =
new Rotation( Cube.RotateLeftFaceCounterClockwise,
Cube.RotateLeftFaceClockwise );
// etc..
}
// now we can keep track of the state changes of a cube using:
List<Rotation> cubeRotations = new List<Rotation>();
cubeRotations.Add( Rotation.RotateFrontFaceCounterClockwise );
cubeRotations.Add( Rotation.RotateBackFaceClockwise );
cubeRotations.Add( Rotation.RotateLeftFaceCounterClockwise );
// to apply the rotations to a cube, you simple walk through the data structure
// calling the Rotate( ) method on each:
Cube someCube = new Cube( ... )
foreach( Rotation r in cubeRotations )
{
r.Rotate( someCube );
}
// to undo these rotations you can walk the like in reverse:
foreach( Rotation r in cubeRotations.Reverse() )
{
r.Unrotate( someCube );
}