【问题标题】:Java - Using multiple stacks to allow an 'undo' methodJava - 使用多个堆栈来允许“撤消”方法
【发布时间】:2011-05-23 19:51:10
【问题描述】:

我正在开发一个井字游戏,我想实现一个撤消方法。我认为最好的方法是设置另一个(多个?)堆栈,并复制刚刚发生的“移动”。然后,如果调用 undo,只需弹出最后一步并重新填充游戏板。

是的,我有这个想法,但不知道如何实现它。

我拥有的一些东西:

设置:

public void set(Position p, int v, int n) throws IOException { 
    if (board[p.x][p.y][p.z]!= 0) throw new IOException("Position taken");

    //Restrict 222 until all other's have been used
    if (n != 26) {
        if (p.x == 1 && p.y == 1 && p.z ==1) {
            throw new IOException("[2,2,2] cannot be played until all other positions have been taken");
        }
    }

    //Enforce x=1 for first 9, x=3 for next 9
    if (n < 9 ) {
        if (p.x != 0) throw new IOException("Please play on x=1 for the first 9 moves");
    }

    if (n >= 9 && n < 18) {
        if (p.x != 2) throw new IOException("Please play on x=3 for the first 9 moves");
    }

    board[p.x][p.y][p.z] = v;
}

然后有一个board方法来搭建board,一个display方法,当然还有一个可以连续检查3个的方法。

感谢您的建议

【问题讨论】:

  • 在 GOF 中搜索 Memento 设计模式

标签: java stack undo tic-tac-toe


【解决方案1】:

有设计模式来做撤消和重做。 命令设计模式。它涉及

public interface ICommand{
   void execute();
   void undo();
   void redo();
}

实现上面的接口来执行你的动作,execute会封装你的动作。

class MoveCommand implements ICommand{//parameter to store current board state
  public MoveCommand(){
    // new board state is validated
  }
  public void execute(){
    // change the board state
  }
 public void undo(){ // restore
 }
 public void redo(){ // apply again if possible
 }
}

现在创建一个新类,它将是 CommandDispatcher

class CommandDispatcher{
 private List<ICommand> commands = new ArrayList<ICommand>();
 public CommandDispatcher(){
 }
 private ICommand currentCommand = null;
 public void setCommand(ICommand cmd){
   currentCommand  = cmd;
   cmd.execute();
   commands.add(cmd);
 }
 public void undoAll(){
    for(ICommand cmd : commands){cmd.undo();}
}
 public void undo(){
 commands.remove(commands.size()-1);
 currentCommand = commands.get(commands.size()-1)
}
public void redo(){
if(null!=currentCommand) currentCommand.redo();
}

}

通过这种方式,您可以保留应用程序的状态并防止自己获得空指针异常。 方法 redo() 将调用 execute() 方法。为了清楚起见,我只是添加了它。

【讨论】:

  • 虽然我不是在玩井字游戏,但我从你的回答中学到了一些非常有用的东西!
【解决方案2】:

直接转到四人组Design Patterns 书并阅读有关命令模式的部分。这就是你正在努力的方向——并且做得很好——一旦你有了这个想法,就可以直接在 Java 中实现。

【讨论】:

    【解决方案3】:

    我建议你有一个对象来封装一个“移动”,它有一个 apply(BoardState s) 和一个类似的 unapply 方法。 然后你可以保留这些的堆栈/列表。 撤消成为从堆栈中弹出并取消应用到当前板状态。

    由于您的应用/取消应用方法是可逆的,这可能是解决它的最简单和最有效的方法之一(如果应用方法记住它覆盖的任何状态,则适用于更复杂的问题)。

    如果这不是一个可接受的解决方案,那么我建议您详细解释一下您的代码是如何工作的 - 重新解释所有数字,以及 n 代表什么,cos 对我来说不是那么清楚。

    【讨论】:

      猜你喜欢
      • 2017-03-16
      • 2021-06-04
      • 1970-01-01
      • 2020-09-24
      • 2015-12-14
      • 2016-08-01
      • 1970-01-01
      • 2021-03-05
      • 1970-01-01
      相关资源
      最近更新 更多