import javax.swing.JFrame;
import cell.Cell;
import field.Field;
import field.View;
public class CellMachine {
//看懂代码从 main 函数开始,这是老师数次在课堂上强调的
public static void main(String[] args) {
//定义一个30x30的网格
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());
}
}
/*定义一个细胞的变量,这个变量依次管理所有的细胞对象,如果产生的随机数小于1/5,把这个细胞变活*/
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);//把 field作为参数放入 view 里面去
JFrame frame = new JFrame();//创建frame框架
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口,停止程序
frame.setResizable(false);//不可被拉伸
frame.setTitle("Cells");//设置标题 Cells
frame.add(view);//把 view 加进来显示(有点类似于ArrayList 也是储存的对象
/*
Causes this Window to be sized to fit the preferred
size and layouts of its subcomponents
上面是官方文档给的英文注释,他的意思是
把窗口调整为推荐的大小,并自动排版子组件,学 java 要多查阅文档
在 eclipse 里面你可以把光标放到这个方法上,他会自动加载出文档
(如果能看懂英文可以直接读
*/
frame.pack();
frame.setVisible(true);//设置窗口课可见
/*-----------这里是运行的主代码,代码比较多,一定要细细思考---------*/
for ( int i=0; i<1000; i++ ) //做了1000次循环(也就是遍历了1000次区域,
{ //一个表格算一步的话,走路900,000步
for ( int row = 0; row<field.getHeight(); row++ )
{
for ( int col = 0; col<field.getWidth(); col++ )
{
//上面两个 for 循环遍历了整个区域
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(); //周围存活数量小于2大于3,细胞死亡
System.out.print("die");//意思是,周围细胞为2或3的时候不用死
}
}
else if ( numOfLive == 3 ) //如果细胞是死亡的,周围存活数量为3
{
cell.reborn();//细胞可以复活
System.out.print("reborn");
}
System.out.println();
}//第三层for循环
}//第二层for循环
System.out.println("UPDATE");//这个我不知道怎么清除掉的,应该输出1000遍才对
frame.repaint();//Repaints this component. 更新表格数据
//这里是异常,属于后面讲解的内容 Thread 与线程有关,这里不做讨论
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//第一层for循环
}
}
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);//Invoked by Swing to draw components. 画出传入的图形
//遍历传入的区域
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 ) //该区域有Cell的对象
{//调用draw函数 对象为传入的 g, x=1x16,y=1x16,y=2x16...
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);
}//Constructs a Dimension and initializesit to the specified width and specified height
//创建一个维度,参数是长和宽,这个函数我也没有找到被调用的地方
/*-----------------------以下是测试代码,不再写注释--------------------------------*/
public static void main(String[] args) {
Field field = new Field(10,10);
for ( int row = 0; row<field.getHeight(); row++ ) {
for ( int col = 0; col<field.getWidth(); col++ ) {
field.place(row, col, new Cell());
}
}
View view = new View(field);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setTitle("Cells");
frame.add(view);
frame.pack();
frame.setVisible(true);
}
}
import java.util.ArrayList;
import cell.Cell;
public class Field {
private int width;
private int height;
private Cell[][] field;//创建一个二维的Cell变量数组,用于储存细胞
//构造函数
public Field(int width, int height) {
this.width = width;
this.height = height;
field = new Cell[height][width];//同时创造 宽乘高个细胞对象,放进field
}
/*--------------------这两个函数用于给外界使用-------------------*/
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某个位置上对细胞对象的管理权限赋给ret
field[row][col] = o;//该位置去管理一个新的对象
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;//r,c为方位
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 void clear() {//清除所有细胞,目前没有看到被调用
for ( int i=0; i<height; i++ ) {
for ( int j=0; j<width; j++ ) {
field[i][j] = null;
}
}
}
}
//import java.awt.Color;//测试代码
import java.awt.Graphics;
public class Cell {
private 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);//x y是坐标,size是大小,
//画一个位于x,y位置上,底色百色的色块
if ( alive ) //如果存活,填充颜色,默认为黑色
{
// g.setColor(Color.yellow);//测试代码
g.fillRect(x, y, size, size);//给色块填充颜色,参数与drawRect一样
}
}
}
view 代码最为复杂,其中的几个函数没有被调用