Java - использование нескольких стеков, чтобы разрешить метод отмены - PullRequest
1 голос
/ 11 декабря 2010

Я работаю над игрой в крестики-нолики и хочу реализовать метод отмены.На мой взгляд, лучший способ сделать это - просто установить еще один (несколько?) Стеков и скопировать только что сделанные «ходы».Затем, если вызывается отмена, просто вытолкните последний ход и снова заселите игровое поле.

Так что да, у меня есть идея, но я не могу понять, как ее реализовать.из того, что у меня есть:

Чтобы установить:

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 ]

4 голосов
/ 11 декабря 2010

Существует шаблон проектирования для отмены и повтора. Шаблон проектирования . Это включает

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 (). Я просто добавил это для ясности.

2 голосов
/ 11 декабря 2010

Перейдите непосредственно к книге «Банда четырех» Шаблоны проектирования и прочитайте раздел, посвященный шаблону командования. Это то, над чем вы работаете - и делаете с этим довольно хорошую работу - и сразу же приступите к реализации на Java, как только у вас появится идея.

1 голос
/ 11 декабря 2010

Я хотел бы предложить, чтобы у вас был объект, который инкапсулирует «Move», в котором есть метод apply (BoardState) и аналогичный метод неприменения.Затем вы можете сохранить стек / список из них.Отмена становится всплывающим из стека и не применяется к текущему состоянию платы.

Поскольку ваши методы применения / отмены являются обратимыми, это, вероятно, один из самых простых и эффективных методов его решения (и работает для более сложных проблем, еслиметод apply запоминает любое состояние, которое он переопределяет).

Если это неприемлемое решение, я бы посоветовал вам подробнее объяснить, как работает ваш код - все числа и то, что обозначает n, потому что не так яснодля меня.

...