では「Undo機能+Redo機能」を備えた 完全版サンプル を紹介します。これで「元に戻す」「やり直す」が両方できるようになります。
基本アイデア
- 履歴(undoStack) に「過去の状態」を保存
- Redo用の履歴(redoStack) に「Undoで戻した状態」を保存
- 操作の流れ:
- 状態を変更する前に
undoStackに保存 - Undoすると
undoStackから取り出してredoStackに保存 - 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完全版」が完成です。
