|
// save every alive cells so we can update only them and neighbours |
|
let aliveCells = [], |
|
time = 0; |
|
const rowInt = Math.floor((screen.height / 10) + 1), |
|
colInt = Math.floor((screen.width / 10) + 1), |
|
col = Array(rowInt).fill().map((x, i) => i), |
|
row = Array(colInt).fill().map((x, i) => i); |
|
|
|
/* cell component */ |
|
var GameCell = React.createClass({ |
|
getInitialState: function() { |
|
return { |
|
cellState: 'dead' |
|
}; |
|
}, |
|
handleClick: function(x, y) { // toggle between alive and dead |
|
let coord = x + "x" + y; |
|
if (this.state.cellState === 'dead') { |
|
this.setState({ |
|
cellState: 'alive' |
|
}); |
|
aliveCells.push(coord); |
|
} else { |
|
this.setState({ |
|
cellState: 'dead' |
|
}); |
|
let index = aliveCells.indexOf(coord); |
|
aliveCells.splice(index, 1); |
|
} |
|
}, |
|
render: function() { |
|
return ( |
|
<td onClick={this.handleClick.bind(this, this.props.k, this.props.i)} |
|
id={this.props.k+'x'+this.props.i} |
|
className={this.state.cellState}></td> |
|
); |
|
} |
|
}); |
|
|
|
/* random button */ |
|
var RandomButton = React.createClass({ |
|
randomClick: function() { |
|
let cells = $("td").get(); |
|
for (var i = 0; i < cells.length; i++) { |
|
let rand = Math.floor(Math.random() * 10); |
|
if (rand < 2) { |
|
/*$(cells[i]).removeClass("dead"); |
|
$(cells[i]).addClass("alive");*/ |
|
let cellId = $(cells[i]).attr("id"); |
|
document.getElementById(cellId).className = 'alive'; |
|
aliveCells.push(cellId); |
|
} |
|
} |
|
}, |
|
render: function() { |
|
return ( |
|
<i className="fa fa-random" onClick={this.randomClick} aria-hidden="true"></i> |
|
) |
|
} |
|
}); |
|
|
|
/* play button */ |
|
var Buttons = React.createClass({ |
|
getInitialState: function(){ |
|
return { |
|
time: 0, |
|
running: true |
|
} |
|
}, |
|
playClick: function() { |
|
if(this.state.running === true){ |
|
// if empty, random |
|
if(aliveCells.length === 0){ |
|
$(".fa-random").click(); |
|
} |
|
let neighboursArray = []; |
|
for (var j = 0; j < aliveCells.length; j++) { |
|
let coordsCell = aliveCells[j].split("x"); |
|
let y = Number(coordsCell[0]), |
|
x = Number(coordsCell[1]); |
|
|
|
neighboursArray.push( |
|
(x - 1) + "x" + (y - 1), (x - 1) + "x" + y, (x - 1) + "x" + (y + 1), |
|
x + "x" + (y - 1), x + "x" + y, x + "x" + (y + 1), |
|
(x + 1) + "x" + (y - 1), (x + 1) + "x" + y, (x + 1) + "x" + (y + 1)); |
|
} |
|
|
|
let uniquesArray = Array.from(new Set(neighboursArray)); |
|
let nextGenCells = [], |
|
nextDeadCells = []; |
|
// this is too slow |
|
for (var i = 0; i < uniquesArray.length; i++) { |
|
let neighbours = 0; |
|
let coords = uniquesArray[i].split("x"); |
|
let y = Number(coords[0]), |
|
x = Number(coords[1]); |
|
//top |
|
if ($("#" + (x - 1) + "x" + (y - 1)).hasClass("alive")) {neighbours++} |
|
if ($("#" + (x - 1) + "x" + (y)).hasClass("alive")) {neighbours++} |
|
if ($("#" + (x - 1) + "x" + (y + 1)).hasClass("alive")) {neighbours++} |
|
//middle |
|
if ($("#" + (x) + "x" + (y - 1)).hasClass("alive")) {neighbours++} |
|
if ($("#" + (x) + "x" + (y + 1)).hasClass("alive")) {neighbours++} |
|
//bottom |
|
if ($("#" + (x + 1) + "x" + (y - 1)).hasClass("alive")) {neighbours++} |
|
if ($("#" + (x + 1) + "x" + (y)).hasClass("alive")) {neighbours++} |
|
if ($("#" + (x + 1) + "x" + (y + 1)).hasClass("alive")) {neighbours++} |
|
// check each active cell and neighbours, array for dead && array for living |
|
if ((neighbours < 2 || neighbours > 3) && $("#" + x + "x" + y).hasClass("alive")) { |
|
let index = nextDeadCells.indexOf(x+"x"+y); |
|
if (index === -1) { |
|
nextDeadCells.push(x+"x"+y); |
|
} |
|
} |
|
else if ((neighbours == 3 && $("#" + x + "x" + y).hasClass("dead")) || |
|
(neighbours < 4 || neighbours > 1) && $("#" + x + "x" + y).hasClass("alive")) { |
|
let index = nextGenCells.indexOf(x+"x"+y); |
|
if (index === -1) { |
|
nextGenCells.push(x+"x"+y); |
|
} |
|
} |
|
} |
|
for(var a = 0;a < nextDeadCells.length; a++){ |
|
document.getElementById(nextDeadCells[a]).className = "dead"; |
|
} |
|
for(var b = 0; b < nextGenCells.length;b++){ |
|
document.getElementById(nextGenCells[b]).className = "alive"; |
|
} |
|
aliveCells = nextGenCells; |
|
time++; |
|
this.setState({time: time}) |
|
//setTimeout(this.playClick); |
|
requestAnimationFrame(this.playClick); |
|
}else{ |
|
this.setState({running: true}) |
|
$(".fa-start").click(); |
|
} |
|
}, |
|
pauseClick: function() { |
|
this.setState({running: false}) |
|
}, |
|
stopClick: function() { |
|
$(".fa-pause").click(); |
|
time = 0; |
|
this.setState({time: time}) |
|
for (var i = 0; i <= aliveCells.length; i++) { |
|
document.getElementById(aliveCells[i]).className = "dead"; |
|
} |
|
aliveCells = []; |
|
}, |
|
render: function() { |
|
return ( |
|
<div className="menu"> |
|
<i className="fa fa-play" onClick={this.playClick} aria-hidden="true"></i> |
|
<i className="fa fa-pause" onClick={this.pauseClick} aria-hidden="true"></i> |
|
<i className="fa fa-stop" onClick={this.stopClick} aria-hidden="true"></i> |
|
<RandomButton /> |
|
<p>Gen: {this.state.time}</p> |
|
</div> |
|
) |
|
} |
|
}); |
|
|
|
/* generate board */ |
|
var GenerateBoard = React.createClass({ |
|
render: function() { |
|
return ( |
|
<table> |
|
{col.map((i) => { |
|
return ( |
|
<tr key={i} id={i}>{ |
|
row.map((k) => { |
|
return <GameCell key={k} k={k} i={i} /> |
|
})} |
|
</tr> |
|
); |
|
})} |
|
</table> |
|
); |
|
} |
|
}); |
|
|
|
/* main component */ |
|
var LifeBoard = React.createClass({ |
|
render: function() { |
|
return ( |
|
<div className="board"> |
|
<Buttons /> |
|
<GenerateBoard /> |
|
</div> |
|
); |
|
} |
|
}); |
|
|
|
ReactDOM.render(<LifeBoard />, |
|
document.getElementById('app')); |