java实现细胞自动机

细胞自动机的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地址
小结:博客为个人学习之余沉淀所学知识所用,有纠正之处,劳烦大家指出,共同进步。

猜你喜欢

转载自blog.csdn.net/MR_Peach07/article/details/72862677