📄 cellspace.java
字号:
package GameOfLife;
import java.awt.*;
import java.util.*;
public class CellSpace extends Canvas
{
//constants ->growthTYPE->growCellSugar()
static int SEED = 0, RENEW = 1;
//constants ->detailLevel->showStatus()
static int DETAIL = 0, ALL = 1, SUMMARY = 2;
public int generations = 0;
public int population;
public int sugarCount;
static int destinationI = -1, destinationJ = -1;
private int cellSize;
private int cellRows;
private int cellCols;
private boolean cellUnderMouse;
private boolean cells[][];
private int cellsBuffer[][];
private double cellsSugar[][];
private Image offScreenImage = null;
private Graphics offScreenGraphics;
private Citizen citizen[][];
//datastream - collects data from multiple methods
private String bigDataStream;
public CellSpace( int cellSize, int cellCols, int cellRows )
{
cells = new boolean[cellCols][cellRows];
cellsBuffer = new int[cellCols][cellRows];
cellsSugar = new double[cellCols][cellRows];
//array of citizen - not all elements actually contain citizens
citizen = new Citizen[cellCols][cellRows];
for (int i=0;i<cellCols;i++)
for (int j=0;j<cellRows;j++)
citizen[i][j]= new Citizen();
this.cellSize = cellSize;
this.cellCols = cellCols;
this.cellRows = cellRows;
//generate a sugar distribution in CellSpace
growCellSugar( SEED );
//display sugar distribution
if( GoLconst.DEBUG || GoLconst.DEBUG_CELLSCAPE_SUGAR )
{ bigDataStream += showSugarscapeStats(0,0,cellCols,cellRows); } //display sugar distribution
reshape(0, 0, cellSize*cellCols-1, cellSize*cellRows-1);
//Initialize grid & list of citizens
clear();
}
public int getCellRows()
{ return cellRows; }
public int getCellCols()
{ return cellCols; }
public int getCellSugar(int col, int row)
{ return (int) cellsSugar[col][row]; }
public void setCellSugar(int col, int row)
{ //**The decimal portion of sugar is currently discarded
cellsSugar[col][row] = 0.0;
}
/***Generate initial/periodic distribution of sugar in Cellspace***/
public void growCellSugar(int growthType)
{ sugarCount = 0;
for(int i = 0; i<cellCols; i++)
for(int j = 0; j < cellRows; j++)
{ if( growthType == RENEW )
{ //renew available sugar up to max cell capacity
if( GoLconst.LIMIT_CELL_SUGAR )
cellsSugar[i][j] += cellsSugar[i][j] < GoLconst.SUGAR_MAX_CELL ?
GoLconst.SUGAR_RENEW : 0;
else
cellsSugar[i][j] += GoLconst.SUGAR_RENEW;
} else
{ if( Math.random() > GoLconst.GRID_FERTILITY )
cellsSugar[i][j] = 0.0;
else
cellsSugar[i][j] = ( (int)(Math.random() *
GoLconst.SUGAR_MAX_CELL) );
}
sugarCount += cellsSugar[i][j];
}
}
public synchronized boolean mouseUp(java.awt.Event evt, int x, int y) {
toggleCellUnderMouse( x,y );
return true;
}
public synchronized boolean mouseDown(java.awt.Event evt, int x, int y)
{ try { cellUnderMouse = cells[x/cellSize][y/cellSize];
} catch ( java.lang.ArrayIndexOutOfBoundsException e ) {}
return true;
}
public synchronized boolean mouseDrag(java.awt.Event evt, int x, int y)
{ toggleCellUnderMouse( x,y );
return true;
}
public synchronized boolean toggleCellUnderMouse(int x, int y)
{ //Determine Col from pixel position on grid
int col = x/cellSize, row = y/cellSize;
// toggle cell
try { cells[col][row] = !cellUnderMouse; }
catch ( java.lang.ArrayIndexOutOfBoundsException e ) {}
//Cell toggled ON - create new citizen
if( cells[col][row] )
{ int RANDOM = -1;
citizen[col][row].setVision(RANDOM);
citizen[col][row].setMetabolism(RANDOM);
citizen[col][row].sugar = citizen[col][row].setSugar(RANDOM)
+ getCellSugar(col,row);
setCellSugar(col,row); //cell sugar content set to zero
population++;
if( GoLconst.DEBUG || GoLconst.DEBUG_CREATE_CITIZEN )
{ bigDataStream += showCitizenStats("Born! Citizen", col, row); }
} else //Cell toggled OFF - so kill citizen
{
citizen[col][row].setVision(0);
citizen[col][row].setMetabolism(0);
citizen[col][row].setSugar(0);
population--;
if( GoLconst.DEBUG || GoLconst.DEBUG_CREATE_CITIZEN )
{ bigDataStream += showCitizenStats("Died! Citizen", col, row); }
}
repaint();
return true;
}
public synchronized void update( Graphics theG )
{
Dimension d = size();
if((offScreenImage == null) ) {
offScreenImage = createImage( d.width, d.height );
offScreenGraphics = offScreenImage.getGraphics();
}
paint(offScreenGraphics);
theG.drawImage( offScreenImage, 0, 0, null );
}
public void paint(Graphics g)
{ int colorVal;
// draw background (MSIE doesn't do that)
g.setColor( Color.lightGray ); //sets/resets window background - new Color(0,0,240)
//font setting for grid coordinates
g.setFont( new java.awt.Font("Verdana",Font.PLAIN,(int)(cellSize/2.5)) );
//draws the window background for the grid
g.fillRect( 0, 0, cellSize*cellCols-1, cellSize*cellRows-1 );
// draw grid
g.setColor( getBackground() );
//draw the vertical lines on the grid
for( int x=1; x<cellCols; x++ )
{ g.drawLine( x*cellSize-1, 0, x*cellSize-1, cellSize*cellRows-1 ); }
//draw the horizontal lines on the grid
for( int y=1; y<cellRows; y++ )
{ g.drawLine( 0, y*cellSize-1, cellSize*cellCols-1, y*cellSize-1 ); }
// draw populated cells
g.setColor( Color.gray );
for( int x=0; x<cellCols; x++ ) {
for( int y=0; y<cellRows; y++ )
{ //**All Menu Selections Other Than Sugarscape
if( !GoLconst.flagSugarscape )
{ if ( cells[x][y] )
{ g.setColor( Color.yellow ); }
else g.setColor( Color.gray );
g.fillRect( x*cellSize, y*cellSize, cellSize-1, cellSize-1 );
continue;
}
//**If Cell Occupied, Draw Citizen
if ( cells[x][y] )
{ int currVision = citizen[x][y].getVision();
int currMetabolism = citizen[x][y].getMetabolism();
int currSugar = citizen[x][y].getSugar();
int currSugarReserve = currSugar / currMetabolism;
//Determine color of citizen object//
if( currSugarReserve < 10 )
//Color.red - gets darker with increasing sugar reserve
{ g.setColor( new Color(255-(currSugarReserve*10),0,0) ); }
else if( currSugarReserve > 100 )
//Color.green - gets darker with increasing sugar reserve
{ g.setColor( new Color(0,
255-( currSugarReserve>200?200:currSugarReserve ),0) ); }
else
//Color.orange changes to yellow as sugar reserve increases
{ g.setColor( new Color(254,155+currSugarReserve,0) );}
/**Determine shape of citizen object**/
// if HIGH vision & HIGH metabolism draw filled CIRCLE
if( (currVision >= (0.5 * GoLconst.VISION_MAX)) &&
(currMetabolism >= (0.5 * GoLconst.METABOLISM_MAX)) )
{ g.fillOval( x*cellSize, y*cellSize, cellSize-1, cellSize-1 ); }
// if LOW vision & HIGH metabolism draw filled RECTANGLE
else if( (currVision < (0.5 * GoLconst.VISION_MAX)) &&
(currMetabolism >= (0.5 * GoLconst.METABOLISM_MAX)) )
{ g.fillRect( x*cellSize, y*cellSize, cellSize-1, cellSize-1 ); }
// if HIGH vision & LOW metabolism draw filled PLUS sign
else if( (currVision >= (0.5 * GoLconst.VISION_MAX)) &&
(currMetabolism < (0.5 * GoLconst.METABOLISM_MAX)) )
{ g.fillRect( (x*cellSize)+(cellSize/3), y*cellSize, (cellSize-1)/3, cellSize-1 );
g.fillRect( x*cellSize, y*cellSize+(cellSize/3), cellSize-1, (cellSize-1)/3 );
}
// if LOW vision & LOW metabolism draw filled INVERTED ARC's
else if( (currVision < (0.5 * GoLconst.VISION_MAX)) &&
(currMetabolism < (0.5 * GoLconst.METABOLISM_MAX)) )
{ g.fillArc( x*cellSize, y*cellSize, cellSize, cellSize,30,120 );
g.fillArc( x*cellSize, y*cellSize, cellSize, cellSize,210,120 );
}
}
else //Empty Cell, Determine Color Based on Available Sugar
{ int currCellSugar = getCellSugar(x,y);
g.setColor( Color.lightGray );
if( currCellSugar >= GoLconst.SUGAR_MAX_CELL )
{ g.setColor( Color.darkGray ); }
else if( currCellSugar > 0 && currCellSugar < GoLconst.SUGAR_MAX_CELL )
{ colorVal = (int)( (( (double)currCellSugar / (double)GoLconst.SUGAR_MAX_CELL )
* 100) * 1.28 );
g.setColor( new Color( 192 - colorVal, 192 - colorVal, 192 - colorVal) ); }
//Fill Based on Determined Color
g.fillRect( x*cellSize, y*cellSize, cellSize-1, cellSize-1 );
//Write cell coordinates
if( GoLconst.GRID_COORD_SHOW )
{
if( GoLconst.GRID_COORD_DETAIL==0 ||
(GoLconst.GRID_COORD_DETAIL==1 && (x == cellCols-1 || y == cellRows-1)) ||
(GoLconst.GRID_COORD_DETAIL==2 && x == cellCols-1) ||
(GoLconst.GRID_COORD_DETAIL==3 && y == cellRows-1) ||
(GoLconst.GRID_COORD_DETAIL==4 && x == cellCols-1 && y == cellRows-1) )
{
if( GoLconst.GRID_COORD_COLOR == "blue" )
g.setColor( Color.blue);
else if( GoLconst.GRID_COORD_COLOR == "red" )
g.setColor( Color.red );
else if( GoLconst.GRID_COORD_COLOR == "green" )
g.setColor( Color.green );
else g.setColor( Color.black );
g.drawString(x+","+y, x*cellSize, (y+1)*cellSize-1);
}
}
}
}
}
}
//Clears Grid & Citizen List
public synchronized void clear() {
generations = 0;
population = 0;
for( int x=0; x<cellCols; x++ ) {
for( int y=0; y<cellRows; y++ ) {
cells[x][y] = false;
//If Sugarscape, Clear Citizen List as well
if( GoLconst.flagSugarscape )
{
citizen[x][y].setVision(0);
citizen[x][y].setMetabolism(0);
citizen[x][y].setSugar(0);
}
}
}
}
// create next generation of shape
public synchronized void next()
{ int x;
int y;
generations++;
// clear the buffer
for( x=0; x<cellCols; x++ )
for( y=0; y<cellRows; y++ )
{ cellsBuffer[x][y] = 0; }
// count neighbors of off-edge cells
for( x=1; x<cellCols-1; x++ )
for( y=1; y<cellRows-1; y++ )
if ( cells[x][y] )
{ cellsBuffer[x-1][y-1]++; cellsBuffer[x][y-1]++;
cellsBuffer[x+1][y-1]++; cellsBuffer[x-1][y]++;
cellsBuffer[x+1][y]++; cellsBuffer[x-1][y+1]++;
cellsBuffer[x][y+1]++; cellsBuffer[x+1][y+1]++;
}
// count neighbors of edge cells
x=1; // start at (1,0)
y=0;
int dx=1; int dy=0;
while( true )
{ if ( cells[x][y] )
{ if ( x > 0 )
{ if ( y > 0 ) { cellsBuffer[x-1][y-1]++; }
if ( y < cellRows-1 ) { cellsBuffer[x-1][y+1]++; }
cellsBuffer[x-1][y]++;
}
if ( x < cellCols-1 )
{ if ( y < cellRows-1 ) { cellsBuffer[x+1][y+1]++; }
if ( y > 0 ) { cellsBuffer[x+1][y-1]++; }
cellsBuffer[x+1][y]++;
}
if ( y > 0 ) { cellsBuffer[x][y-1]++; }
if ( y < cellRows-1 ) { cellsBuffer[x][y+1]++; }
}
// turn clockwise at collision with edge
if ( x==cellCols-1 && y==0 )
{ dx = 0; dy = 1; }
else if ( x==cellCols-1 && y==cellRows-1 )
{ dx = -1; dy = 0; }
else if ( x==0 && y==cellRows-1 )
{ dx = 0; dy = -1; }
else if ( x==0 && y==0 ) // all edge cells done
{ break; }
x += dx;
y += dy;
}
// here is the life algorithm
// simple, isn't it?
for( x=0; x<cellCols; x++ )
for( y=0; y<cellRows; y++ )
switch( cellsBuffer[x][y] )
{ case 2: // no change
break;
case 3:
cells[x][y] = true;
break;
default:
cells[x][y] = false;
break;
}
}
// draws shape in cells
// returns false if shape doesn't fit
public synchronized boolean drawShape( int shapeWidth, int shapeHeight, int shape[] )
{ int xOffset;
int yOffset;
if ( shapeWidth>cellCols || shapeHeight>cellRows )
return false; // shape doesn't fit on canvas
// center the shape
xOffset = (cellCols-shapeWidth)/2;
yOffset = (cellRows-shapeHeight)/2;
clear();
for ( int i=0; i < shape.length; i+=2 )
cells[xOffset+shape[i]][yOffset+shape[i+1]] = true;
return true;
}
public synchronized boolean drawRandomShape( )
{ clear();
for ( int i=0; i < cellCols; i++ )
for ( int j=0; j < cellRows; j++ )
if( ( (float)(Math.random()) ) < GoLconst.DENSITY_FACTOR)
cells[i][j] = true;
return true;
}
public synchronized String drawSugarscape( )
{
String dataStream = "";
int RANDOM = -1;
//initialize cells, population, generations & reseed Sugarscape
clear();
growCellSugar( SEED );
//initialize cells, population & generations
if( GoLconst.DEBUG_PROGRAM_FLOW )
{ bigDataStream += "drawSugarscape(" + ")\n"; }
if( GoLconst.DEBUG || GoLconst.DEBUG_CREATE_CITIZEN )
{ dataStream += "Randomly populating the grid...\n"; }
for(int i=0; i<cellCols; i++)
for(int j=0; j<cellRows; j++)
if( (float)(Math.random()) < GoLconst.DENSITY_FACTOR)
{ cells[i][j] = true;
citizen[i][j].vision = citizen[i][j].setVision(RANDOM);
citizen[i][j].metabolism = citizen[i][j].setMetabolism(RANDOM);
/*Initialize citizen sugar lvl & add curr cell sugar to it*/
citizen[i][j].sugar = citizen[i][j].setSugar(RANDOM) + this.getCellSugar(i,j);
setCellSugar(i,j); //initialize cell sugar to zero
population++;
if( GoLconst.DEBUG || GoLconst.DEBUG_CREATE_CITIZEN )
{ dataStream += showCitizenStats("Citizen", i,j); }
}
//no closing brace FOR j
//no closing brace FOR i
if( GoLconst.DEBUG || GoLconst.DEBUG_CREATE_CITIZEN )
{ dataStream += "Finished populating.., curr. population : " + population + "\n"; }
return dataStream;
}
// Create next generation for Sugarscape
public synchronized String nextScape(int detailLevel)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -