通过 LinkedList 实现撤消/重做功能

2024-04-06

我正在编写自己的“魔方”应用程序。主要班级Cube有18种旋转方式:

  • RotateAxisXClockWise、RotateAxisXAntiClockWise
  • 顺时针旋转轴 Y、逆时针旋转轴 Y
  • RotateAxisZClockWise、RotateAxisZAntiClockWise

  • 顺时针旋转UpperFace、逆时针旋转UpperFace

  • 顺时针旋转正面、逆时针旋转正面
  • 顺时针旋转右面、逆时针旋转右面
  • RotateBackFace顺时针、RotateBackFace逆时针
  • 顺时针旋转左面、逆时针旋转左面
  • 顺时针旋转下脸、逆时针旋转下脸

是的,它们可以通过参数 Direction 成对连接(例如RotateFrontFace(Direction direction))但目前看来这似乎是合适的。

我想实现撤消/重做功能,并且因为所有方法都具有相同的签名(没有输入参数,无效返回类型),所以它们可以保存在 LinkedList 数据结构中。因此,每次调用其中一种旋转方法时,都会将其添加到链表中。

如果我们从 LinkedList 的开头开始(虽然还没有尝试过)并向结尾前进,那么这将非常有效,因此每次旋转都将完全按照最初的方式执行。

但是撤消呢?如果我从末尾到开头遍历列表,那么应该调用相反的方法(例如,而不是RotateFrontFaceClockWise, RotateFrontFaceAntiClockWise应该调用)。有什么想法如何实施吗?优雅? :)


我不会使用委托引用作为旋转建模的方式,如果主要目的之一是能够执行重做/撤消。我会考虑为每次轮换创建一个数据模型,并存储这些轮换步骤的列表。然后,每个步骤都可以有其自己关联的重做/撤消委托,这允许某人(从任一端)遍历列表以了解发生了哪些操作,并重复或反转它们。

使用面向数据的方法对此类转换进行建模的另一个好处是,它可能会减少类似(但略有不同)版本的数量。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 );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 LinkedList 实现撤消/重做功能 的相关文章

随机推荐