有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java使用多个堆栈允许“撤消”方法

我正在做一个井字游戏,我想实现一个撤销方法。我觉得最好的方法就是设置另一个(多个?)堆叠,并复制刚刚发生的“移动”。然后,如果调用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;
}

然后是一种构建电路板的电路板方法,一种显示方法,当然还有一种检查一行中的3

谢谢你的建议


共 (3) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    我建议你有一个对象,它封装了一个“Move”,上面有一个apply(BoardState s)和一个类似的unapply方法。 然后你可以保留一个堆栈/列表。 撤消从堆栈中弹出,不应用于当前板状态

    由于你的apply/unapply方法是可逆的,这可能是解决这个问题最简单、最有效的方法之一(如果apply方法记住了它覆盖的任何状态,那么它就适用于更复杂的问题)

    如果这不是一个可接受的解决方案,那么我建议你进一步解释你的代码是如何工作的——所有的数字,以及n代表什么,因为我不太清楚

  3. # 3 楼答案

    有一种设计模式可以进行撤销和重做。命令设计模式。它涉及

    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();
    }
    

    }

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