I am trying to implement The Game Of Life using React, and it works...mostly. My implementation includes a start
button that triggers the game and must keep cycling until the users push the button stop
.
I say that it works...mostly because I can see that the matrix is developing as expected, but I am unable to cycle the process with a while
clause. When I remove such a clause, the game performs a cycle every time the user pushes start
, but I want the game to perform cycles continually.
This is the code:
import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Grid from './Grid';
class Matrix extends React.Component {
constructor (props) {
super(props);
this.state = {
cycle: 0,
rows: 120,
columns: 260,
livingBase: 0.01,
matrix: null,
killWith: 2,
setAliveWith: 4,
continue: true
};
}
getRandomMatrix = () => {
let randomMatrix=[]
let randomRow = [];
let randomNumber = null;
for (let i=0; i<this.state.columns; i++) {
randomRow = []
for (let j=0; j<this.state.rows; j++) {
randomNumber = Math.random();
randomRow.push(randomNumber < this.state.livingBase? true: false);
}
randomMatrix.push(randomRow);
}
this.setState({matrix: randomMatrix})
}
getNextMatrix = () => {
let newMatrix = this.state.matrix.slice();
const getCurrentCellLivingNeighbours = (n, m) => {
let currenCellLivingNeighburs = 0;
const getNeighbour = (l, k) => {
let tryCell = false;
try {
tryCell = this.state.matrix[l][k];
return tryCell
} catch {
return false
}
}
if (getNeighbour(n-1, m-1)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n-1, m)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n-1, m+1)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n, m-1)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n, m+1)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n+1, m-1)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n+1, m)) {
currenCellLivingNeighburs++;
}
if (getNeighbour(n+1, m+1)) {
currenCellLivingNeighburs++;
}
return currenCellLivingNeighburs;
}
for (let j=0; j<this.state.matrix.length; j++) {
for (let i=0; i<this.state.matrix[0].length; i++) {
let currentCell = this.state.matrix[j][i];
let livingNeigbours = getCurrentCellLivingNeighbours(j, i)
if (currentCell) {
if (livingNeigbours<2 || livingNeigbours>3) {
newMatrix[j][i] = false;
}
} else {
if (livingNeigbours === 3) {
newMatrix[j][i] = true;
}
}
}
}
this.setState({matrix: newMatrix})
}
handleResetClick = () => {
this.getRandomMatrix();
}
catchLivingBaseChange = (e) => {
this.setState({livingBase: parseInt(e.target.value)/100})
}
handleStartClick = () => {
while (this.state.continue) {
this.getNextMatrix();
}
}
render () {
return (
<div>
<AppBar position="static">
<Toolbar>
<div style={{display: 'flex'}}>
<div>
<Typography variant="h6" >
The Game Of Life
</Typography>
</div>
<div style={{paddingLeft: 15}}>
<TextField id="livingBase" label="Porcentaje de Inicio" defaultValue="1" onChange={this.catchLivingBaseChange.bind(this)} />
<Button color="black" variant='contained' onClick={this.handleResetClick.bind(this)} >Reset</Button>
<Button color="black" variant='contained' onClick={this.handleStartClick.bind(this)} >Start</Button>
</div>
</div>
</Toolbar>
</AppBar>
{this.state.matrix? <Grid matrix={this.state.matrix} />: <h1>Push reset to init matrix...</h1>}
</div>
)
}
}
export default Matrix;
Method handleStartClick()
is the one I want to cycle with a while
clause, but the screen never updates when such a clause is added.
you can maintain the loop like this.
setinterval( () => {
this.getNextMatrix();
}, 100); /// 100 or whatever value works for you. the value is in miliseconds