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

发布于 2024-10-07 06:28:46 字数 968 浏览 11 评论 0原文

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

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

我有一些:

设置:

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 个的方法。

感谢您的任何建议

I'm working on a tic tac toe game and am wanting to implement an undo method. What I feel is the best way to do this is just setup another (multiple?) stacks, and make a copy of the 'moves' that have just taken place. Then, if undo is called, just pop the last move and repopulate the game board.

So yeah, I have the idea, but can't figure out how to implement it.

Some of what I have:

To set:

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

Then there is a board method to build the board, a display method, and of course one to check for 3 in a row.

Thanks for any advice

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情绪失控 2024-10-14 06:28:46

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

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

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

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()方法。我只是为了清楚起见添加了它。

There is design pattern to do undo and redo. The command design pattern. It involes

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

implement the above interface to perform your move, execute will encapsulate your action.

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
 }
}

now create a new class that will be 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();
}

}

This way you can preserve the state of your application and prevent yourself from getting nullpointer exceptions.
The method redo() will call execute() method. I just added it for clarity.

花想c 2024-10-14 06:28:46

直接转到《四人帮》设计模式一书并阅读有关命令模式。这就是您正在努力实现的目标,并且做得相当好,一旦您有了这个想法,就可以直接用 Java 实现它。

Go directly to the Gang of Four Design Patterns book and read the section on the Command pattern. That's what you're working toward -- and making a pretty good job of it -- and it's straight forward to implement in Java once you get the idea.

情魔剑神 2024-10-14 06:28:46

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

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

如果这不是一个可接受的解决方案,那么我建议你更多地解释你的代码是如何工作的——所有的数字,以及 n 代表什么,cos 对我来说不太清楚。

I would suggest that you have an object that encapsulates a "Move" which has an apply(BoardState s) and a similar unapply method on it.
Then you can keep a stack/list of these.
Undo becomes a pop from stack and unapply to current board state.

Since your apply/unapply methods are reversable this is probably one of the simplest and most efficient methods of solving it (and works for more complex problems if the apply method remembers any state it overrides).

If this is not an acceptable solution then I would suggest you explain more how your code works - re all the numbers, and what n stands for, cos is not that clear to me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文