如何实现撤销功能
本文关键字:功能 实现 何实现 | 更新日期: 2023-09-27 18:12:26
我正在写一个名为Flipper的程序,它有3x3个单元格用于拼图。每个单元格(按钮)初始颜色为绿色。当单击某个单元格时,该单元格及其相邻单元格将翻转(更改颜色)。另一个要求是撤销功能,它可以回到上一个阶段。我不知道如何实现这一点。这些是游戏中发生的主要事情。
public Puzzle(Form1 form1)
{
buttons = new Button[3, 3] { { form1.button1, form1.button2, form1.button3 },
{ form1.button4, form1.button5, form1.button6 },
{ form1.button7, form1.button8, form1.button9 } };
//button reference from form1
}
public void reset()
{
//reset all the colors of buttons in the puzzle to lime
}
public void FlipCells(int row, int col)
{
//when certain button is clicked(this event is done in the form1.cs), say for (0,0) change color of cell (0,0),///(0,1) and (1,0) by calling changeColor method
}
public void changeColor(int row, int col)
{
//test current color of the cell, and change it
}
我要求在一个叫做undo的类中实现undo函数。任何想法都很感激!!
通过知道上一次操作改变了什么,可以实现一次撤销。
事实证明,取消翻转可以通过……再翻一遍。所以只要记住你的最后一个动作,并重复它!
如果你记得每一个移动,那么你可以在游戏的初始状态中多次这样做。你可以通过创建一个移动堆栈来实现这一点,当你移动时,你可以推它,当你撤销时,它会弹出。更一般地说,要撤销,你需要做三件事:
- 对于用户可以做的每一个动作,做一个反向动作来撤销它。
- 每次用户做出一个动作,记住它,这样你就知道要采取哪个反向动作(如果需要的话)。
- 当用户表示他想要撤销时,将他所做的最后一件事与其反向动作相匹配,并执行它。
有时候,创建一个反向动作是非常困难的。在这些情况下,在操作执行之前只存储程序的状态,然后在用户想要撤销时重新加载它会变得更容易。
有很多实现撤销功能的选项。
因为这是家庭作业,我只给你指出Stack
数据结构。堆栈是后进先出的。把它想象成桌子上的一叠文件。
当玩家翻转一个方块时,你记录下它并将其添加到堆栈中(称为"push")。玩家翻转另一个方块:你做另一个笔记,然后推到堆栈的顶部。
当请求"撤销"时,您要撤销哪个操作?最近的一个——所以你从堆栈的顶部抽取(称为"pop")。调用stack. pop()将返回堆栈中最顶层(最近)的项,并从堆栈中删除该项。
这应该足以让你继续——找出你在堆栈中需要什么,你就差不多完成了。
进一步阅读:Stack
: http://msdn.microsoft.com/en-us/library/system.collections.stack.aspxStack<T>
: http://msdn.microsoft.com/en-us/library/3278tedw.aspx
不妨想想当你"撤销"一个动作时会发生什么。所有你刚刚翻转的颜色都被翻转回来(或者再次)假设你只有两种颜色
尽管在您的情况下这可能是多余的,但Memento设计模式是实现撤消(和重做)功能的标准方法。
Memento将保存对象的当前状态,并将具有还原功能,该功能将逆转其所链接对象的更改。
所以在你的例子中,Memento将保存板的状态(每个单元格的每种颜色),当应用到板上时,它将设置颜色。
执行命令模式。你可以在字典,数组或堆栈中记录你的命令然后撤销
访问此链接http://www.codeproject.com/KB/architecture/sharped.aspx
如果您只有两种颜色,那么撤销与您在类中调用它的单元格的changeColor没有什么不同。因此,您所要做的就是存储(在成员变量中)调用changeColor的最后一列和行,并在Undo函数中使用存储的值再次调用changeColor。