狐狸和兔子:细胞自动机升级版
包:foxandrabbit
主程序(FoxAndRabbit)
package foxandrabbit;
import java.util.ArrayList;
import javax.swing.JFrame;
import field.Field;
import field.View;
import field.Location;
import animal.Animal;
import animal.Fox;
import animal.Rabbit;
import cell.Cell;
public class FoxAndRabbit {
//成员变量
private Field theField;//Field变量,用来管理新的网格
private View theView;//继承自Jpanel的类,用来显示图形
/*------构造函数------*/
public FoxAndRabbit(int size) {
//创建网格
theField=new Field(size,size);
//遍历网格
for(int row=0;row<theField.getHeight();row++)
{
for(int col=0;col<theField.getWidth();col++)
{
double probability=Math.random();
//随机放入狐狸
if(probability<0.05)
{
theField.place(row,col,new Fox());
}
//随机放入兔子
else if(probability<0.15)
{
theField.place(row, col,new Rabbit());
}
}
}
/*------把theField加入到显示框------*/
theView=new View(theField);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setTitle("Cells");
frame.add(theView);
frame.pack();
frame.setVisible(true);
}
/*------开始函数,传入的参数是程序要执行的次数------*/
public void start(int steps)
{
for (int i=0;i<steps;i++) {
step();
theView.repaint();//Java底层函数
try {
Thread.sleep(200);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*------step()函数,每次更新表格- - - - - -*/
public void step() {
for(int row=0;row<theField.getHeight();row++)
{
for(int col=0;col<theField.getWidth();col++)
{
//获取所有Cell的对象变量
Cell cell=theField.get(row, col);
if(cell!=null)
{
//把管理的对象造型为Animal对象
Animal animal=(Animal)cell;
//年龄增长
animal.grow();
if(animal.isAlive())
{
//向周围移动
Location loc=animal.move(theField.getFreeNeighbour(row, col));
if(loc!=null) { theField.move(row,col,loc); }
//获取周围的兔子,储存进容器里面
Cell[] neighbour=theField.getNeighbour(row, col);
ArrayList<Animal> listRabbit=new ArrayList<Animal>();
for(Cell an:neighbour)
{//instanceof关键字,判断是不是某个类的实例
if(an instanceof Rabbit) { listRabbit.add((Rabbit)an); }
}
//吃掉兔子
if(!listRabbit.isEmpty()) //isEmpty()是ArrayList的函数,没有元素则返回true
{
//这里涉及到了多态,这个animal实际上是Fox的对象,调用的是Fox的feed()
//(animal本身是抽象类,自己不可能有对象的)
Animal fed=animal.feed(listRabbit);
//fed得到了兔子的对象之后,调用函数删除这个对象(被吃掉
if(fed!=null) { theField.remove((Cell)fed); }
}
//动物繁殖
Animal baby=animal.breed();
if(baby!=null) { theField.placeRandomAdj(row,col,(Cell)baby); }
}
else { theField.remove(row ,col); }
}
}
}
}
public static void main(String[] args) {
FoxAndRabbit fr=new FoxAndRabbit(30);
fr.start(50);
}
}
包:field
数据处理(Field)
package field;
import java.util.ArrayList;
import cell.Cell;
public class Field {
private int width;
private int height;
private Cell[][] field;// 声明有这么个数组变量,但未承接任何对象
private static final Location[] adjacent = {
new Location(-1, -1), new Location(-1, 0), new Location(-1, 1),
new Location(0, -1), new Location(0, 0), new Location(0, 1),
new Location(1, -1), new Location(1, 0), new Location(1, 1),
};
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 cell) {
// !这里的Cell o并非Cell类的对象,而是实现了Cell接口的对象
field[row][col] = cell;
Cell ret = field[row][col];
return ret;
}
public Cell get(int row, int col) {
return field[row][col];
}
public Cell[] getNeighbour(int row, int col) {
ArrayList<Cell> list = 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 (r > -1 && r < height && c > -1 && c < width && !(r == row && c == col)) {
list.add(field[r][c]);
}
}
}
return list.toArray(new Cell[list.size()]);
}
public Location[] getFreeNeighbour(int row, int col) {
ArrayList<Location> list = new ArrayList<Location>();
for (Location loc : adjacent) {
int r = row + loc.getRow();
int c = col + loc.getCol();
if (r > -1 && r < height && c > -1 && c < width && field[r][c] == null) {
list.add(new Location(r, c));
}
}
// !学着点
return list.toArray(new Location[list.size()]);
}
public boolean placeRandomAdj(int row, int col, Cell cell) {
boolean ret = false;
Location[] freeAdj = getFreeNeighbour(row, col);
if (freeAdj.length > 0) {
int idx = (int) (Math.random() * freeAdj.length);
field[freeAdj[idx].getRow()][freeAdj[idx].getCol()] = cell;
ret = true;
}
return ret;
}
public void clear() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
field[i][j] = null;
}
}
}
public void remove(Cell fed) {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (field[row][col] == fed) {
field[row][col] = null;
break;
}
}
}
}
public Cell remove(int row, int col) { // *函数重构
field[row][col] = null;
Cell ret = field[row][col];
return ret;
}
public void move(int row, int col, Location loc) {
field[loc.getRow()][loc.getCol()] = field[row][col];
remove(row, col);
}
}
图形绘制(View)
package field;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
import cell.Cell;
public class View extends JPanel {
private static final long serialVersionUID = -2417015700213488315L;
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);
g.setColor(Color.GRAY);
for (int row = 0; row < theField.getHeight(); row++)
g.drawLine(0, row * GRID_SIZE, theField.getWidth() * GRID_SIZE, row * GRID_SIZE);
for ( int col = 0; col<theField.getWidth(); col++ )
g.drawLine(col * GRID_SIZE, 0, col * GRID_SIZE, theField.getHeight() * GRID_SIZE);
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);
}
}
存储移动位置(Location)
package field;
public class Location {
private int row;
private int col;
public Location(int row, int col) {
this.row = row;
this.col = col;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
}
包:Cell
接口(Cell)
package cell;
import java.awt.Graphics;
public interface Cell {//注意这里不能写成interface class
/*
* Cell是一个接口而非类(接口是一种完全抽象的抽象类)
* !这个接口就是为了实现Fox和Rabbit类new的对象能够传递给Field类
* Field类中指明需要的对象的类是Cell而Cell是作为中间承接者
* Fox和Rabbit类需要有implements Cell语句来实现接口
* !注意这里函数可以不用写函数前缀,只需要写返回值类型
* ?抽象类无函数主体,只需声明函数原型,实现抽象类/接口的类都必须Override所有抽象方法,否则此子类仍为抽象类
* ?abstract与final是冲突对立关系,抽象是用来被继承或重写的,final相反是不让继承/重写的
*/
void draw(Graphics g, int x, int y, int size);
}
包:animal
动物类[父类](Animal)
package animal;
import java.util.ArrayList;
import field.Location;
public abstract class Animal {
private int ageLimit;
private int breedableAge;
private int age;
private boolean isAlive = true;
public Animal(int ageLimit, int breedableAge) {
this.ageLimit = ageLimit;
this.breedableAge = breedableAge;
}
protected int getAge() {
return age;
}
protected double getAgePercent() {
return (double) age / (double) ageLimit;
}
public abstract Animal breed();
public void grow() {
age++;
if (age >= ageLimit)
die();
}
public void die() {
isAlive = false;
}
public boolean isAlive() {
return isAlive;
}
public boolean isBreedable() {
return (age >= breedableAge);
}
//概率移动,移动位置
public Location move(Location[] freeAdj) {
Location ret = null;
if (freeAdj.length > 0 && Math.random() < 0.02) {
ret = freeAdj[(int) (Math.random() * freeAdj.length)];
}
return ret;
}
@Override
public String toString() {
return "" + age + ":" + (isAlive ? "live" : "dead");
}
public Animal feed(ArrayList<Animal> neighbor) {
return null;
}
protected void longerLife(int inc) {
ageLimit += inc;
}
}
狐狸[子类](Fox)
package animal;
import java.awt.Graphics;
import java.awt.Color;
import java.util.ArrayList;
import cell.Cell;
/**
* *Fox实现接口Cell,使Fox对象能间接传给Field
*/
public class Fox extends Animal implements Cell {
public Fox() {
super(20, 4);
}
@Override // 实现接口Cell中的draw()
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int) ((1 - getAgePercent()) * 255);
g.setColor(new Color(0, 0, 0, alpha));
g.fillRect(x, y, size, size);
}
@Override
public Animal breed() {
Animal ret = null;
if (isBreedable() && Math.random() < 0.05) {
ret = new Fox();
}
return ret;
}
@Override
public String toString() {
return ("Fox:" + super.toString());
}
@Override
public Animal feed(ArrayList<Animal> neighbor) { //狐狸进食增加寿命
Animal ret = null;
if (Math.random() < 0.2) {
ret = neighbor.get((int) (Math.random() * neighbor.size()));
longerLife(2);
}
return ret;
}
}
兔子[子类](Rabbit)
package animal;
import java.awt.Color;
import java.awt.Graphics;
import cell.Cell;
public class Rabbit extends Animal implements Cell {
public Rabbit() {
super(10, 2); // *寿命&&生育年龄
}
@Override
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int) ((1 - getAgePercent()) * 255);
g.setColor(new Color(255, 0, 0, alpha));
g.fillRect(x, y, size, size);
}
@Override
public Animal breed() {
Animal ret = null;
if (isBreedable() && Math.random() < 0.12) {
ret = new Rabbit();
}
return ret;
}
@Override
public String toString() {
return "Rabbit" + super.toString();
}
}
相关:
Java:Swing