纯 reactJS:由于 float:left 网格构建与 2d 数组不对应,生命游戏规则显示错误
Pure reactJS: Game of Life rules are displayed wrong due to float:left grid building not corresponding with 2d Array
我正在和我在纯 reactJS 上构建的生活游戏一起旅行。我让用户触摸一个按钮来选择网格的大小,但问题是位置没有正确着色,因为它没有与跟踪单元格状态(活着或不活着)的数组同步。网格像普通数组一样呈现,然后使用 float:left 和取决于单元格大小的特定宽度显示为网格。
这是代码笔http://codepen.io/juanf03/pen/zKvzBY?editors=0011。您必须输入点,然后按一次开始(我停用了循环,因为它无法正常工作,所以它只会生成一次。这是代码:
class Header extends React.Component {
render(){
return ( <h1 className="title text-center">The Game Of Life</h1>);
}
}
class Cell extends React.Component {
toggleState(){
const i=this.props.row;
const j=this.props.column;
this.props.changeCellHandler(i,j);
}
render(){
var style="cell";
if(this.props.alive){
style+=" alive";
}
return ( <div className={style} id={this.props.id} onClick={this.toggleState.bind(this)}></div>);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {lifeStateMatrix:[],boardWidth:50,boardHeight:30,simulationIsRunning:false, generationNumber: 0};
this.timer;
}
componentWillMount(){
this.setBoardSizeAndStatusMatrix(70,50);
}
//add all the neighbours of a position to an Array to check later how many neighbours the position has
applyLifeRules(i,j){
const minX=0, minY=0,maxX=this.state.boardWidth,maxY=this.state.boardHeight;
let totalLiveNeighbours=0;
let currentStatusMatrix=this.state.lifeStateMatrix;
//check for limits
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
if(left){
if(currentStatusMatrix[i-1][j]){
totalLiveNeighbours+=1;
}
}
if(topLeft){
if(currentStatusMatrix[i-1][j+1]){
totalLiveNeighbours+=1;
}
}
if(topMiddle){
if(currentStatusMatrix[i][j+1]){
totalLiveNeighbours+=1;
}
}
if(topRight){
if(currentStatusMatrix[i+1][j+1]){
totalLiveNeighbours+=1;
}
}
if(right){
if(currentStatusMatrix[i+1][j]){
totalLiveNeighbours+=1;
}
}
if(bottomRight){
if(currentStatusMatrix[i+1][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomMiddle){
if(currentStatusMatrix[i][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomLeft){
if(currentStatusMatrix[i-1][j-1]){
totalLiveNeighbours+=1;
}
}
if(totalLiveNeighbours>0 && i==0 && j==0){
console.log('totalNeib',totalLiveNeighbours,"left",left,"topLeft",topLeft,"topMiddle",topMiddle,"topRight",topRight,"right",right,"bottomright",bottomRight,"bottomMiddle",bottomMiddle,"bottomLeft",bottomLeft);
}
if(i===1 && j===0){
console.log(totalLiveNeighbours);
}
if(currentStatusMatrix[i][j] && totalLiveNeighbours < 2){
//underpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && totalLiveNeighbours>3){
//overpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
}else if(!currentStatusMatrix[i][j] && totalLiveNeighbours===3){
//a new cell is born
return true;
}else{
return false
}
}
changeCell(i,j){
//put the cell as alive and add the pairs that have the cell as the neighbour if the simulation is not running
let newArray=this.state.lifeStateMatrix;
newArray[i][j]= !this.state.lifeStateMatrix[i][j];
this.setState({ lifeStateMatrix: newArray});
}
moveToNextGeneration(){
let nextGenMatrix=[]
for(let i=0,maxX=this.state.boardWidth; i<maxX ;i++){
let nextGenRow=[];
for(let j=0,maxY=this.state.boardHeight; j<maxY;j++){
nextGenRow.push(this.applyLifeRules(i,j));
}
nextGenMatrix.push(nextGenRow);
}
const genNumber= this.state.generationNumber+1;
this.setState({ lifeStateMatrix: nextGenMatrix, generationNumber:genNumber});
/*if(this.state.simulationIsRunning){
this.moveToNextGeneration();
}else{
console.log("game stopped");
}*/
if(this.state.simulationIsRunning){
this.start();
}
}
setBoardSizeAndStatusMatrix(x,y){
let lifeStateMatrix=[];
for(let i=0,len=x;i<len;i++){
let rowStatus=[];
for(let j=0,len=y;j<len;j++){
rowStatus.push(false);
}
lifeStateMatrix.push(rowStatus);
}
this.setState({ lifeStateMatrix: lifeStateMatrix, boardWidth: x, boardHeight: y});
}
start(firstTime=false){
this.setState({ simulationIsRunning:true});
this.moveToNextGeneration();
/* const that=this;
if(firstTime){
console.log("hola");
that.setState({ simulationIsRunning:true},that.moveToNextGeneration);
}
if(this.state.simulationIsRunning){
this.timer=setInterval(function next() {
that.moveToNextGeneration();
}, 2000);
}else{
console.log("tiene que terminar");
clearTimeout(this.timer);
}*/
}
pause(){
console.log("pausa");
this.setState({ simulationIsRunning:false});
}
clear(x,y){
this.setState({simulationIsRunning:false,lifeStateMatrix: [], generationNumber: 0});
this.setBoardSizeAndStatusMatrix(x,y);
}
render(){
let generatedId=0, cellsRenderMatrix=[], x= this.state.boardWidth, y= this.state.boardHeight;
let clickableState;
for(let i=0,len=x;i<len;i++){
let rowRender=[];
for(let j=0,len=y;j<len;j++){
rowRender.push(<Cell id={generatedId}
changeCellHandler={this.changeCell.bind(this)} row={i} column={j}
alive={this.state.lifeStateMatrix[i][j]} height={x} />); generatedId++;
}
cellsRenderMatrix.push(rowRender);
}
return (
<div className="holder well">
<Header />
<div className="topButtons">
<button className="run btn gridPicker" onClick={this.start.bind(this,true)}>Run</button>
<button className="pause btn gridPicker" onClick={this.pause.bind(this)}>Pause</button>
<button className="clear btn gridPicker" onClick={this.clear.bind(this,x,y)}>Clear</button>
<span id="generation">Generation: {this.state.generationNumber}</span>
</div>
<div className="board" style={{width: (y*10)+"px"}}>
{cellsRenderMatrix}
</div>
<div className="bottomButtons">
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,50,30)}>50x30</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,70,50)}>70x50</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,100,80)}>100x80</button>
</div>
</div>);
}
}
ReactDOM.render(
<Board />,
document.getElementById('container')
);
我认为主要问题出在 applyLifeRules(i,j) 方法上,我在该方法中设置了规则以查看邻居是否还活着,根据我一直在做的一些日志记录,我认为问题出在这里:
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
我已经尝试了很多东西,但我没有看到解决方案。我确定问题一定出在用于循环的 i、j 索引和该矩阵的不正确网格表示上,但我不知道它到底是什么。有任何想法吗?。非常感谢!
我找到了解决方案。而不是
else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
it was else if(currentStatusMatrix[i][j] && totalLiveNeighbours>=2 && totalLiveNeighbours<=3){
return true;
最终代码为
class Header extends React.Component {
render(){
return ( <h1 className="title text-center">The Game Of Life</h1>);
}
}
class Cell extends React.Component {
toggleState(){
const i=this.props.row;
const j=this.props.column;
this.props.changeCellHandler(i,j);
}
render(){
var style="cell";
if(this.props.alive){
style+=" alive";
}
return ( <div className={style} id={this.props.id} onClick={this.toggleState.bind(this)}></div>);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {lifeStateMatrix:[],boardWidth:50,boardHeight:30,simulationIsRunning:false, generationNumber: 0};
this.timer;
}
componentWillMount(){
this.setBoardSizeAndStatusMatrix(70,50);
}
//add all the neighbours of a position to an Array to check later how many neighbours the position has
applyLifeRules(i,j){
const minX=0, minY=0,maxX=this.state.boardWidth,maxY=this.state.boardHeight;
let totalLiveNeighbours=0;
let currentStatusMatrix=this.state.lifeStateMatrix;
//check for limits
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
if(left){
if(currentStatusMatrix[i-1][j]){
totalLiveNeighbours+=1;
}
}
if(topLeft){
if(currentStatusMatrix[i-1][j+1]){
totalLiveNeighbours+=1;
}
}
if(topMiddle){
if(currentStatusMatrix[i][j+1]){
totalLiveNeighbours+=1;
}
}
if(topRight){
if(currentStatusMatrix[i+1][j+1]){
totalLiveNeighbours+=1;
}
}
if(right){
if(currentStatusMatrix[i+1][j]){
totalLiveNeighbours+=1;
}
}
if(bottomRight){
if(currentStatusMatrix[i+1][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomMiddle){
if(currentStatusMatrix[i][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomLeft){
if(currentStatusMatrix[i-1][j-1]){
totalLiveNeighbours+=1;
}
}
if(totalLiveNeighbours>0 && i==0 && j==0){
console.log('totalNeib',totalLiveNeighbours,"left",left,"topLeft",topLeft,"topMiddle",topMiddle,"topRight",topRight,"right",right,"bottomright",bottomRight,"bottomMiddle",bottomMiddle,"bottomLeft",bottomLeft);
}
if(i===1 && j===0){
console.log(totalLiveNeighbours);
}
if(currentStatusMatrix[i][j] && totalLiveNeighbours < 2){
//underpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && totalLiveNeighbours>3){
//overpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
}else if(!currentStatusMatrix[i][j] && totalLiveNeighbours===3){
//a new cell is born
return true;
}else{
return false
}
}
changeCell(i,j){
//put the cell as alive and add the pairs that have the cell as the neighbour if the simulation is not running
let newArray=this.state.lifeStateMatrix;
newArray[i][j]= !this.state.lifeStateMatrix[i][j];
this.setState({ lifeStateMatrix: newArray});
}
moveToNextGeneration(){
let nextGenMatrix=[]
for(let i=0,maxX=this.state.boardWidth; i<maxX ;i++){
let nextGenRow=[];
for(let j=0,maxY=this.state.boardHeight; j<maxY;j++){
nextGenRow.push(this.applyLifeRules(i,j));
}
nextGenMatrix.push(nextGenRow);
}
const genNumber= this.state.generationNumber+1;
this.setState({ lifeStateMatrix: nextGenMatrix, generationNumber:genNumber});
/*if(this.state.simulationIsRunning){
this.moveToNextGeneration();
}else{
console.log("game stopped");
}*/
if(this.state.simulationIsRunning){
this.start();
}
}
setBoardSizeAndStatusMatrix(x,y){
let lifeStateMatrix=[];
for(let i=0,len=x;i<len;i++){
let rowStatus=[];
for(let j=0,len=y;j<len;j++){
rowStatus.push(false);
}
lifeStateMatrix.push(rowStatus);
}
this.setState({ lifeStateMatrix: lifeStateMatrix, boardWidth: x, boardHeight: y});
}
start(firstTime=false){
this.setState({ simulationIsRunning:true});
this.moveToNextGeneration();
/* const that=this;
if(firstTime){
console.log("hola");
that.setState({ simulationIsRunning:true},that.moveToNextGeneration);
}
if(this.state.simulationIsRunning){
this.timer=setInterval(function next() {
that.moveToNextGeneration();
}, 2000);
}else{
console.log("tiene que terminar");
clearTimeout(this.timer);
}*/
}
pause(){
console.log("pausa");
this.setState({ simulationIsRunning:false});
}
clear(x,y){
this.setState({simulationIsRunning:false,lifeStateMatrix: [], generationNumber: 0});
this.setBoardSizeAndStatusMatrix(x,y);
}
render(){
let generatedId=0, cellsRenderMatrix=[], x= this.state.boardWidth, y= this.state.boardHeight;
let clickableState;
for(let i=0,len=x;i<len;i++){
let rowRender=[];
for(let j=0,len=y;j<len;j++){
rowRender.push(<Cell id={generatedId}
changeCellHandler={this.changeCell.bind(this)} row={i} column={j}
alive={this.state.lifeStateMatrix[i][j]} height={x} />); generatedId++;
}
cellsRenderMatrix.push(rowRender);
}
return (
<div className="holder well">
<Header />
<div className="topButtons">
<button className="run btn gridPicker" onClick={this.start.bind(this,true)}>Run</button>
<button className="pause btn gridPicker" onClick={this.pause.bind(this)}>Pause</button>
<button className="clear btn gridPicker" onClick={this.clear.bind(this,x,y)}>Clear</button>
<span id="generation">Generation: {this.state.generationNumber}</span>
</div>
<div className="board" style={{width: (y*10)+"px"}}>
{cellsRenderMatrix}
</div>
<div className="bottomButtons">
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,50,30)}>50x30</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,70,50)}>70x50</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,100,80)}>100x80</button>
</div>
</div>);
}
}
ReactDOM.render(
<Board />,
document.getElementById('container')
);
我正在和我在纯 reactJS 上构建的生活游戏一起旅行。我让用户触摸一个按钮来选择网格的大小,但问题是位置没有正确着色,因为它没有与跟踪单元格状态(活着或不活着)的数组同步。网格像普通数组一样呈现,然后使用 float:left 和取决于单元格大小的特定宽度显示为网格。
这是代码笔http://codepen.io/juanf03/pen/zKvzBY?editors=0011。您必须输入点,然后按一次开始(我停用了循环,因为它无法正常工作,所以它只会生成一次。这是代码:
class Header extends React.Component {
render(){
return ( <h1 className="title text-center">The Game Of Life</h1>);
}
}
class Cell extends React.Component {
toggleState(){
const i=this.props.row;
const j=this.props.column;
this.props.changeCellHandler(i,j);
}
render(){
var style="cell";
if(this.props.alive){
style+=" alive";
}
return ( <div className={style} id={this.props.id} onClick={this.toggleState.bind(this)}></div>);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {lifeStateMatrix:[],boardWidth:50,boardHeight:30,simulationIsRunning:false, generationNumber: 0};
this.timer;
}
componentWillMount(){
this.setBoardSizeAndStatusMatrix(70,50);
}
//add all the neighbours of a position to an Array to check later how many neighbours the position has
applyLifeRules(i,j){
const minX=0, minY=0,maxX=this.state.boardWidth,maxY=this.state.boardHeight;
let totalLiveNeighbours=0;
let currentStatusMatrix=this.state.lifeStateMatrix;
//check for limits
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
if(left){
if(currentStatusMatrix[i-1][j]){
totalLiveNeighbours+=1;
}
}
if(topLeft){
if(currentStatusMatrix[i-1][j+1]){
totalLiveNeighbours+=1;
}
}
if(topMiddle){
if(currentStatusMatrix[i][j+1]){
totalLiveNeighbours+=1;
}
}
if(topRight){
if(currentStatusMatrix[i+1][j+1]){
totalLiveNeighbours+=1;
}
}
if(right){
if(currentStatusMatrix[i+1][j]){
totalLiveNeighbours+=1;
}
}
if(bottomRight){
if(currentStatusMatrix[i+1][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomMiddle){
if(currentStatusMatrix[i][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomLeft){
if(currentStatusMatrix[i-1][j-1]){
totalLiveNeighbours+=1;
}
}
if(totalLiveNeighbours>0 && i==0 && j==0){
console.log('totalNeib',totalLiveNeighbours,"left",left,"topLeft",topLeft,"topMiddle",topMiddle,"topRight",topRight,"right",right,"bottomright",bottomRight,"bottomMiddle",bottomMiddle,"bottomLeft",bottomLeft);
}
if(i===1 && j===0){
console.log(totalLiveNeighbours);
}
if(currentStatusMatrix[i][j] && totalLiveNeighbours < 2){
//underpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && totalLiveNeighbours>3){
//overpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
}else if(!currentStatusMatrix[i][j] && totalLiveNeighbours===3){
//a new cell is born
return true;
}else{
return false
}
}
changeCell(i,j){
//put the cell as alive and add the pairs that have the cell as the neighbour if the simulation is not running
let newArray=this.state.lifeStateMatrix;
newArray[i][j]= !this.state.lifeStateMatrix[i][j];
this.setState({ lifeStateMatrix: newArray});
}
moveToNextGeneration(){
let nextGenMatrix=[]
for(let i=0,maxX=this.state.boardWidth; i<maxX ;i++){
let nextGenRow=[];
for(let j=0,maxY=this.state.boardHeight; j<maxY;j++){
nextGenRow.push(this.applyLifeRules(i,j));
}
nextGenMatrix.push(nextGenRow);
}
const genNumber= this.state.generationNumber+1;
this.setState({ lifeStateMatrix: nextGenMatrix, generationNumber:genNumber});
/*if(this.state.simulationIsRunning){
this.moveToNextGeneration();
}else{
console.log("game stopped");
}*/
if(this.state.simulationIsRunning){
this.start();
}
}
setBoardSizeAndStatusMatrix(x,y){
let lifeStateMatrix=[];
for(let i=0,len=x;i<len;i++){
let rowStatus=[];
for(let j=0,len=y;j<len;j++){
rowStatus.push(false);
}
lifeStateMatrix.push(rowStatus);
}
this.setState({ lifeStateMatrix: lifeStateMatrix, boardWidth: x, boardHeight: y});
}
start(firstTime=false){
this.setState({ simulationIsRunning:true});
this.moveToNextGeneration();
/* const that=this;
if(firstTime){
console.log("hola");
that.setState({ simulationIsRunning:true},that.moveToNextGeneration);
}
if(this.state.simulationIsRunning){
this.timer=setInterval(function next() {
that.moveToNextGeneration();
}, 2000);
}else{
console.log("tiene que terminar");
clearTimeout(this.timer);
}*/
}
pause(){
console.log("pausa");
this.setState({ simulationIsRunning:false});
}
clear(x,y){
this.setState({simulationIsRunning:false,lifeStateMatrix: [], generationNumber: 0});
this.setBoardSizeAndStatusMatrix(x,y);
}
render(){
let generatedId=0, cellsRenderMatrix=[], x= this.state.boardWidth, y= this.state.boardHeight;
let clickableState;
for(let i=0,len=x;i<len;i++){
let rowRender=[];
for(let j=0,len=y;j<len;j++){
rowRender.push(<Cell id={generatedId}
changeCellHandler={this.changeCell.bind(this)} row={i} column={j}
alive={this.state.lifeStateMatrix[i][j]} height={x} />); generatedId++;
}
cellsRenderMatrix.push(rowRender);
}
return (
<div className="holder well">
<Header />
<div className="topButtons">
<button className="run btn gridPicker" onClick={this.start.bind(this,true)}>Run</button>
<button className="pause btn gridPicker" onClick={this.pause.bind(this)}>Pause</button>
<button className="clear btn gridPicker" onClick={this.clear.bind(this,x,y)}>Clear</button>
<span id="generation">Generation: {this.state.generationNumber}</span>
</div>
<div className="board" style={{width: (y*10)+"px"}}>
{cellsRenderMatrix}
</div>
<div className="bottomButtons">
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,50,30)}>50x30</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,70,50)}>70x50</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,100,80)}>100x80</button>
</div>
</div>);
}
}
ReactDOM.render(
<Board />,
document.getElementById('container')
);
我认为主要问题出在 applyLifeRules(i,j) 方法上,我在该方法中设置了规则以查看邻居是否还活着,根据我一直在做的一些日志记录,我认为问题出在这里:
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
我已经尝试了很多东西,但我没有看到解决方案。我确定问题一定出在用于循环的 i、j 索引和该矩阵的不正确网格表示上,但我不知道它到底是什么。有任何想法吗?。非常感谢!
我找到了解决方案。而不是
else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
it was else if(currentStatusMatrix[i][j] && totalLiveNeighbours>=2 && totalLiveNeighbours<=3){
return true;
最终代码为
class Header extends React.Component {
render(){
return ( <h1 className="title text-center">The Game Of Life</h1>);
}
}
class Cell extends React.Component {
toggleState(){
const i=this.props.row;
const j=this.props.column;
this.props.changeCellHandler(i,j);
}
render(){
var style="cell";
if(this.props.alive){
style+=" alive";
}
return ( <div className={style} id={this.props.id} onClick={this.toggleState.bind(this)}></div>);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {lifeStateMatrix:[],boardWidth:50,boardHeight:30,simulationIsRunning:false, generationNumber: 0};
this.timer;
}
componentWillMount(){
this.setBoardSizeAndStatusMatrix(70,50);
}
//add all the neighbours of a position to an Array to check later how many neighbours the position has
applyLifeRules(i,j){
const minX=0, minY=0,maxX=this.state.boardWidth,maxY=this.state.boardHeight;
let totalLiveNeighbours=0;
let currentStatusMatrix=this.state.lifeStateMatrix;
//check for limits
const left= i-1>=minX;
const topLeft= i-1 >=minX && j+1<maxY;
const topMiddle= j+1<maxY;
const topRight= i+1<maxX && j+1<maxY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j-1>=minY;
const bottomMiddle= j-1>=minY;
const bottomLeft= i-1>=minX && j-1>=minY;
if(left){
if(currentStatusMatrix[i-1][j]){
totalLiveNeighbours+=1;
}
}
if(topLeft){
if(currentStatusMatrix[i-1][j+1]){
totalLiveNeighbours+=1;
}
}
if(topMiddle){
if(currentStatusMatrix[i][j+1]){
totalLiveNeighbours+=1;
}
}
if(topRight){
if(currentStatusMatrix[i+1][j+1]){
totalLiveNeighbours+=1;
}
}
if(right){
if(currentStatusMatrix[i+1][j]){
totalLiveNeighbours+=1;
}
}
if(bottomRight){
if(currentStatusMatrix[i+1][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomMiddle){
if(currentStatusMatrix[i][j-1]){
totalLiveNeighbours+=1;
}
}
if(bottomLeft){
if(currentStatusMatrix[i-1][j-1]){
totalLiveNeighbours+=1;
}
}
if(totalLiveNeighbours>0 && i==0 && j==0){
console.log('totalNeib',totalLiveNeighbours,"left",left,"topLeft",topLeft,"topMiddle",topMiddle,"topRight",topRight,"right",right,"bottomright",bottomRight,"bottomMiddle",bottomMiddle,"bottomLeft",bottomLeft);
}
if(i===1 && j===0){
console.log(totalLiveNeighbours);
}
if(currentStatusMatrix[i][j] && totalLiveNeighbours < 2){
//underpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && totalLiveNeighbours>3){
//overpopulation. cell dies
return false;
}else if(currentStatusMatrix[i][j] && currentStatusMatrix[i][j]>=2 && currentStatusMatrix[i][j]<=3){
return true;
}else if(!currentStatusMatrix[i][j] && totalLiveNeighbours===3){
//a new cell is born
return true;
}else{
return false
}
}
changeCell(i,j){
//put the cell as alive and add the pairs that have the cell as the neighbour if the simulation is not running
let newArray=this.state.lifeStateMatrix;
newArray[i][j]= !this.state.lifeStateMatrix[i][j];
this.setState({ lifeStateMatrix: newArray});
}
moveToNextGeneration(){
let nextGenMatrix=[]
for(let i=0,maxX=this.state.boardWidth; i<maxX ;i++){
let nextGenRow=[];
for(let j=0,maxY=this.state.boardHeight; j<maxY;j++){
nextGenRow.push(this.applyLifeRules(i,j));
}
nextGenMatrix.push(nextGenRow);
}
const genNumber= this.state.generationNumber+1;
this.setState({ lifeStateMatrix: nextGenMatrix, generationNumber:genNumber});
/*if(this.state.simulationIsRunning){
this.moveToNextGeneration();
}else{
console.log("game stopped");
}*/
if(this.state.simulationIsRunning){
this.start();
}
}
setBoardSizeAndStatusMatrix(x,y){
let lifeStateMatrix=[];
for(let i=0,len=x;i<len;i++){
let rowStatus=[];
for(let j=0,len=y;j<len;j++){
rowStatus.push(false);
}
lifeStateMatrix.push(rowStatus);
}
this.setState({ lifeStateMatrix: lifeStateMatrix, boardWidth: x, boardHeight: y});
}
start(firstTime=false){
this.setState({ simulationIsRunning:true});
this.moveToNextGeneration();
/* const that=this;
if(firstTime){
console.log("hola");
that.setState({ simulationIsRunning:true},that.moveToNextGeneration);
}
if(this.state.simulationIsRunning){
this.timer=setInterval(function next() {
that.moveToNextGeneration();
}, 2000);
}else{
console.log("tiene que terminar");
clearTimeout(this.timer);
}*/
}
pause(){
console.log("pausa");
this.setState({ simulationIsRunning:false});
}
clear(x,y){
this.setState({simulationIsRunning:false,lifeStateMatrix: [], generationNumber: 0});
this.setBoardSizeAndStatusMatrix(x,y);
}
render(){
let generatedId=0, cellsRenderMatrix=[], x= this.state.boardWidth, y= this.state.boardHeight;
let clickableState;
for(let i=0,len=x;i<len;i++){
let rowRender=[];
for(let j=0,len=y;j<len;j++){
rowRender.push(<Cell id={generatedId}
changeCellHandler={this.changeCell.bind(this)} row={i} column={j}
alive={this.state.lifeStateMatrix[i][j]} height={x} />); generatedId++;
}
cellsRenderMatrix.push(rowRender);
}
return (
<div className="holder well">
<Header />
<div className="topButtons">
<button className="run btn gridPicker" onClick={this.start.bind(this,true)}>Run</button>
<button className="pause btn gridPicker" onClick={this.pause.bind(this)}>Pause</button>
<button className="clear btn gridPicker" onClick={this.clear.bind(this,x,y)}>Clear</button>
<span id="generation">Generation: {this.state.generationNumber}</span>
</div>
<div className="board" style={{width: (y*10)+"px"}}>
{cellsRenderMatrix}
</div>
<div className="bottomButtons">
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,50,30)}>50x30</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,70,50)}>70x50</button>
<button className="fiftyThirty btn gridPicker" onClick={this.setBoardSizeAndStatusMatrix.bind(this,100,80)}>100x80</button>
</div>
</div>);
}
}
ReactDOM.render(
<Board />,
document.getElementById('container')
);