I am having an issue with advancing the iterations in my effort for the Game of Life project and hoping to get some help or suggestions. I am new to React, but familiar enough to have completed the 3 ReactJS projects prior to this.
I am going via the rules mentioned in the Wikipedia entry for GOL. I plan to stick to a pure ReactJS implementation all through, if possible.
Rough flow:
I have a <board>
component(or class) that holds the main logic. Inside this multiple nested <cell>
components are generated per some variables (well, i have it declared in the state for now but perhaps they will change).
In the <board>
component i have a ‘board’ state consisting of an array of length 400(or whatever number - this is a calculated value and is filled in from the componentDidMount
). The render
method iterates over this number and generates the necessary cells.
All cells are dead by default(‘x’) except a few that are alive(‘j’). These alive cells are the seed and come from a state declaration - an array consisting of numbers that point to an index in the board state array. The cells have props that trigger changes (including a shouldComponetMount
condition where i compare the previous and current states). It works fine. My board is generated and the dead/alive cells display as intended.
Functions for calculating the position of a cell (i.e is it an edge etc etc) and getting the ‘neighbours’ are in place. Standalone, they work fine (except a glitch for the bottom left corner cell - which i will be fixing later since it is not pertinent to my immediate problem. In fact the edge functions as a whole are not pertinent as well for the immediate problem on hand). Given a number(an index mostly since mostly they will be called inside a loop) the functions reliably return neighbour cells.
A Start
button in my <board>
component calls a function that consists the rules. A thought-flow follows:
- i create copies of the board and seed states
- i then have my wrapper setInterval that will run the rules
- Inside this setInterval, i begin a loop over the seed array(the ‘alive’ cells). I do it backward since i will be modifying the array in-place - removing entries if they are ‘dead’. For example for the seed array that consists of [48, 49, 50] - a blinker, the loop begins at 48, and checks if it needs to be alive/dead. If dead, the entry is removed from the array. I then loop over its neighbours (mostly 8 but it can vary depending on the position since i have a finite board - i will be displaying a shorter viewport however for a better user experience. No plans to mirror. Mostly i will be making the cells dead if they collide with an out-of-view edge) and run the same rule-set for each of them.
My loop runs through but all end up dead. Typically, i should have at least one alive cell on a single setTimeout/setIntreval iteration, going by the rules.
My first goal is a working blinker from a seed. I am not sure if my overall approach is right even though i do think it is definitely viable and the things that do work as of now do so without any problems.
Any help/suggestions here would be definitely welcome. Ideally, something that follows my thought flow(even if it seems not too optimal). Since i am quite new to ReactJS i thought ill follow through with my flow in order to avoid confusion when i try changing core approaches. But if a re-think is really required, i will go that path.
I have a JSfiddle link with a WIP code at https://jsfiddle.net/arunmenon/bL0qczbd/1/ so that the current code can be seen in entirety. Using JS Fiddle here instead of Code Pen since the latter is currently reserved for more complete/publishable code. The following function/snippet is where things start off:
startClicked(){
var boardCopy=this.state.board.slice();
var seedSlice = this.state.seed.slice();
this.interval = window.setInterval(function(){
//seedSlice.forEach(function(obj,ind){
for(var i=seedSlice.length;i>0;i--){
var obj = seedSlice[i-1];
this.neighbours = this.getNeighbours(obj);
let population = this.populationDynamics(obj);
if(population==="under"){
boardCopy[obj]="x";
console.log(obj, seedSlice);
seedSlice.splice(seedSlice.indexOf(obj),1);
console.log(obj, seedSlice);
}
else if(population==="over"){
boardCopy[obj]="x";
this.state.seed.splice(obj,1);
}
else if(population==="equable"){
boardCopy[obj]="j";
}
else /*if(population==="resurrect")*/{
boardCopy[obj]="j";
}
/* I will be using a second/nested loop here that goes through the neighbours (this.neighbours) here.
Finally i will set state.
Note:I will be optimizing the repetitive calls below by separating them to a function as well as have &&/|| where necessary.
This is just WIP */
for(var j=this.neighbours.length;j>0;j--){
let ob = this.neighbours[j-1];
let population = this.populationDynamics(ob);
if(population==="under"){
boardCopy[ob]="x";
}
else if(population==="over"){
boardCopy[ob]="x";
}
else if(population==="equable"){
boardCopy[ob]="j";
}
else /*if(population==="resurrect")*/{
boardCopy[ob]="j";
}
}
this.setState({
seed: seedSlice,
board: boardCopy
});
}
//}.bind(this),1000);
}.bind(this),1000);
};