2011-02-28 73 views
0

我正在編寫自己的'魔方'應用程序。主類Cube具有18點旋轉的方法:LinkedList撤銷/重做功能<Action>實施

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

  • RotateUpperFaceClockWise,RotateUpperFaceAntiClockWise

  • RotateFrontFaceClockWise,RotateFrontFaceAntiClockWise
  • RotateRightFaceClockWise,RotateRightFaceAntiClockWise
  • RotateBackFaceClockWise,RotateBackFAceAntiClockWise
  • RotateLeftFaceClockWise,RotateLeftFaceAntiClockWise
  • RotateDownFaceClockWise,RotateDownFaceAntiClockWise

是,它們可以以對被接合與一參數方向(例如RotateFrontFace(Direction direction))但現在這個似乎適當。

我想實現撤銷/重做功能,因爲所有方法都有相同的簽名(沒有輸入參數,無效返回類型),他們可以保存在LinkedList數據結構中。所以每次調用其中一種旋轉方法時,它都會添加到鏈接列表中。

如果我們從LinkedList的開始處開始(儘管還沒有嘗試過)並且朝向結尾前進,那麼這將工作得很好,因此每次輪換將按照首先執行的方式執行。

但是如何撤消?如果我從頭到尾遍歷列表,則應該調用相反的方法(例如,應該調用RotateFrontFaceClockWise,RotateFrontFaceAntiClockWise)。任何想法如何實現這一點?優雅? :)

回答

1

我不會使用委託引用作爲模型旋轉的方法,如果其中一個主要目的是能夠執行重做/撤消。我會考慮爲每次輪換創建一個數據模型,並存儲這些輪換步驟的列表。然後每個步驟都可以擁有它自己的關聯重做/撤銷委託,它允許有人遍歷列表(從任一端)來了解發生了什麼操作,並重復或反轉它們。

面向數據的方法來模擬這種轉換的另一個好處是,它可能會減少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); 
} 
+0

這個數據模型是怎麼樣的?可以舉個例子嗎? – sventevit 2011-03-01 19:39:21

1

我知道你想避免你的參數化方法,但你可能最好關閉奉行類似的規定:

enum Face 
{ 
    Top, 
    Bottom, 
    Left, 
    Right, 
    Front, 
    Back 
} 

enum Direction 
{ 
    Clockwise, 
    CounterClockwise 
} 

struct Rotation 
{ 
    public Face Face; 
    public Direction Direction; 
} 

LinkedList<Rotation> actions; 

你可以選擇是否將推動直接或反轉動作到列表中,但是一旦以這種方式存儲動作,就很容易編寫一些快速切換語句,以便在從列表中移除時反轉該動作。

在附註中,考慮將StackList替換爲Stack,它將服務於您,並且完全適合您的目的。

編輯:

注意到,我沒有爲我的枚舉軸旋轉的支持,但我敢肯定,你可以將它們添加在票面枚舉的附加條目(雖然你可能想將其重命名在這一點上)

0

假設你真的要堅持你的模型......

你可以通過在列表中執行的方法,每名進入嘗試,然後與反思,通過重複調用零件櫃在名單上。這假定您的方法將具有匹配的名稱(如您所建議的)。

您還可以創建一個HybridDictionary,將方法名稱用作計數器方法的ID和地址作爲值。所以當你迭代列表時,你可以讓委託處理給定值的方法。

+0

我個人不建議追求這個解決方案,無論是緩存代表或直接反射調用。反射是一個有用的工具,但應該在有實際需要時使用,而不是像這樣的興奮 – LorenVS 2011-02-28 20:55:23

+0

我同意,我認爲他應該採取其他方法。除了反思真的很重要的資源。但是我只是在發表意見,這取決於他的決定......但是,這是給出的問題,雖然...... – PedroC88 2011-02-28 20:57:47

1

18個方法似乎有很多需要跟上,特別是當您考慮實現撤消/重做功能時。你有沒有考慮過使用一種更通用的方法?如果你這樣做了,你可以以非常一致的方式存儲傳遞給該方法的內容,並輕鬆執行相反的操作。相反的行爲可以從字典中查找。