LinkedList< Action>的撤消/重做功能;实作 [英] Undo/redo functionality with LinkedList<Action> implementation

查看:90
本文介绍了LinkedList< Action>的撤消/重做功能;实作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写自己的 Rubik’s cube应用程序。主类 Cube 具有18种旋转方法:

I am writing my own 'Rubik's cube' application. The main class Cube has 18 rotation methods:


  • RotateAxisXClockWise,RotateAxisXAntiClockWise

  • RotateAxisYClockWise,RotateAxisYAntiClockWise

  • RotateAxisZClockWise,RotateAxisZAntiClockWise

  • RotateAxisXClockWise, RotateAxisXAntiClockWise
  • RotateAxisYClockWise, RotateAxisYAntiClockWise
  • RotateAxisZClockWise, RotateAxisZAntiClockWise

RotateUpperFaceClockWise,RotateUpperFaceAntiClockWise

RotateUpperFaceClockWise, RotateUpperFaceAntiClockWise

是的,他们可以可以与参数Direction(例如 RotateFrontFace(Direction direction))成对连接,但现在看来似乎是合适的。

Yes, they could be joined in pairs with a parameter Direction (for example RotateFrontFace(Direction direction)) but for now this seems appropriately.

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

I would like to implement undo/redo functionality and because all methods have the same signature (no input parameters, void return type) they could be saved in a LinkedList data structure. So every time one of the rotation methods is called, it is added to the linked list.

如果我们从LinkedList的开头开始(虽然还没有尝试过),然后进行到最后,那么效果会很好,所以每次旋转都会

This would work pretty well if we start on the beginning of the LinkedList (haven't tried it out yet though) and advance toward the end, so each rotation would be performed exactly as it was in the first place.

但是撤消呢?如果我从头到尾遍历列表,则应调用相反的方法(例如,代替 RotateFrontFaceClockWise RotateFrontFaceAntiClockWise 应该被调用)。任何想法如何实现这一点?优雅吗? :)

But what about undo? If I traverse the list from the end to the beginnig, then the opposite method should be called (for example instead of RotateFrontFaceClockWise, RotateFrontFaceAntiClockWise should be called). Any ideas how to implement this? Elegantly? :)

推荐答案

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

I would not use delegate references as the way to model the rotations, if one of the main purposes is to be able to perform redo/undo. I would consider creating a data-model for each rotation, and store a list of these rotation steps. Each step could then have it's own associated Redo/Undo delegate, which allows someone traversing the list (from either end) to understand what operations took place, and either repeat or reverse them.

使用面向数据的方法对此类转换进行建模的另一个好处是,它可以减少 RotateXXX()方法。

One additional benefit of a data-oriented approach to model such transformations, is that it could potentially reduce the number of similar (but slightly different) versions of your RotateXXX( ) methods.

编辑:解决您的问题,这种解决方案可能采用哪种形状。

最简单的操作可能是存储一个 Tuple< Action,Action> 将成对的每对旋转/非旋转操作表示为成对的委托。但是,我将考虑使用描述旋转操作的显式数据结构,也许最终包括诸如描述性名称,方向/面属性等内容。我还将更改您的 RotateXXX 方法,使它们成为 Cube 的静态方法,并接受多维数据集的实例作为参数。这将允许对 Cube 实例的外部旋转操作进行建模。

The simplest thing to do may be to store a Tuple<Action,Action> representing each pair of rotate/unrotate operations as paired delegates. However, I would consider using an explicit data structure that describes the rotation operation, perhaps eventually including things like a descriptive name, direction/face attributes, and so on. I would also change your RotateXXX methods so that they are static methods of Cube, and accept an instance of cube as a parameter. This would allow modeling the rotation operations externally to the instance of 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 );
}

这篇关于LinkedList&lt; Action&gt;的撤消/重做功能;实作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