first commit

This commit is contained in:
Boris
2024-01-15 20:14:10 +00:00
commit 8c81ee28b7
3106 changed files with 474415 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
#BlueJ class context
comment0.params=
comment0.target=Cell()
comment0.text=\n\ Set\ the\ initial\ state\ to\ be\ DEAD.\n
comment1.params=initialState
comment1.target=Cell(int)
comment1.text=\n\ Set\ the\ initial\ state.\n\ @param\ initialState\ The\ initial\ state\n
comment2.params=
comment2.target=int\ getNextState()
comment2.text=\n\ Determine\ this\ cell's\ next\ state,\ based\ on\ the\n\ state\ of\ its\ neighbors.\n\ This\ is\ an\ implementation\ of\ the\ rules\ for\ Brian's\ Brain.\n\ @return\ The\ next\ state.\n
comment3.params=neighborList
comment3.target=void\ setNeighbors(java.util.ArrayList)
comment3.text=\n\ Receive\ the\ list\ of\ neighboring\ cells\ and\ take\n\ a\ copy.\n\ @param\ neighborList\ Neighboring\ cells.\n
comment4.params=
comment4.target=int\ getState()
comment4.text=\n\ Get\ the\ state\ of\ this\ cell.\n\ @return\ The\ state.\n
comment5.params=state
comment5.target=void\ setState(int)
comment5.text=\n\ Set\ the\ state\ of\ this\ cell.\n\ @param\ The\ state.\n
numComments=6

View File

@@ -0,0 +1,97 @@
import java.util.*;
/**
* A cell in a 2D cellular automaton.
* The cell has multiple possible states.
* This is an implementation of the rules for Brian's Brain.
* @see https://en.wikipedia.org/wiki/Brian%27s_Brain
*
* @author David J. Barnes and Michael Kölling
* @version 2016.02.29
*/
public class Cell
{
// The possible states.
public static final int ALIVE = 0, DEAD = 1, DYING = 2;
// The number of possible states.
public static final int NUM_STATES = 3;
// The cell's state.
private int state;
// The cell's neighbors.
private Cell[] neighbors;
/**
* Set the initial state to be DEAD.
*/
public Cell()
{
this(DEAD);
}
/**
* Set the initial state.
* @param initialState The initial state
*/
public Cell(int initialState)
{
state = initialState;
neighbors = new Cell[0];
}
/**
* Determine this cell's next state, based on the
* state of its neighbors.
* This is an implementation of the rules for Brian's Brain.
* @return The next state.
*/
public int getNextState()
{
if(state == DEAD) {
// Count the number of neighbors that are alive.
int aliveCount = 0;
for(Cell n : neighbors) {
if(n.getState() == ALIVE) {
aliveCount++;
}
}
return aliveCount == 2 ? ALIVE : DEAD;
}
else if(state == DYING) {
return DEAD;
}
else {
return DYING;
}
}
/**
* Receive the list of neighboring cells and take
* a copy.
* @param neighborList Neighboring cells.
*/
public void setNeighbors(ArrayList<Cell> neighborList)
{
neighbors = new Cell[neighborList.size()];
neighborList.toArray(neighbors);
}
/**
* Get the state of this cell.
* @return The state.
*/
public int getState()
{
return state;
}
/**
* Set the state of this cell.
* @param The state.
*/
public void setState(int state)
{
this.state = state;
}
}

View File

@@ -0,0 +1,29 @@
#BlueJ class context
comment0.params=
comment0.target=Environment()
comment0.text=\n\ Create\ an\ environment\ with\ the\ default\ size.\n
comment1.params=numRows\ numCols
comment1.target=Environment(int,\ int)
comment1.text=\n\ Create\ an\ environment\ with\ the\ given\ size.\n\ @param\ numRows\ The\ number\ of\ rows.\n\ @param\ numCols\ The\ number\ of\ cols;\n
comment2.params=
comment2.target=void\ step()
comment2.text=\n\ Run\ the\ automaton\ for\ one\ step.\n
comment3.params=
comment3.target=void\ reset()
comment3.text=\n\ Reset\ the\ state\ of\ the\ automaton\ to\ all\ DEAD.\n
comment4.params=
comment4.target=void\ randomize()
comment4.text=\n\ Generate\ a\ random\ setup.\n
comment5.params=row\ col\ state
comment5.target=void\ setCellState(int,\ int,\ int)
comment5.text=\n\ Set\ the\ state\ of\ one\ cell.\n\ @param\ row\ The\ cell's\ row.\n\ @param\ col\ The\ cell's\ col.\n\ @param\ state\ The\ cell's\ state.\n
comment6.params=
comment6.target=Cell[][]\ getCells()
comment6.text=\n\ Return\ the\ grid\ of\ cells.\n\ @return\ The\ grid\ of\ cells.\n
comment7.params=numRows\ numCols
comment7.target=void\ setup(int,\ int)
comment7.text=\n\ Setup\ a\ new\ environment\ of\ the\ given\ size.\n\ @param\ numRows\ The\ number\ of\ rows.\n\ @param\ numCols\ The\ number\ of\ cols;\n
comment8.params=
comment8.target=void\ setupNeighbors()
comment8.text=\n\ Give\ to\ a\ cell\ a\ list\ of\ its\ neighbors.\n
numComments=9

View File

@@ -0,0 +1,161 @@
import java.security.SecureRandom;
import java.util.*;
/**
* Maintain the environment for a 2D cellular automaton.
*
* @author David J. Barnes
* @version 2016.02.29
*/
public class Environment
{
// Default size for the environment.
private static final int DEFAULT_ROWS = 50;
private static final int DEFAULT_COLS = 50;
// The grid of cells.
private Cell[][] cells;
// Visualization of the environment.
private final EnvironmentView view;
/**
* Create an environment with the default size.
*/
public Environment()
{
this(DEFAULT_ROWS, DEFAULT_COLS);
}
/**
* Create an environment with the given size.
* @param numRows The number of rows.
* @param numCols The number of cols;
*/
public Environment(int numRows, int numCols)
{
setup(numRows, numCols);
randomize();
view = new EnvironmentView(this, numRows, numCols);
view.showCells();
}
/**
* Run the automaton for one step.
*/
public void step()
{
int numRows = cells.length;
int numCols = cells[0].length;
// Build a record of the next state of each cell.
int[][] nextStates = new int[numRows][numCols];
// Ask each cell to determine its next state.
for(int row = 0; row < numRows; row++) {
int[] rowOfStates = nextStates[row];
for(int col = 0; col < numCols; col++) {
rowOfStates[col] = cells[row][col].getNextState();
}
}
// Update the cells' states.
for(int row = 0; row < numRows; row++) {
int[] rowOfStates = nextStates[row];
for(int col = 0; col < numCols; col++) {
setCellState(row, col, rowOfStates[col]);
}
}
}
/**
* Reset the state of the automaton to all DEAD.
*/
public void reset()
{
int numRows = cells.length;
int numCols = cells[0].length;
for(int row = 0; row < numRows; row++) {
for(int col = 0; col < numCols; col++) {
setCellState(row, col, Cell.DEAD);
}
}
}
/**
* Generate a random setup.
*/
public void randomize()
{
int numRows = cells.length;
int numCols = cells[0].length;
SecureRandom rand = new SecureRandom();
for(int row = 0; row < numRows; row++) {
for(int col = 0; col < numCols; col++) {
setCellState(row, col, rand.nextInt(Cell.NUM_STATES));
}
}
}
/**
* Set the state of one cell.
* @param row The cell's row.
* @param col The cell's col.
* @param state The cell's state.
*/
public void setCellState(int row, int col, int state)
{
cells[row][col].setState(state);
}
/**
* Return the grid of cells.
* @return The grid of cells.
*/
public Cell[][] getCells()
{
return cells;
}
/**
* Setup a new environment of the given size.
* @param numRows The number of rows.
* @param numCols The number of cols;
*/
private void setup(int numRows, int numCols)
{
cells = new Cell[numRows][numCols];
for(int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
cells[row][col] = new Cell();
}
}
setupNeighbors();
}
/**
* Give to a cell a list of its neighbors.
*/
private void setupNeighbors()
{
int numRows = cells.length;
int numCols = cells[0].length;
// Allow for 8 neighbors plus the cell.
ArrayList<Cell> neighbors = new ArrayList<>(9);
for(int row = 0; row < numRows; row++) {
for(int col = 0; col < numCols; col++) {
Cell cell = cells[row][col];
// This process will also include the cell.
for(int dr = -1; dr <= 1; dr++) {
for(int dc = -1; dc <= 1; dc++) {
int nr = (numRows + row + dr) % numRows;
int nc = (numCols + col + dc) % numCols;
neighbors.add(cells[nr][nc]);
}
}
// The neighbours should not include the cell at
// (row,col) so remove it.
neighbors.remove(cell);
cell.setNeighbors(neighbors);
neighbors.clear();
}
}
}
}

