Untitled

Anonymous
java
02/16/2026 2:18 AM
8.1 KB
11
Indexable
import java.util.*;

public class GameOfLifeFile {

    // ==================== Mock File System ====================
    private static Map<String, String> filesystem = new HashMap<>();

    static String read(String name, int offset, int length) {
        String content = filesystem.getOrDefault(name, "");
        return content.substring(offset, Math.min(offset + length, content.length()));
    }

    static void append(String name, String contents) {
        filesystem.merge(name, contents, String::concat);
    }

    // ==================== File Helpers ====================

    private static String rowFileName(int gen, int row) {
        return "gen" + gen + "_row" + row;
    }

    /**
     * 把一行 int[] 写入文件,每个 cell 用 '0' 或 '1' 表示
     */
    private static void writeRow(int gen, int row, int[] data) {
        StringBuilder sb = new StringBuilder(data.length);
        for (int val : data) {
            sb.append(val);
        }
        append(rowFileName(gen, row), sb.toString());
    }

    /**
     * 从文件读取一行,返回 int[]
     */
    private static int[] readRow(int gen, int row, int cols) {
        String content = read(rowFileName(gen, row), 0, cols);
        int[] result = new int[cols];
        for (int j = 0; j < cols; j++) {
            result[j] = content.charAt(j) - '0';
        }
        return result;
    }

    // ==================== Initialize ====================

    public static void initialize(int[][] board) {
        for (int i = 0; i < board.length; i++) {
            writeRow(0, i, board[i]);
        }
    }

    // ==================== 核心:基于 3 行滑动窗口的 nextGen ====================

    /**
     * 用滑动窗口处理,内存中只保留 3 行。
     * 复用原题代码的计数逻辑:遍历周围 8 个方向,统计活邻居数。
     *
     * rows[0] = 上一行 (i-1),可能为 null
     * rows[1] = 当前行 (i)
     * rows[2] = 下一行 (i+1),可能为 null
     */
    private static int[] processRow(int[] prevRow, int[] currRow, int[] nextRow, int cols) {
        // 把 3 行组装成一个小的局部 board,方便复用原始代码的双重循环逻辑
        // 局部 board: 最多 3 行,当前行始终在 index = localI
        //   prevRow 存在 → localBoard[0], currRow → localBoard[1], nextRow → localBoard[2]
        //   prevRow 不存在 → currRow → localBoard[0], nextRow → localBoard[1]
        // 但这样映射比较麻烦,不如直接用数组引用更清晰:

        int[] newRow = new int[cols];

        for (int j = 0; j < cols; j++) {
            int count = 0;

            // 遍历 3 行 × 3 列 的邻域,和原始代码思路完全一致
            // rows 数组: index 0 = prevRow, 1 = currRow, 2 = nextRow
            // dx 对应: -1, 0, +1
            int[][] rows = {prevRow, currRow, nextRow};

            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    // 跳过自身
                    if (dx == 0 && dy == 0) continue;

                    int rowIdx = 1 + dx;  // dx=-1 → rows[0]=prevRow, dx=0 → rows[1]=currRow, dx=1 → rows[2]=nextRow
                    int nj = j + dy;

                    // 边界检查:行越界(prevRow/nextRow 为 null)或列越界
                    if (rows[rowIdx] == null) continue;
                    if (nj < 0 || nj >= cols) continue;

                    // 统计活细胞(直接读文件的原始值,不存在中间状态,所以 ==1 即可)
                    if (rows[rowIdx][nj] == 1) count++;
                }
            }

            // 和原始代码一样的规则判断
            if (currRow[j] == 1 && (count < 2 || count > 3)) {
                newRow[j] = 0;  // 活 → 死
            } else if (currRow[j] == 0 && count == 3) {
                newRow[j] = 1;  // 死 → 活
            } else {
                newRow[j] = currRow[j];  // 保持不变
            }
        }

        return newRow;
    }

    /**
     * 计算下一代。从 gen 读,写入 gen+1。
     * 内存开销:O(cols),只保留 3 行。
     */
    public static void nextGen(int gen, int m, int n) {
        int[] prevRow = null;
        int[] currRow = readRow(gen, 0, n);
        int[] nextRow = (m > 1) ? readRow(gen, 1, n) : null;

        for (int i = 0; i < m; i++) {
            // 处理当前行
            int[] newRow = processRow(prevRow, currRow, nextRow, n);
            writeRow(gen + 1, i, newRow);

            // 滑动窗口:向下移一行
            prevRow = currRow;
            currRow = nextRow;
            nextRow = (i + 2 < m) ? readRow(gen, i + 2, n) : null;
        }
    }

    // ==================== 读取结果 ====================

    public static int[][] readBoard(int gen, int m, int n) {
        int[][] board = new int[m][n];
        for (int i = 0; i < m; i++) {
            board[i] = readRow(gen, i, n);
        }
        return board;
    }

    // ==================== Demo ====================

    public static void main(String[] args) {
        // Example 1
        System.out.println("=== Example 1 ===");
        int[][] board1 = {
            {0, 1, 0},
            {0, 0, 1},
            {1, 1, 1},
            {0, 0, 0}
        };
        filesystem.clear();
        initialize(board1);
        printBoard("Input:", board1);

        nextGen(0, board1.length, board1[0].length);
        int[][] result1 = readBoard(1, board1.length, board1[0].length);
        printBoard("Output:", result1);

        // Example 2
        System.out.println("=== Example 2 ===");
        int[][] board2 = {
            {1, 1},
            {1, 0}
        };
        filesystem.clear();
        initialize(board2);
        printBoard("Input:", board2);

        nextGen(0, board2.length, board2[0].length);
        int[][] result2 = readBoard(1, board2.length, board2[0].length);
        printBoard("Output:", result2);
    }

    private static void printBoard(String label, int[][] board) {
        System.out.println(label);
        for (int[] row : board) {
            System.out.println("  " + Arrays.toString(row));
        }
        System.out.println();
    }
}
Editor is loading...
Leave a Comment