I am trying to write the code to Conway's game of life but it just keeps dying out. I do not know what i should write so instead of making all the calculations as the code going forward it should just store what the code says and then make the changes. And to clarify i do not want my code to make one decision about one cell and the change it and then move on to the next cell but I want it to make a decision move on to the next cell and in the end of my code i want it to change all the cell att once.
This is the button to create the world:
private void btnSVActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
for (rad = 0; rad < 15; rad++){
for (kolumn = 0; kolumn < 15; kolumn++){
int x = 10 + 20 * kolumn;
int y = 10 + 20 * rad;
int diameter = 20;
int liv = (int) (Math.random()+0.5);
Cirkel cirkel = new Cirkel(x, y, diameter, liv);
cirklar.add(cirkel);
}
}
repaint();
}
This is a button to make the next generation:
private void btnNGActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
for (i=0; i<=225; i++){
rad=(i/15+1);
kolumn=(i%15+1);
if (rad==1 && kolumn==1) {
int levandeGrannarH1=cirklar.get(i+1).kollaLevande()
+cirklar.get(i+15).kollaLevande()
+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarH1!=2 && levandeGrannarH1!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH1==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==1 && kolumn==15 ) {
int levandeGrannarH2=cirklar.get(i-1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande();
if ((levandeGrannarH2!=2 && levandeGrannarH2!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH2==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn==1 ) {
int levandeGrannarH3=cirklar.get(i+1).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-15).kollaLevande();
if ((levandeGrannarH3!=2 && levandeGrannarH3!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH3==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn==15 ) {
int levandeGrannarH4=cirklar.get(i-1).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande();
if ((levandeGrannarH4!=2 && levandeGrannarH4!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarH4==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==1 && kolumn>1 && kolumn<15) {
int levandeGrannarR1=cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarR1!=2 && levandeGrannarR1!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR1==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn==15 && rad<15) {
int levandeGrannarR2=cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande()+cirklar.get(i-1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande();
if ((levandeGrannarR2!=2 && levandeGrannarR2!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR2==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad==15 && kolumn>1 && kolumn<15) {
int levandeGrannarR3=cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-16).kollaLevande();
if ((levandeGrannarR3!=2 && levandeGrannarR3!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR3==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn==1 && rad<15 ) {
int levandeGrannarR4=cirklar.get(i-15).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannarR4!=2 && levandeGrannarR4!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannarR4==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
if (rad>1 && kolumn>1 && rad<15 && kolumn<15) {
int levandeGrannar = cirklar.get(i-16).kollaLevande()+cirklar.get(i-15).kollaLevande()+cirklar.get(i-14).kollaLevande()+cirklar.get(i-1).kollaLevande()+cirklar.get(i+1).kollaLevande()+cirklar.get(i+14).kollaLevande()+cirklar.get(i+15).kollaLevande()+cirklar.get(i+16).kollaLevande();
if ((levandeGrannar!=2 && levandeGrannar!=4) && cirklar.get(i).kollaLevande()==1)
cirklar.get(i).gorDod();
else if ((levandeGrannar==3) && cirklar.get(i).kollaLevande()==0 )
cirklar.get(i).gorLevande();
}
repaint();
}
}
This is the explanation of how the cells should look like and if they are alive or not.
public class Cirkel {
private int x = 0;
private int y = 0;
private int diameter = 10;
private int liv = 1;
public Cirkel(int x, int y, int diameter, int liv){
this.x = x;
this.y = y;
this.diameter = diameter;
this.liv = liv;
}
public void rita(Graphics g){
if (this.liv==1)
g.setColor(Color.green);
else
g.setColor(Color.white);
g.fillOval(this.x, this.y, this.diameter, this.diameter);
}
public int kollaLevande(){
return this.liv;
}
public void gorLevande(){
this.liv=1;
}
public void gorDod(){
this.liv=0;
}
}
I would be grateful for any kind of help and if there is some problem whit my question please just ask and I will try to explain in an other way.
When you calculate your next generation, you appear to be trying to update the state of your current grid cells, in other words, you're setting the state of the cells in your cirklar ArrayList, while you're still using cirklar to calculate the state of the next generation of cells. But doing this before the entire grid has been checked will effect calculations of the grid cell neighbors down-stream. And in fact you already know that this is a problem, since you state:
And to clarify i do not want my code to make one decision about one cell and the change it and then move on to the next cell but I want it to make a decision move on to the next cell and in the end of my code i want it to change all the cell att once.
To fix this, you need to create a new grid, and then when doing your calculations, set the state of the new grid cells as dead or alive. Then when you've completed your iteration through the entire grid, swap the new grid in for the old grid.
Also note that you have a lot of unneeded redundancy in your code, and I think that you're doing this in order to handle the edges of the grid. This can be cleaned up greatly and greatly simplified by thinking through your coding a bit. Do something like:
// pseudo-code:
SomeArray newGrid = new SomeArray....
for (int currentRow = 0; currentRow <= NUMBER_OF_ROWS; currentRow++) {
for (int currentCol = 0; currentCol <= NUMBER_OF_COLS; currentCol++) {
int minumumRow = Math.max(currentRow - 1, 0); // *** check for edge!!!
int maximumRow = Math.min(currentRow + 1, NUMBER_OF_ROWS); // *** check for edge!!!
int minumumCol = Math.max(currentCol - 1, 0); // *** check for edge!!!
int maximumCol = Math.MIN(currentCol + 1, NUMBER_OF_COLS); // *** check for edge!!!
int neighborCount = 0;
for (row = minumumRow; row <= maximumRow; row++) {
for (col = minumumCol; col <= maximumCol; col++) {
if (row != currentRow || col != currentCol) {
// check if neighbors alive and increment neighborCount
}
}
}
// use neighbor count to set the state of the grid cell in a **new** grid
// silly pseudo-code:
newGrid.getCell(currentRow, currentCol).setState(....)
}
}
// now you've checked all the grid and set the new grid states.
// Time to swap grids
currentGrid = newGrid;
Related
I'm coding Conway's Game of Life on Processing 3 and I want to store x and y so that the squares don't change right away, but I don't know how to store it to use later. Any help is appreciated!
void keyPressed() {
for (int x = 0; x < 30; x++) {
for (int y = 0; y < 30; y++) {
int numNeighbours = numNeighbours(x,y);
if (cells[x][y] == true) {
if (numNeighbours > 3 || numNeighbours <= 1) { //underpopulation or overpopulation
}
}
else if (cells[x][y] == false) {
if (numNeighbours == 3) {
}
}
}
}
}
Based on my understanding of your code (and the Game of Life), you don't need to store x and y. What you actually need to do is to store the (x, y) pairs where the cell changes state.
You could do this by creating pairs and adding them to lists.
But a another idea is to use a second array representing the next generation of the game and put all of the new values there; e.g.
for (int x = 0; x < 30; x++) {
for (int y = 0; y < 30; y++) {
int numNeighbours = numNeighbours(x,y);
if (cells[x][y] == true) {
if (numNeighbours > 3 || numNeighbours <= 1) {
cellsNext[x][y] = false;
} else {
cellsNext[x][y] = true;
}
}
else if (cells[x][y] == false) {
if (numNeighbours == 3) {
cellsNext[x][y] = true;
} else {
cellsNext[x][y] = false;
}
}
}
}
Note: that could be simplified / written better, but I have written it as above so that you can see clearly what I have done.
Currently I'm trying to implement heuristics for a 3D tic-tac-toe but it seems like my counter is way of it,f but I'm unsure where I've done wrong, I'm not gonna post all of the code since it's a lot, but here is a part:
public void countDiagonal(GameState gameState) {
/*
* yz-plane (negativ)
*/
int z;
for (int x = 0; x < GameState.BOARD_SIZE; x++) {
for (int y = 0; y < GameState.BOARD_SIZE; y++) {
z = y;
if (gameState.at(x, y, z) == myPlayer) {
myCounter++;
opponentCounter = 0;
}
if (gameState.at(x, y, z) == opponentPlayer) {
opponentCounter++;
myCounter = 0;
}
if (gameState.at(x, y, z) == Constants.CELL_EMPTY) {
emptyCells++;
}
}
evaluateBoard();
myCounter = 0;
opponentCounter = 0;
emptyCells = 0;
}
The evaluation is done here:
public void evaluateBoard() {
if (myCounter == 1 && emptyCells == 3) {
myScore = myScore + 5;
}
if (myCounter == 2 && emptyCells == 2) {
myScore = myScore + 10;
}
if (myCounter == 3 && emptyCells == 1) {
myScore = myScore + 20;
}
if (myCounter == 4) {
myScore = myScore + 1000;
}
if (opponentCounter == 1 && emptyCells == 3) {
opponentScore = opponentScore + 5;
}
if (opponentCounter == 2 && emptyCells == 2) {
opponentScore = opponentScore + 10;
}
if (opponentCounter == 3 && emptyCells == 1) {
opponentScore = opponentScore + 20;
}
if (opponentCounter == 4) {
opponentScore = opponentScore + 1000;
}
}
When I try to run it, I use alpha-beta prune, but it seems like the calculation are done horrbly wrong, when I use the value, I take myScore - opponentScore and I use an alpha-beta tree with depth 1, but even after only playing one move, I'm down -15 in points, as I'm a noob in java, im therefore asking for help, is there an obvious mistake in my way of trying to evaluate the board?
trying to create a Conways Game of life, but apparently the shapes are not like they have to be. Perhaps someone can help me find the issue.
For example the glider :
- X - - - -
- - X X - -
- X X - - -
- - - - - -
becomes this
- - X X - -
- X - - - -
X X X - - -
- X X X - -
but should be like this :
- - X - - -
- - - X - -
- X X X - -
- - - - - -
And my code looks like this
public Frame(int x, int y) {
setWidth(x);
setHeight(y);
if (x<1)
frame = null;
else if (y<1)
frame = null;
else {
frame = new String [x][y];
for (int i=0; i<frame.length; i++) {
for (int j=0; j<frame[i].length; j++) {
frame [i][j] = DEAD;
}
}
} // else
} // construktor
public Integer getNeighbourCount(int x, int y) {
Frame cell = new Frame(getHeight(), getWidth());
int counter = 0;
if(frame[x][y].equals(ALIVE))
{
counter = counter - 1;
}
for(int i=x-1; i<=x+1;i++){
if(i<frame.length && i>0){
for(int j=y-1; j<=y+1;j++){
if(j<frame[i].length && j>0){
if (frame[i][j]==ALIVE) {
counter++;
}
}
}
}
}
return counter;
}
public Frame nextFrame() {
// Returns next frame
Frame cell = new Frame(getWidth(), getHeight());
//cell.frame = new String[getWidth()][getHeight()];
for(int i = 0; i < frame.length; i++){
for(int j =0; j <frame[i].length;j++){
int n = getNeighbourCount(i,j);
if(cell.frame[i][j]==null) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n < 2 || n > 3) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n == 3 || n == 2){
cell.frame[i][j] = ALIVE;
}
if(!isAlive(i, j) && n == 3) {
cell.frame[i][j] = ALIVE;
}
if(isAlive(i, j) && n > 3){
cell.frame[i][j] = DEAD;
}
frame[i][j] = cell.frame[i][j];
}
}
cell.toString();
return cell;
}
`
Full code http://pastebin.com/LMwz724H
Here's a solution that works - using an enum for each cell and getting the i/j and x/y stuff right (I think). It certainly generates the correct first iteration:
static class GameOfLife {
final int w;
final int h;
State[][] frame;
enum State {
Dead, Alive;
}
public GameOfLife(int w, int h) {
this.w = w;
this.h = h;
frame = new State[h][w];
}
public void alive(int x, int y) {
frame[y][x] = State.Alive;
}
public void tick() {
frame = nextGeneration();
}
private int surroundingPopulation(int x, int y) {
int pop = 0;
for (int i = y - 1; i <= y + 1; i++) {
for (int j = x - 1; j <= x + 1; j++) {
// On frame - vertically.
if ((i >= 0 && i < h)
// On frame horizontally.
&& (j >= 0 && j < w)
// Alive
&& (frame[i][j] == State.Alive)
// Not the center.
&& (i != y || j != x)) {
pop += 1;
}
}
}
return pop;
}
private State[][] nextGeneration() {
State[][] next = new State[h][w];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pop = surroundingPopulation(x, y);
// Any live cell
if (frame[y][x] == State.Alive) {
if (pop < 2) {
// ... with fewer than two live neighbours dies, as if caused by under-population.
next[y][x] = State.Dead;
} else if (pop > 3) {
// ... with more than three live neighbours dies, as if by overcrowding.
next[y][x] = State.Dead;
} else {
// ... with two or three live neighbours lives on to the next generation.
next[y][x] = State.Alive;
}
} else {
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (pop == 3) {
next[y][x] = State.Alive;
}
}
}
}
return next;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
for (State[] row : frame) {
for (State c : row) {
s.append(c == State.Alive ? "X" : " ");
}
s.append("\r\n");
}
return s.toString();
}
}
public void test() {
GameOfLife g = new GameOfLife(6, 6);
g.alive(1, 0);
g.alive(2, 1);
g.alive(3, 1);
g.alive(1, 2);
g.alive(2, 2);
System.out.println("Before:\r\n" + g);
g.tick();
System.out.println("After:\r\n" + g);
}
I believe the problem is that you are copying the new value as you iterate through the loop. This means neighbours are using the value from the next tick rather than the current one.
You can fix this by waiting until you calculated all new values in your new frame: cell.frame and then iterate through the frame again and copy from cell.frame to frame.
An alternative (better in my view) is to have away of cloning a frame during construction. Then you could change your nextFrame method to create a clone of frame and use the clone to set the new values in frame.
You are changing the DEAD and ALIVE frames while you iterate through the grid. You need to store the coordinates which should die or become alive and perform that afterwards.
Store the coordinates in two ArrayLists (dead, alive). The first and second position is the x and y axis, and change those coordinates according to whether they should become alive or not.
Here's a snippet from a simple test I wrote a while back. As others have mentioned, don't change values on an active board while still reading them. Instead, clone the board and make changes to the copy while reading the current board.
Another problem I bumped into a few times was iterating over y, then x for each y, but referring to x,y when accessing a point. It feels back to front :)
// Rules:
// 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
// 2) Any live cell with two or three live neighbours lives on to the next generation.
// 3) Any live cell with more than three live neighbours dies, as if by overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
void mutateGrid() {
// Copy existing grid into the next generation's grid
boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight];
for (int i = 0; i < gridXWidth; i++) {
System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight);
}
// Start mutation rules
for (int y = 0; y < gridYHeight; y++) {
for (int x = 0; x < gridXWidth; x++) {
int liveNeighbours = countLiveNeighbours(x,y);
if (liveNeighbours < 2 || liveNeighbours > 3) {
mutatedGrid[x][y] = false;
}
else if (liveNeighbours == 3) {
mutatedGrid[x][y] = true;
}
}
}
grid = mutatedGrid;
}
int countLiveNeighbours(int x, int y) {
int count = 0;
for (int j = y-1; j <= y+1; j++) {
for (int i = x-1; i <= x+1; i++) {
if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){
continue;
}
if (grid[i][j]) {
count++;
}
}
}
count -= grid[x][y]?1:0; // remove self from count
return count;
}
In my program you can place pictures on the applet if you have the required minerals
you start with 400 and each one is 100 minerals so you place 3 and then on the 4th it will delete all the others
public int Minerals
//Pylons
int xCoord[];
int yCoord[];
int numSquare;
boolean firstPaint;
public void init()
{
Minerals = 400;
pylon = getImage(getDocumentBase(),"image/pylon.png");
//pylons
xCoord = new int[100];
yCoord = new int[100];
numSquare = 0;
firstPaint = true;
}
public void paint(Grapics g)
{
pylons(g);
}
public void pylons(Graphics g)
{
//Building the pylons
if(Minerals >= 100)
{
for (int k = 0; k < numSquare; k++)
{
g.drawImage(pylon,xCoord[k],yCoord[k],85,85,this);
//Makes cursor normal.
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
//Checks if buildPylon is 1 if so it will draw the infoScreen and then set the cursor to pylon
if(buildPylon == 1)
{
g.drawImage(pylon,510,820,100,100,this);
//Use the custom cursor
setCursor(cursor);
}
}
private void handlePylonPlacement()
{
//This takes away 100 minerals and will add 9 population and make buildPylon 0 again
if(decrementMinerals(100))
addPopMax(9);
buildPylon = 0;
}
private boolean decrementMinerals(int amount)
{
//This Is where it takes away the minerals
if(Minerals - amount >= 0) // prevent situation where you go into negative minerals
{
Minerals -= amount;
return true;
}
else
return false;
}
private void addPopMax(int amount)
{
//Add the population (9)
if(popMax + amount <= 72) // restrict addition to pop-max to a sane upper bound
popMax += amount;
}
public boolean mouseDown(Event e, int x, int y) {
//Makes the ints xCoord2 to equal x and same for the other
xCoord2 = x;
yCoord2 = y;
repaint();
if (numClicks == 10) {//Title screen
numClicks++;
repaint();
}
//Checks to see if buildPylon == 1 then builds the pylon if its in the correct place.
if(buildPylon == 1)
{
if(x > 1 && x < 1275 && y > 711 && y < 948) // Checks to see if the person clicked in this area
{}
else if(x > 378 && x < 876 && y < 568 && y < 705) // Checks to see if the person clicked in this area
{}else if (Minerals >= 100)
{
xCoord[numSquare] = x;
yCoord[numSquare] = y;
numSquare++;
handlePylonPlacement(); // call your new handler
repaint();
}
}
return true;
}
Instead of it deleting them i want the pylons to stay painted on the screen... any help?
In handlePylonPlacement(), did you mean
private void handlePylonPlacement()
{
//This takes away 100 minerals and will add 9 population and make buildPylon 0 again
if (decrementMinerals(100)) {
addPopMax(9);
buildPylon = 0;
}
}
?
My board correctly detects groups with less than 3 neighbors and kills them off, but doesn't seem to detect and give birth to cells with 3 neighbors.
Any thoughts?
If I haven't provided enough information let me know, and I can paste more of the code, but I think this is all of the relevant parts.
Thank you in advance for any advice offered.
public boolean getCell(int row, int col) {
boolean state = board[row][col];
int neighbors = 0;
for (int x = row-1; x <= row+1; x++) {
for (int y = col-1; y <= col+1; y++) {
// don't include this
if ((x != row || y != col) && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {
if (board[x][y] == ALIVE){
neighbors ++;
}
}
}
}
if (neighbors > 3 || neighbors < 2)
state = DEAD;
else if(neighbors == 3)
state = ALIVE;
return state;
}
Here is the lifeCycle method requested.
/** Process one life cycle of the cellular automaton
*
*/
public void lifeCycle() {
for (int x = 0; x < NROWSCOLS ; x++) {
for (int y = 0; y < NROWSCOLS; y++) {
getCell(x,y);
}
}
generations ++;
}
I've attached the LifeGUI for reference, but this code is provided and not intended for me to change.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LifeGUI extends JPanel {
// game instance variables
private Life board; // game board
// GUI components
private JLabel generationsLived;
private JButton resetButton, cycleButton; // reset control and cycle control
private Cell[][] cells; // board cells for display
/** Construct new Life game with a graphical user interface */
public LifeGUI() {
// create and initialize game board and display representation
board = new Life();
cells = new Cell[Life.NROWSCOLS][Life.NROWSCOLS];
// set layout for game display
setLayout(new BorderLayout());
// Create board cells and add to display
JPanel boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(Life.NROWSCOLS, Life.NROWSCOLS));
for (int row = 0; row < Life.NROWSCOLS; row++) {
for (int col = 0; col < Life.NROWSCOLS; col++) {
cells[row][col] = new Cell(Life.DEAD, row, col);
boardPanel.add(cells[row][col]);
}
}
add(boardPanel, BorderLayout.CENTER);
// Set up 2 buttons
// a reset button so it starts a new game when clicked
// a cycle button to tell the Life automaton to live one cycle
resetButton = new JButton("New Game");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
board.newGame();
updateDisplay();
}
});
cycleButton = new JButton("Live One Cycle");
cycleButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
board.lifeCycle();
updateDisplay();
}
});
// Put the buttons and the generation count display on the screen
JPanel buttonPanel = new JPanel();
buttonPanel.add(resetButton);
buttonPanel.add(cycleButton);
generationsLived = new JLabel(" Generations Lived: " , JLabel.RIGHT);
buttonPanel.add(generationsLived);
add(buttonPanel, BorderLayout.SOUTH);
// show initial display
updateDisplay();
}
/** Update display to match game state. */
public void updateDisplay() {
// update count display
generationsLived.setText(" Generations Lived: " + board.getGenerationCount());
// update board display
for (int row = 0; row < Life.NROWSCOLS; row++) {
for (int col = 0; col < Life.NROWSCOLS; col++) {
cells[row][col].setState(board.getCell(row,col));
}
}
repaint();
}
/** Create new game and a window to display it */
private static void test() {
JFrame f = new JFrame("The Game of Life"); // top-level window
LifeGUI l = new LifeGUI();
f.getContentPane().add(l);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600,600);
f.validate();
f.setVisible(true);
f.toFront();
}
public static void main(String[] args) {
// To support stand-alone application
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
LifeGUI.test();
}
});
}
}
public boolean getCell(int row, int col) {
boolean state = board[row][col];
int neighbors = 0;//you are summing the alive neighbours
//keep var declaration outside the iteration over them
for (int x = Math.max(0,row-1); x < Math.min(row+2,NROWSCOLS); x++) {
for (int y = Math.max(0,col-1); y < Math.min(col+2,NROWSCOLS); y++) {
//using min and max to ensure x and y remain between 0 and NROWSCOLS
//so no IOBException
if (board[x][y] == ALIVE){
neighbors ++;
}
}
}
}
if (neighbors > 3 || neighbors < 2)//only do the check when you are finished counting the alive neighbours
state = DEAD;
else if(neighbors == 3)
state = ALIVE;
return state;
}
check your loop is not correct.
for (int x = row-1; x <= row; x++)
it will always go to board[row] index. which is out of bound . same thing for other loop
Please check this
at Life.getCell(Life.java:63)
The problem is in the line 63 of Life.java
I don't know if the problem is there but check this line:
if (x != row || y != col && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {
because is not doing what you think it's doing beacuse of the operator precedence,
please, add some parentheses.
Like this
if ((x != row || y != col) && x != -1 && y != -1
&& x != NROWSCOLS && y != NROWSCOLS) {
The || will not work as intended without adding perenthisis.
Current code will do this:
if (x != row || (y != col && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS))
You prob want this
if ((x != row || y != col) && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS)
or this
if (x != row && y != col && x != -1 && y != -1 && x != NROWSCOLS && y != NROWSCOLS)