java实现细胞自动机

来源:互联网 发布:java免费报表开发工具 编辑:程序博客网 时间:2024/05/17 08:07

细胞自动机的java实现

一丶
先说说这个题目吧,还是第一次接触这种类型的题目:生命游戏中,对于任意细胞,规则如下:
每个细胞有两种状态-存活或死亡,每个细胞与以自身为中心的周围八格细胞产生互动。
当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)
可以把最初的细胞结构定义为种子,当所有在种子中的细胞同时被以上规则处理后, 可以得到第一代细胞图。按规则继续处理当前的细胞图,可以得到下一代的细胞图,周而复始。

二丶
1.看到这个题目的第一反应是将整个生命环境看作一个矩阵,其中的每一个细胞以二维坐标的形式存在于环境中,那么这个细胞类就有三个属性在生命游戏中的:x坐标,y坐标,生命状态。但是,这样做了以后发现两个问题:
1)环境边界处的细胞生命状态判断实现很难。
2)细胞之间的生命状态无法实现关联关系。
2.之后是将单个细胞单独做一个(BasicUnit类),还是以3*3九宫格的方式判段我们抽象出来的单元细胞的生命状态,再将其放入生命游戏沙盘(LifeGame类)中演变,当然,还是写一个细胞信息类(Cell类)将从BasicUnit类中判断得来的细胞生命状态和在LifeGame类中的坐标两个信息存储起来。
3.到此,整个生命游戏的实现逻辑就构建好了,接下来就是编码实现的事情了。
4.编码过程中遇到很多坑,这里就不多提了,碰到的坑都是为了以后少进坑做贡献。
5.下面讲这三个类代码贴出来(不能直接跑,用了单元测试,测试每个类的逻辑是否实现,要跑的话需要自己写一个run类)
BasicUnit类:

