Java进阶学习-9 细胞自动机


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)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值