title: Java进阶学习-9 细胞自动机
date: 2020-02-02 22:06:23
tags: Java学习
死亡:如果活着的邻居数量<2或>3 则死亡
新生:如果正好有3个邻居活着,则新生
其他情况则保持原状
两种看程序的方法
①从main开始看程序 看完
②从小的部件开始看 追父类一直看到顶层 从细节开始看 最后拼在一起
代码展示入下:
CellMachine.java
package cellmachine;
import javax.swing.JFrame;
import cell.Cell;
import field.Field;
import field.View;
public class CellMachine {
public static void main(String[] args) {
// 准备数据
Field field = new Field(30,30);
for(int row=0;row<field.getHeight();row++) {
for(int col=0;col<field.getWidth();col++){
field.place(row, col, new Cell());
}
}
for(int row=0;row<field.getHeight();row++) {
for(int col=0;col<field.getWidth();col++){
Cell cell =field.get(row,col);
if(Math.random()<0.2){
cell.reborn();
}
}
}
// 准备窗口
View view = new View(field);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Cells");
frame.setResizable(true);
frame.add(view);
frame.pack();
frame.setVisible(true);
// 计算业务逻辑
for(int i=0 ;i<1000; i++){
for(int row=0; row<field.getHeight();row++) {
for(int col=0;col<field.getHeight();col++){
Cell cell = field.get(row, col);
Cell[] neighbour = field.getNeighbour(row, col); //取出邻居
int numOfLive = 0;
for(Cell c: neighbour){ //遍历所有邻居
if(c.isAlive()) {
numOfLive++; //统计邻居数量
}
}
System.out.print("["+row+"]["+col+"]:");
System.out.print(cell.isAlive()?"live":"dead");
System.out.print(":"+numOfLive+"-->");
if(cell.isAlive()) {
if(numOfLive < 2 || numOfLive > 3) { //死掉规则
cell.die();
System.out.print("die");
}
} else if ( numOfLive == 3 ) {
cell.reborn();
System.out.print("reborn");
}
System.out.println();
}
}
System.out.print("UPDATE");
frame.repaint(); //此处每轮重画 field 每次重画一次
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
cell.java
package cell;
import java.awt.Graphics;
public class Cell {
public boolean alive = false;
public void die() { alive = false; }
public void reborn(){ alive = true;}
public boolean isAlive() { return alive; }
public void draw(Graphics g,int x,int y,int size){
g.drawRect(x, y, size, size);
if(alive) {
g.fillRect(x, y, size, size);
}
}
}
Field.java
package field;
import java.util.ArrayList;
import cell.Cell;
public class Field {
private int width;
private int height;
private Cell[][] field;
public Field(int width, int height){
this.width = width;
this.height = height;
field = new Cell[height][width];
}
public int getWidth() { return width; }
public int getHeight(){ return height; }
public Cell place(int row,int col,Cell o){
Cell ret = field[row][col];
field[row][col] = o;
return ret;
}
public Cell get(int row, int col){
return field[row][col];
}
public void clear(){
for (int i=0;i<width;i++)
for (int j=0;j<height;j++){
field[i][j] = null;
}
}
public Cell[] getNeighbour(int row,int col){
ArrayList<Cell> neighbour = new ArrayList<Cell>();
for(int i = -1;i<2;i++)
for(int j = -1;j<2;j++){
int r=row+i;
int c=col+j;
if (!(i==0&&j==0)&&r<width&&c<height&&r>-1&&c>-1){
neighbour.add(field[r][c]);
}
}
return neighbour.toArray(new Cell[neighbour.size()]);
}
}
View.java
package field;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import cell.Cell;
public class View extends JPanel{
private static final long serialVersionUID = -5258995676212660595L;
private static final int GRID_SIZE = 16;
private Field theField;
public View(Field field) {
theField = field;
}
@Override
public void paint(Graphics g) {
super.paint(g);
for( int row = 0; row < theField.getHeight();row++ ) {
for( int col = 0; col < theField.getWidth(); col++){
Cell cell = theField.get(row, col);
if( cell != null ){
cell.draw(g, col*GRID_SIZE, row*GRID_SIZE, GRID_SIZE);
}
}
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(theField.getWidth()*GRID_SIZE+1, theField.getHeight()*GRID_SIZE+1);
}
public static void main(String[] args) {
Field theField = new Field(10,10);
for(int i=0;i<10;i++)
for(int j=0;j<10;j++){
theField.place(i, j, new Cell());
}
View view = new View(theField);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("测试标题");
frame.setResizable(true);
frame.add(view);
frame.pack();
frame.setVisible(true);
}
}
java的语法是简单的,难是难在设计理念上,学习程序,最重要的是学习设计理念。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WP4M5s1Z-1580664072086)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202233122833.png)]
此处,数据就是每一轮计算后的结果使用Field存储数据,Field当中是一个一个的Cell,而View单纯只是拿到数据以后进行绘制整个图形。
CellMachine的作用一个是业务逻辑主体,绘制图形一个是重新绘制图形。是连接Field和View功能实现的桥梁。
此代码很重要的思想就是体现了数据与表现的分离
数据与表现分离
程序的业务逻辑与表现无关
表现可以是图形的也可以是文本的
表现可以是当地的也可以是远程的
学习语法是基础,学习编程最重要的是学习设计理念。
此处数据与表现是分离的。
数据与表现分开有很大好处,因为表现可以有很多,可以远程socket通信、画页面、使用文本ASCII码……故数据域表现分开好处很多 也易于扩展
View与Field的关系
表现与数据的关系
View只管根据Field画出图形
Field只管数据的存放
一旦数据更新 通知View重新画出整个画面
·不去精心设计哪个布局需要更新
·这样简化了程序逻辑
·是在计算机运行速度提高的基础上实现的
责任驱动的设计
将程序要实现的功能分配到合适的类/对象中,是设计中非常重要的一环。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D2qexZMn-1580664072087)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202234328557.png)]
网络化
图形界面本身有更高的解析度
但是画面网格化以后,数据就更容易处理。
问题
问题0.[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6gNYl8p-1580664072090)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202234817310.png)]
问题1.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wabG7hcF-1580664072091)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202234840269.png)]
问题2.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dX4EUTAT-1580664072094)(C:\Users\36987\AppData\Roaming\Typora\typora-user-images\image-20200202234943014.png)]