package org.coach.tdd.template;/** * Created by lzy on 17-6-3. *//** * BasicUnit类判断单元细胞的生命状态。 */public class BasicUnit {    private static final int DEATH = 0;    private static final int LIVE = 1;    private int[][] testUnit = new int[3][3]; //将一个细胞及其周围相邻细胞看作一个基本单元    private int status = DEATH;    public void setTestUnit(int[][] testUnit) {        this.testUnit = testUnit;    }    /**     * .     * 获得单元细胞生命状态     *     * @param basicUnit 该细胞周围细胞生命状态     * @return 该细胞生命状态     */    public int getUnitCelltatus(int[][] basicUnit) {        int numberofcell = 0;        for (int i = 0; i < 3; i++) {            for (int j = 0; j < 3; j++) {                if (1 == basicUnit[i][j]) {                    if (1 == i && 1 == j) {                    } else {                        numberofcell += 1;                    }                }            }        }        if (3 == numberofcell) {            return 1;        } else if (2 == numberofcell) {            return basicUnit[1][1];        }        return 0;    }}

Cell类:

package org.coach.tdd.template;/** * Created by lzy on 17-6-3. *//** * Cell类存储细胞的坐标,生命状态,周围细胞状态。 */public class Cell {    private int location_x = 0;    private int location_y = 0;    private int cellStatus = 0;    private int[][] aroundCells = new int[3][3];    /**     * 构造方法的描述     *     * @param location_x 细胞的x坐标     * @param location_y 细胞的y坐标     * @param cellStatus 细胞的状态     */    public Cell(int location_x, int location_y, int cellStatus) {        this.location_x = location_x;        this.location_y = location_y;        this.cellStatus = cellStatus;    }    public int getLocation_x() {        return location_x;    }    public int getLocation_y() {        return location_y;    }    public int getCellStatus() {        return cellStatus;    }    public void setCellStatus(int cellStatus) {        this.cellStatus = cellStatus;    }    /**     * 获取更新后的细胞状态     *     * @return     */    public int getAfterTurnCellStatus() {        BasicUnit basicUnit = new BasicUnit();        this.setCellStatus(basicUnit.getUnitCelltatus(aroundCells));        return this.getCellStatus();    }}

LifeGame类:

package org.coach.tdd.template;/** * Created by lzy on 17-6-3. *//** * LifeGame类生命游戏具体操作类 */public class LifeGame {    public static final int LEFTUP = 1;    public static final int RIGHTUP = 2;    public static final int LEFTDOWN = 3;    public static final int RIGHTDOWN = 4;    private int framesize = 0; //框架大小,表示为正方体框架的边长    private int[][] frame;    private int[][] nextframe;    public LifeGame(int framesize) {        this.framesize = framesize;    }    public int[][] getNextframe() {        return nextframe;    }    public void setFrame(int[][] frame) {        this.frame = frame;    }    public void init() {        frame = new int[framesize][framesize];        nextframe = new int[framesize][framesize];    }    public void putCell(Cell cell) {        frame[cell.getLocation_x()][cell.getLocation_y()] = cell.getCellStatus();    }    public int locationIsCorner(int x, int y) {        if (0 == x && 0 == y) {            return LEFTUP;        } else if (0 == x && framesize - 1 == y) {            return RIGHTUP;        } else if (framesize - 1 == x && 0 == y) {            return LEFTDOWN;        } else if (framesize - 1 == x && framesize - 1 == y) {            return RIGHTDOWN;        }        return 0;    }    public int locationIsLine(int x, int y) {        if (0 == x && 0 != y && framesize - 1 != y) {            return 11;        } else if (framesize - 1 == x && 0 != y && framesize - 1 != y) {            return 12;        } else if (0 == y && 0 != x && framesize - 1 != x) {            return 13;        } else if (framesize - 1 == y && 0 != x && framesize - 1 != x) {            return 14;        }        return 0;    }    /**     * 获取指定坐标细胞周围细胞状态     *     * @param x cell_x坐标     * @param y cell_y坐标     * @return 指定坐标细胞周围细胞状态     */    public int[][] getAroundStatus(int x, int y) {        //corner        int[][] aroundUnit = new int[3][3];        int isCorner = locationIsCorner(x, y);        int isLine = locationIsLine(x, y);        if (isCorner != 0) {            switch (isCorner) {                case 1: {                    aroundUnit = new int[][]{{frame[x][y + 1], frame[x + 1][y], frame[x + 1][y + 1]}, {0, frame[x][y], 0}, {0, 0, 0}};                    break;                }                case 2: {                    aroundUnit = new int[][]{{frame[x][y - 1], frame[x + 1][y - 1], frame[x + 1][y]}, {0, frame[x][y], 0}, {0, 0, 0}};                    break;                }                case 3: {                    aroundUnit = new int[][]{{frame[x - 1][y], frame[x - 1][y + 1], frame[x][y + 1]}, {0, frame[x][y], 0}, {0, 0, 0}};                    break;                }                case 4: {                    aroundUnit = new int[][]{{frame[x - 1][y], frame[x - 1][y - 1], frame[x][y - 1]}, {0, frame[x][y], 0}, {0, 0, 0}};                    break;                }                default:                    break;            }        }        //line        else if (isLine != 0) {            switch (isCorner) {                case 11: {                    aroundUnit = new int[][]{{frame[x][y - 1], frame[x][y + 1], frame[x + 1][y - 1]}, {frame[x + 1][y], frame[x][y], frame[x + 1][y + 1]}, {0, 0, 0}};                    break;                }                case 12: {                    aroundUnit = new int[][]{{frame[x - 1][y - 1], frame[x - 1][y], frame[x - 1][y + 1]}, {frame[x][y - 1], frame[x][y], frame[x][y + 1]}, {0, 0, 0}};                    break;                }                case 13: {                    aroundUnit = new int[][]{{frame[x - 1][y], frame[x - 1][y + 1], frame[x][y + 1]}, {frame[x + 1][y], frame[x][y], frame[x + 1][y + 1]}, {0, 0, 0}};                    break;                }                case 14: {                    aroundUnit = new int[][]{{frame[x - 1][y - 1], frame[x - 1][y], frame[x][y - 1]}, {frame[x + 1][y - 1], frame[x][y], frame[x + 1][y]}, {0, 0, 0}};                    break;                }                default:                    break;            }        } else {            aroundUnit = new int[][]{{frame[x - 1][y - 1], frame[x - 1][y], frame[x - 1][y + 1]}, {frame[x][y - 1], frame[x][y], frame[x][y + 1]}, {frame[x + 1][y - 1], frame[x + 1][y], frame[x + 1][y + 1]}};        }        return aroundUnit;    }    /**     * 更新环境中所有细胞生命状态     *     * @return 环境中是否还在活着的细胞     */    public boolean isfreshFrame() {//      boolean flag =false;        boolean hasLife = false;        BasicUnit basicUnit = new BasicUnit();        for (int i = 0; i < framesize; i++) {            for (int j = 0; j < framesize; j++) {                int[][] aroundUnit = getAroundStatus(i, j);                int status = basicUnit.getUnitCelltatus(aroundUnit);                nextframe[i][j] = status;            }        }        for (int i = 0; i < framesize; i++) {            for (int j = 0; j < framesize; j++) {                System.out.print(frame[i][j]);            }            System.out.println("");        }        System.out.println("");        for (int i = 0; i < framesize; i++) {            for (int j = 0; j < framesize; j++) {                if (1 == nextframe[i][j]) {                    hasLife = true;                }                System.out.print(nextframe[i][j]);            }            System.out.println("");        }//      flag=true;        return hasLife;    }    /**     * 运行整个生命游戏     *     * @param lifeGame 生命游戏的初始对象     * @return 运行成功     */    public boolean run(LifeGame lifeGame) {        while (lifeGame.isfreshFrame()) {            lifeGame.setFrame(lifeGame.getNextframe());            System.out.println("");        }        return true;    }}

最后附上该项目github地址:github地址
小结:博客为个人学习之余沉淀所学知识所用,有纠正之处,劳烦大家指出,共同进步。