细胞自动机与数据与表现分离

打印 上一主题 下一主题

主题 528|帖子 528|积分 1584

  细胞自动机的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类:
  1. package org.coach.tdd.template;
  2. /**
  3. * Created by lzy on 17-6-3.
  4. */
  5. /**
  6. * BasicUnit类判断单元细胞的生命状态。
  7. */
  8. public class BasicUnit {
  9.     private static final int DEATH = 0;
  10.     private static final int LIVE = 1;
  11.     private int[][] testUnit = new int[3][3]; //将一个细胞及其周围相邻细胞看作一个基本单元
  12.     private int status = DEATH;
  13.     public void setTestUnit(int[][] testUnit) {
  14.         this.testUnit = testUnit;
  15.     }
  16.     /**
  17.      * .
  18.      * 获得单元细胞生命状态
  19.      *
  20.      * @param basicUnit 该细胞周围细胞生命状态
  21.      * @return 该细胞生命状态
  22.      */
  23.     public int getUnitCelltatus(int[][] basicUnit) {
  24.         int numberofcell = 0;
  25.         for (int i = 0; i < 3; i++) {
  26.             for (int j = 0; j < 3; j++) {
  27.                 if (1 == basicUnit[i][j]) {
  28.                     if (1 == i && 1 == j) {
  29.                     } else {
  30.                         numberofcell += 1;
  31.                     }
  32.                 }
  33.             }
  34.         }
  35.         if (3 == numberofcell) {
  36.             return 1;
  37.         } else if (2 == numberofcell) {
  38.             return basicUnit[1][1];
  39.         }
  40.         return 0;
  41.     }
  42. }
复制代码
 Cell类:
  1. package org.coach.tdd.template;
  2. /**
  3. * Created by lzy on 17-6-3.
  4. */
  5. /**
  6. * Cell类存储细胞的坐标,生命状态,周围细胞状态。
  7. */
  8. public class Cell {
  9.     private int location_x = 0;
  10.     private int location_y = 0;
  11.     private int cellStatus = 0;
  12.     private int[][] aroundCells = new int[3][3];
  13.     /**
  14.      * 构造方法的描述
  15.      *
  16.      * @param location_x 细胞的x坐标
  17.      * @param location_y 细胞的y坐标
  18.      * @param cellStatus 细胞的状态
  19.      */
  20.     public Cell(int location_x, int location_y, int cellStatus) {
  21.         this.location_x = location_x;
  22.         this.location_y = location_y;
  23.         this.cellStatus = cellStatus;
  24.     }
  25.     public int getLocation_x() {
  26.         return location_x;
  27.     }
  28.     public int getLocation_y() {
  29.         return location_y;
  30.     }
  31.     public int getCellStatus() {
  32.         return cellStatus;
  33.     }
  34.     public void setCellStatus(int cellStatus) {
  35.         this.cellStatus = cellStatus;
  36.     }
  37.     /**
  38.      * 获取更新后的细胞状态
  39.      *
  40.      * @return
  41.      */
  42.     public int getAfterTurnCellStatus() {
  43.         BasicUnit basicUnit = new BasicUnit();
  44.         this.setCellStatus(basicUnit.getUnitCelltatus(aroundCells));
  45.         return this.getCellStatus();
  46.     }
  47. }
复制代码
LifeGame类:
  1. package org.coach.tdd.template;
  2. /**
  3. * Created by lzy on 17-6-3.
  4. */
  5. /**
  6. * LifeGame类生命游戏具体操作类
  7. */
  8. public class LifeGame {
  9.     public static final int LEFTUP = 1;
  10.     public static final int RIGHTUP = 2;
  11.     public static final int LEFTDOWN = 3;
  12.     public static final int RIGHTDOWN = 4;
  13.     private int framesize = 0; //框架大小,表示为正方体框架的边长
  14.     private int[][] frame;
  15.     private int[][] nextframe;
  16.     public LifeGame(int framesize) {
  17.         this.framesize = framesize;
  18.     }
  19.     public int[][] getNextframe() {
  20.         return nextframe;
  21.     }
  22.     public void setFrame(int[][] frame) {
  23.         this.frame = frame;
  24.     }
  25.     public void init() {
  26.         frame = new int[framesize][framesize];
  27.         nextframe = new int[framesize][framesize];
  28.     }
  29.     public void putCell(Cell cell) {
  30.         frame[cell.getLocation_x()][cell.getLocation_y()] = cell.getCellStatus();
  31.     }
  32.     public int locationIsCorner(int x, int y) {
  33.         if (0 == x && 0 == y) {
  34.             return LEFTUP;
  35.         } else if (0 == x && framesize - 1 == y) {
  36.             return RIGHTUP;
  37.         } else if (framesize - 1 == x && 0 == y) {
  38.             return LEFTDOWN;
  39.         } else if (framesize - 1 == x && framesize - 1 == y) {
  40.             return RIGHTDOWN;
  41.         }
  42.         return 0;
  43.     }
  44.     public int locationIsLine(int x, int y) {
  45.         if (0 == x && 0 != y && framesize - 1 != y) {
  46.             return 11;
  47.         } else if (framesize - 1 == x && 0 != y && framesize - 1 != y) {
  48.             return 12;
  49.         } else if (0 == y && 0 != x && framesize - 1 != x) {
  50.             return 13;
  51.         } else if (framesize - 1 == y && 0 != x && framesize - 1 != x) {
  52.             return 14;
  53.         }
  54.         return 0;
  55.     }
  56.     /**
  57.      * 获取指定坐标细胞周围细胞状态
  58.      *
  59.      * @param x cell_x坐标
  60.      * @param y cell_y坐标
  61.      * @return 指定坐标细胞周围细胞状态
  62.      */
  63.     public int[][] getAroundStatus(int x, int y) {
  64.         //corner
  65.         int[][] aroundUnit = new int[3][3];
  66.         int isCorner = locationIsCorner(x, y);
  67.         int isLine = locationIsLine(x, y);
  68.         if (isCorner != 0) {
  69.             switch (isCorner) {
  70.                 case 1: {
  71.                     aroundUnit = new int[][]{{frame[x][y + 1], frame[x + 1][y], frame[x + 1][y + 1]}, {0, frame[x][y], 0}, {0, 0, 0}};
  72.                     break;
  73.                 }
  74.                 case 2: {
  75.                     aroundUnit = new int[][]{{frame[x][y - 1], frame[x + 1][y - 1], frame[x + 1][y]}, {0, frame[x][y], 0}, {0, 0, 0}};
  76.                     break;
  77.                 }
  78.                 case 3: {
  79.                     aroundUnit = new int[][]{{frame[x - 1][y], frame[x - 1][y + 1], frame[x][y + 1]}, {0, frame[x][y], 0}, {0, 0, 0}};
  80.                     break;
  81.                 }
  82.                 case 4: {
  83.                     aroundUnit = new int[][]{{frame[x - 1][y], frame[x - 1][y - 1], frame[x][y - 1]}, {0, frame[x][y], 0}, {0, 0, 0}};
  84.                     break;
  85.                 }
  86.                 default:
  87.                     break;
  88.             }
  89.         }
  90.         //line
  91.         else if (isLine != 0) {
  92.             switch (isCorner) {
  93.                 case 11: {
  94.                     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}};
  95.                     break;
  96.                 }
  97.                 case 12: {
  98.                     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}};
  99.                     break;
  100.                 }
  101.                 case 13: {
  102.                     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}};
  103.                     break;
  104.                 }
  105.                 case 14: {
  106.                     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}};
  107.                     break;
  108.                 }
  109.                 default:
  110.                     break;
  111.             }
  112.         } else {
  113.             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]}};
  114.         }
  115.         return aroundUnit;
  116.     }
  117.     /**
  118.      * 更新环境中所有细胞生命状态
  119.      *
  120.      * @return 环境中是否还在活着的细胞
  121.      */
  122.     public boolean isfreshFrame() {
  123. //      boolean flag =false;
  124.         boolean hasLife = false;
  125.         BasicUnit basicUnit = new BasicUnit();
  126.         for (int i = 0; i < framesize; i++) {
  127.             for (int j = 0; j < framesize; j++) {
  128.                 int[][] aroundUnit = getAroundStatus(i, j);
  129.                 int status = basicUnit.getUnitCelltatus(aroundUnit);
  130.                 nextframe[i][j] = status;
  131.             }
  132.         }
  133.         for (int i = 0; i < framesize; i++) {
  134.             for (int j = 0; j < framesize; j++) {
  135.                 System.out.print(frame[i][j]);
  136.             }
  137.             System.out.println("");
  138.         }
  139.         System.out.println("");
  140.         for (int i = 0; i < framesize; i++) {
  141.             for (int j = 0; j < framesize; j++) {
  142.                 if (1 == nextframe[i][j]) {
  143.                     hasLife = true;
  144.                 }
  145.                 System.out.print(nextframe[i][j]);
  146.             }
  147.             System.out.println("");
  148.         }
  149. //      flag=true;
  150.         return hasLife;
  151.     }
  152.     /**
  153.      * 运行整个生命游戏
  154.      *
  155.      * @param lifeGame 生命游戏的初始对象
  156.      * @return 运行成功
  157.      */
  158.     public boolean run(LifeGame lifeGame) {
  159.         while (lifeGame.isfreshFrame()) {
  160.             lifeGame.setFrame(lifeGame.getNextframe());
  161.             System.out.println("");
  162.         }
  163.         return true;
  164.     }
  165. }
复制代码
表现与数据分离
  表现与数据数据分离
表现:顾名思义,就是表达出来的现象,在前端来看,就是html+css,就是平常所看到的的网页的架子;
数据:一般是从后端数据库或从哪爬过来的数据,然后在前台显示出来,即是网页中各个结构上的内容;
  好处与坏处
好处:模块化 –> 容易测试 –> 降低bug频率;
坏处:程序结构复杂,比较耗时,上手有学习曲线;
  应用场景:
项目具有明显的数据需求,比如要与很多Service交互,业务流程复杂,表单很多
  非应用场景:
项目是典型的静态信息展示型页面,或是微型的内部app,或是产品idea验证时期的MVP。
  1. <html xmlns="http://www.w3.org/1999/xhtml">
  2. <head>
  3.     <title></title>
  4.    
  5.    
  6. </head>
  7. <body>
  8.     <select id="pili">
  9.      <option value="叶小钗">叶小钗</option>
  10.         <option value="一页书">一页书</option>
  11.         <option value="素还真">素还真</option>
  12.     </select>
  13.    
  14. </body>
  15. </html>
复制代码

  • 我们好像就在view中使用了选择器获取dom。
  • 我们的数据似乎在model中,我们可以随意改变,但是并不会影响到我们dom。
  • view和model是完全独立的,我们的controller恰好把他们串联起来了。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表