View File

@@ -0,0 +1,17 @@
#BlueJ class context
comment0.params=env\ rows\ cols
comment0.target=EnvironmentView(Environment,\ int,\ int)
comment0.text=\n\ Constructor\ for\ objects\ of\ class\ EnvironmentView\n\ @param\ env\n
comment1.params=rows\ cols
comment1.target=void\ setupGrid(int,\ int)
comment1.text=\n\ Setup\ a\ new\ environment\ of\ the\ given\ size.\n\ @param\ rows\ The\ number\ of\ rows.\n\ @param\ cols\ The\ number\ of\ cols;\n
comment2.params=
comment2.target=void\ showCells()
comment2.text=\n\ Show\ the\ states\ of\ the\ cells.\n
comment3.params=
comment3.target=void\ setupControls()
comment3.text=\n\ Set\ up\ the\ animation\ controls.\n
comment4.params=speedPercentage
comment4.target=void\ setDelay(int)
comment4.text=\n\ Set\ the\ animation\ delay.\n\ @param\ speedPercentage\ (100-speedPercentage)\ as\ a\ percentage\ of\ the\ LONGEST_DELAY.\n
numComments=5

View File

@@ -0,0 +1,271 @@
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
/**
* A GUI for the environment, with runtime controls.
*
* @author David J. Barnes and Michael Kölling
* @version 2016.02.29
*/
public class EnvironmentView extends JFrame
{
// The longest delay for the animation, in milliseconds.
private static final int LONGEST_DELAY = 1000;
// Colors for the different cell states.
private static final Color[] colors = {
Color.WHITE, // Alive
new Color(68, 100, 129), // Dead
new Color(204, 196, 72), // Dying
};
private GridView view;
private final Environment env;
private boolean running;
private int delay;
/**
* Constructor for objects of class EnvironmentView
* @param env
*/
public EnvironmentView(Environment env, int rows, int cols)
{
super("2D Cellular Automaton");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocation(20, 20);
this.env = env;
this.running = false;
setDelay(50);
setupControls();
setupGrid(rows, cols);
pack();
setVisible(true);
}
/**
* Setup a new environment of the given size.
* @param rows The number of rows.
* @param cols The number of cols;
*/
private void setupGrid(int rows, int cols)
{
Container contents = getContentPane();
view = new GridView(rows, cols);
contents.add(view, BorderLayout.CENTER);
}
/**
* Show the states of the cells.
*/
public void showCells()
{
Cell[][] cells = env.getCells();
if(!isVisible()) {
setVisible(true);
}
view.preparePaint();
for(int row = 0; row < cells.length; row++) {
Cell[] cellRow = cells[row];
int numCols = cellRow.length;
for(int col = 0; col < numCols; col++) {
int state = cellRow[col].getState();
view.drawMark(col, row, colors[state]);
}
}
view.repaint();
}
/**
* Set up the animation controls.
*/
private void setupControls()
{
// Continuous running.
final JButton run = new JButton("Run");
run.addActionListener(e -> {
if(!running) {
running = true;
try {
new Runner().execute();
}
catch(Exception ex) {
}
}
});
// Single stepping.
final JButton step = new JButton("Step");
step.addActionListener(e -> {
running = false;
env.step();
showCells();
});
// Pause the animation.
final JButton pause = new JButton("Pause");
pause.addActionListener(e -> running = false);
// Reset of the environment
final JButton reset = new JButton("Reset");
reset.addActionListener(e -> {
running = false;
env.reset();
showCells();
});
// Randomize the environment.
final JButton randomize = new JButton("Random");
randomize.addActionListener(e -> {
running = false;
env.randomize();
showCells();
});
Container contents = getContentPane();
// A speed controller.
final JSlider speedSlider = new JSlider(0, 100);
speedSlider.addChangeListener(e -> {
setDelay(speedSlider.getValue());
});
Container speedPanel = new JPanel();
speedPanel.setLayout(new GridLayout(2, 1));
speedPanel.add(new JLabel("Animation Speed", SwingConstants.CENTER));
speedPanel.add(speedSlider);
contents.add(speedPanel, BorderLayout.NORTH);
// Place the button controls.
JPanel controls = new JPanel();
controls.add(run);
controls.add(step);
controls.add(pause);
controls.add(reset);
controls.add(randomize);
contents.add(controls, BorderLayout.SOUTH);
}
/**
* Set the animation delay.
* @param speedPercentage (100-speedPercentage) as a percentage of the LONGEST_DELAY.
*/
private void setDelay(int speedPercentage)
{
delay = (int) ((100.0 - speedPercentage) * LONGEST_DELAY / 100);
}
/**
* Provide stepping of the animation.
*/
private class Runner extends SwingWorker<Boolean, Void>
{
@Override
/**
* Repeatedly single-step the environment as long
* as the animation is running.
*/
public Boolean doInBackground()
{
while(running) {
env.step();
showCells();
try {
Thread.sleep(delay);
}
catch(InterruptedException e) {
}
}
return true;
}
}
/**
* Provide a graphical view of a rectangular grid.
*/
@SuppressWarnings("serial")
private class GridView extends JPanel
{
private final int GRID_VIEW_SCALING_FACTOR = 10;
private final int gridWidth, gridHeight;
private int xScale, yScale;
private Dimension size;
private Graphics g;
private Image fieldImage;
/**
* Create a new GridView component.
*/
public GridView(int height, int width)
{
gridHeight = height;
gridWidth = width;
size = new Dimension(0, 0);
}
/**
* Tell the GUI manager how big we would like to be.
*/
@Override
public Dimension getPreferredSize()
{
return new Dimension(gridWidth * GRID_VIEW_SCALING_FACTOR,
gridHeight * GRID_VIEW_SCALING_FACTOR);
}
/**
* Prepare for a new round of painting. Since the component
* may be resized, compute the scaling factor again.
*/
public void preparePaint()
{
if(! size.equals(getSize())) {
size = getSize();
fieldImage = view.createImage(size.width, size.height);
g = fieldImage.getGraphics();
xScale = size.width / gridWidth;
if(xScale < 1) {
xScale = GRID_VIEW_SCALING_FACTOR;
}
yScale = size.height / gridHeight;
if(yScale < 1) {
yScale = GRID_VIEW_SCALING_FACTOR;
}
}
}
/**
* Paint on grid location on this field in a given color.
*/
public void drawMark(int x, int y, Color color)
{
g.setColor(color);
g.fillRect(x * xScale, y * yScale, xScale-1, yScale-1);
}
/**
* The field view component needs to be redisplayed. Copy the
* internal image to screen.
*/
@Override
public void paintComponent(Graphics g)
{
if(fieldImage != null) {
Dimension currentSize = getSize();
if(size.equals(currentSize)) {
g.drawImage(fieldImage, 0, 0, null);
}
else {
// Rescale the previous image.
g.drawImage(fieldImage, 0, 0, currentSize.width, currentSize.height, null);
}
}
}
}
}

View File

@@ -0,0 +1,15 @@
Project: brain
Aothors: David J. Barnes and Michael Kölling
This project is part of the material of the book
Objects First with Java - A Practical Introduction using BlueJ
Sixth edition
David J. Barnes and Michael Kölling
Pearson Education, 2016
It is discussed in chapter 7.
An implementation of the 2D cellular automaton known as Brian's Brain.
See https://en.wikipedia.org/wiki/Brian%27s_Brain

View File

@@ -0,0 +1,67 @@
#BlueJ package file
dependency1.from=Environment
dependency1.to=Cell
dependency1.type=UsesDependency
dependency2.from=Environment
dependency2.to=EnvironmentView
dependency2.type=UsesDependency
dependency3.from=EnvironmentView
dependency3.to=Environment
dependency3.type=UsesDependency
dependency4.from=EnvironmentView
dependency4.to=Cell
dependency4.type=UsesDependency
objectbench.height=76
objectbench.width=741
package.editor.height=412
package.editor.width=633
package.editor.x=70
package.editor.y=80
package.numDependencies=4
package.numTargets=3
package.showExtends=true
package.showUses=true
project.charset=UTF-8
readme.editor.height=700
readme.editor.width=900
readme.editor.x=53
readme.editor.y=23
target1.editor.height=818
target1.editor.width=999
target1.editor.x=798
target1.editor.y=92
target1.height=50
target1.name=EnvironmentView
target1.naviview.expanded=false
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=120
target1.x=210
target1.y=230
target2.editor.height=945
target2.editor.width=954
target2.editor.x=206
target2.editor.y=214
target2.height=50
target2.name=Environment
target2.naviview.expanded=true
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=100
target2.x=120
target2.y=50
target3.editor.height=777
target3.editor.width=969
target3.editor.x=88
target3.editor.y=23
target3.height=50
target3.name=Cell
target3.naviview.expanded=true
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=80
target3.x=340
target3.y=140