Java | コピーを使った Undo 機能

Java Java
スポンサーリンク

では「Undo機能+Redo機能」を備えた 完全版サンプル を紹介します。これで「元に戻す」「やり直す」が両方できるようになります。


基本アイデア

  • 履歴(undoStack) に「過去の状態」を保存
  • Redo用の履歴(redoStack) に「Undoで戻した状態」を保存
  • 操作の流れ:
    1. 状態を変更する前に undoStack に保存
    2. Undoすると undoStack から取り出して redoStack に保存
    3. Redoすると redoStack から取り出して undoStack に戻す

コード例:Undo/Redo完全版

import java.util.*;

public class UndoRedoExample {
    public static void main(String[] args) {
        int[] state = {1, 2, 3};

        // Undo用とRedo用の履歴
        List<int[]> undoStack = new ArrayList<>();
        List<int[]> redoStack = new ArrayList<>();

        // 初期状態を保存
        undoStack.add(Arrays.copyOf(state, state.length));

        // ---- 状態を変更していく ----
        state[0] = 99;
        undoStack.add(Arrays.copyOf(state, state.length));

        state[1] = 77;
        undoStack.add(Arrays.copyOf(state, state.length));

        state[2] = 55;
        undoStack.add(Arrays.copyOf(state, state.length));

        System.out.println("現在の状態: " + Arrays.toString(state));
        // [99, 77, 55]

        // ---- Undo処理 ----
        state = undo(state, undoStack, redoStack);
        System.out.println("Undo後: " + Arrays.toString(state));
        // [99, 77, 3]

        state = undo(state, undoStack, redoStack);
        System.out.println("さらにUndo後: " + Arrays.toString(state));
        // [99, 2, 3]

        // ---- Redo処理 ----
        state = redo(state, undoStack, redoStack);
        System.out.println("Redo後: " + Arrays.toString(state));
        // [99, 77, 3]

        state = redo(state, undoStack, redoStack);
        System.out.println("さらにRedo後: " + Arrays.toString(state));
        // [99, 77, 55]
    }

    // Undo処理
    private static int[] undo(int[] state, List<int[]> undoStack, List<int[]> redoStack) {
        if (undoStack.size() > 1) {
            // 最新状態をRedo用に保存
            redoStack.add(Arrays.copyOf(state, state.length));
            // UndoStackから1つ前を復元
            undoStack.remove(undoStack.size() - 1);
            return Arrays.copyOf(undoStack.get(undoStack.size() - 1), state.length);
        }
        return state; // Undoできない場合はそのまま
    }

    // Redo処理
    private static int[] redo(int[] state, List<int[]> undoStack, List<int[]> redoStack) {
        if (!redoStack.isEmpty()) {
            int[] redoState = redoStack.remove(redoStack.size() - 1);
            undoStack.add(Arrays.copyOf(redoState, redoState.length));
            return redoState;
        }
        return state; // Redoできない場合はそのまま
    }
}
Java

解説

  • Undo:
    • 最新状態を redoStack に保存
    • undoStack の1つ前を復元
  • Redo:
    • redoStack から取り出して復元
    • 復元した状態を undoStack に戻す
  • 結果:
    • UndoとRedoを繰り返すことで、状態を行ったり来たりできる。

応用ポイント

  • テキストエディタ: 文字列の状態をコピーして履歴管理すればUndo/Redo可能。
  • ゲーム: 盤面やキャラクターの状態を保存して「戻す」「やり直す」ができる。
  • オブジェクト配列: 浅いコピーだと履歴が共有されるので、深いコピーを実装する必要あり。

✅ これで「Undo/Redo完全版」が完成です。

Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました