では「ゲーム盤面を題材にした実践的なUndo/Redo」の例を紹介します。ここでは オセロや将棋のような盤面を配列で表現し、Undo/Redoで一手戻す/やり直す 仕組みを作ります。
シナリオ
- 盤面を 2次元配列 で表現(例: 3×3の簡易ボード)。
- プレイヤーが「手」を打つたびに盤面を更新。
- 更新前の盤面を 履歴(undoStack) に保存。
- Undoで1手前に戻り、Redoでやり直しができる。
コード例:ゲーム盤面のUndo/Redo
import java.util.*;
public class GameBoardUndoRedo {
public static void main(String[] args) {
// 3x3の盤面(0=空, 1=プレイヤーX, 2=プレイヤーO)
int[][] board = new int[3][3];
List<int[][]> undoStack = new ArrayList<>();
List<int[][]> redoStack = new ArrayList<>();
// 初期状態を保存
undoStack.add(deepCopy(board));
// ---- プレイヤーの手 ----
board[0][0] = 1; // Xが左上に置く
undoStack.add(deepCopy(board));
board[1][1] = 2; // Oが中央に置く
undoStack.add(deepCopy(board));
board[2][2] = 1; // Xが右下に置く
undoStack.add(deepCopy(board));
System.out.println("現在の盤面:");
printBoard(board);
// ---- Undo ----
board = undo(board, undoStack, redoStack);
System.out.println("Undo後:");
printBoard(board);
board = undo(board, undoStack, redoStack);
System.out.println("さらにUndo後:");
printBoard(board);
// ---- Redo ----
board = redo(board, undoStack, redoStack);
System.out.println("Redo後:");
printBoard(board);
board = redo(board, undoStack, redoStack);
System.out.println("さらにRedo後:");
printBoard(board);
}
// 深いコピー(2次元配列)
private static int[][] deepCopy(int[][] src) {
int[][] copy = new int[src.length][];
for (int i = 0; i < src.length; i++) {
copy[i] = Arrays.copyOf(src[i], src[i].length);
}
return copy;
}
// Undo処理
private static int[][] undo(int[][] state, List<int[][]> undoStack, List<int[][]> redoStack) {
if (undoStack.size() > 1) {
redoStack.add(deepCopy(state));
undoStack.remove(undoStack.size() - 1);
return deepCopy(undoStack.get(undoStack.size() - 1));
}
return state;
}
// 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(deepCopy(redoState));
return redoState;
}
return state;
}
// 盤面表示
private static void printBoard(int[][] board) {
for (int[] row : board) {
for (int cell : row) {
char mark = (cell == 0) ? '.' : (cell == 1 ? 'X' : 'O');
System.out.print(mark + " ");
}
System.out.println();
}
System.out.println();
}
}
Java実行イメージ
現在の盤面:
X . .
. O .
. . X
Undo後:
X . .
. O .
. . .
さらにUndo後:
X . .
. . .
. . .
Redo後:
X . .
. O .
. . .
さらにRedo後:
X . .
. O .
. . X
応用ポイント
- オセロや将棋: 盤面を配列で管理すれば、Undo/Redoで「一手戻す/やり直す」が可能。
- 複雑なゲーム: 盤面だけでなく「手番」「スコア」なども一緒にコピーすれば完全な履歴管理ができる。
- GUIゲーム: この仕組みをGUIに組み込めば「戻るボタン」「やり直すボタン」が作れる。
✅ これで「ゲーム盤面を題材にした実践的なUndo/Redo」の完成版です。
