Skip to content

Instantly share code, notes, and snippets.

@juanlet
Last active September 11, 2016 03:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juanlet/fb9794b2fb62a7d14a2a170a03be8abd to your computer and use it in GitHub Desktop.
Save juanlet/fb9794b2fb62a7d14a2a170a03be8abd to your computer and use it in GitHub Desktop.
zKvzBY
<div id="container" class="container text-center">
</div>
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};
}
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 topLeft= i-1 >=minX && j-1>=minY;
const topMiddle= j-1>=minY;
const topRight= i+1<maxX && j-1>=minY;
const right=i+1<maxX;
const bottomRight= i+1<maxX && j+1<maxY;
const bottomMiddle= j+1<maxY;
const bottomLeft= i-1>=minX && j+1<maxY;
const left= i-1>=minX;
//addPairs if they are within the limits of the matrix
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(left){
if(currentStatusMatrix[i-1]){
totalLiveNeighbours+=1;
}
}
if(totalLiveNeighbours>0 && i==0 && j==1){
console.log('totalNeib',totalLiveNeighbours,"left",left,"topLeft",topLeft,"topMiddle",topMiddle,"topRight",topRight,"right",right,"bottomright",bottomRight,"bottomMiddle",bottomMiddle,"bottomLeft",bottomLeft);
}
if(i===0 && 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=[]
console.log("maxX",this.state.boardWidth,"maxY",this.state.boardHeight);
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);
}
this.setState({ lifeStateMatrix: nextGenMatrix});
}
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(){
this.setState({ simulationIsRunning:true},()=>{
});
this.moveToNextGeneration();
}
pause(){
this.setState({ simulationIsRunning:false});
}
clear(x,y){
this.setState({ simulationIsRunning:false});
this.setState({lifeStateMatrix: []});
this.setBoardSizeAndStatusMatrix(x,y);
}
render(){
let generatedId=0, cellsRenderMatrix=[], x= this.state.boardWidth, y= this.state.boardHeight;
let clickableState;
if(this.state.simulationIsRunning){
clickableState=" none"
}else{
clickableState=" auto"
}
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]} />); generatedId++;
}
cellsRenderMatrix.push(rowRender);
}
return (
<div className="holder well">
<Header />
<div className="topButtons">
<button className="run btn gridPicker" onClick={this.start.bind(this)}>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", pointerEvents: clickableState}}>
{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')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.js"></script>
body
background-color: #455A64
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22)
.holder
background-color: #607D8B
border: none
font-family: 'Black Ops One', cursive
margin: 0 auto
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22)
.topButtons
margin-bottom: 1%
.bottomButtons
margin-top: 1%
.gridPicker
margin: 1%
.title
color: white
margin-top: 2%
margin-bottom: 2%
font-size: 3em
text-shadow: 2px 2px #000
.board
background-color: grey
overflow: hidden
margin: 0 auto
//pointer-events: none
.cell
background-color: #303F9F
width: 10px
height: 10px
border: 1px solid green
float: left
.alive
background-color: red
#generation
margin-left: 2%
font-size: 2em
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Black+Ops+One" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment