cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

Looking for quick-add? Try the external resource search, it's quicker and gives you access to the most recent version of thousands of libraries. ☝️

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Looking for quick-add? Try the external resource search, it's quicker and gives you access to the most recent version of thousands of libraries. ☝️

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <!-- CODED BY valmassoi -->

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"/>

<div>
  <h1>Conway's Game of Life using ReactJS</h1>
  <div id="app"></div>
 <div class = "well">
    <a href="https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life" target="_blank"><i class="fa fa-info-circle" aria-hidden="true"></i> Read about the Game of Life</a><br>
    <a href="https://www.youtube.com/watch?v=E8kUJL04ELA" target="_blank"><i class="fa fa-youtube-play" aria-hidden="true"></i> Watch John Conway explain his Game of Life</a>
   <h4>Rules:</h4>
   <ul>
      <li>Any live cell with fewer than two live neighbours dies, as if caused by under-population.</li>
      <li>Any live cell with two or three live neighbours lives on to the next generation.</li>
      <li>Any live cell with more than three live neighbours dies, as if by over-population.</li>
      <li>Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.</li>
   </ul>
 </div>
</div>
<!--
I choose to use svg, I used a 2d array then had a setItervale function that checks the output, figure out the next state of the 2d array and updates it.
-->
            
          
!
            
              $lt-grey: #E8E8E8

body
  margin: 20px
  background: grey
button
  margin: 0px 5px 5px 0px
  background: steelblue
  vertical-align: top
  padding: 5px 15px
  color: white
  text-align: center
  background: #2980b9
  border: 0
  cursor: pointer
  -webkit-box-shadow: inset 0 -2px #2475ab
  box-shadow: inset 0 -2px #2475ab
.dead
  fill: white
  // cursor:pointer why not working?
.alive
  fill: steelblue
  // stroke: white
.dieing
  fill: grey
.well
  width: 840px
  margin-top: 10px
svg
  box-shadow: 0px 0px 20px #000
a
  color: steelblue
h4
  margin-bottom: 15px
            
          
!
            
              //0 dead  //1 alive

const columns = 70, rows = 50, box=12, speed=50;
const width=box*columns, height=box*rows;
let run = 0;
class Layout extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = {
      cells: [[]],
      gen: 0,
      running: false
    }
  }
  
  // -- Init Populate -- //
  componentWillMount() {
    this.setRandos();
  }
  setRandos(){
    let twoDee = [], tempArr = [];
    for(let i=0; i<rows; i++){
      for(let j=0; j<columns; j++){
        let num = _.random(0,1);
        tempArr.push(num);
      }
      twoDee.push(tempArr);
      tempArr=[];
    }
    this.setState({ cells: twoDee, gen: 0 });
    this.Run();
  }
  
  // -- Controlls -- //
  Run() {
    if(!this.state.running){
      console.log("Run");
      this.setState({ running: true }); //gen: 0
      run = setInterval(function(){this.checkNeighbor();}.bind(this), speed);
    }
  }
  Pause() {
    if(this.state.running){
      console.log("Pause");
      clearInterval(run);
      this.setState({ running: false });
    }
  }
  Clear() {
    console.log("Clear");
    clearInterval(run);
    this.setState({ running: false });
    let twoDee = [], tempArr = [];
    for(let i=0; i<rows; i++){
      for(let j=0; j<columns; j++){
        tempArr.push(0);
      }
      twoDee.push(tempArr);
      tempArr=[];
    }
    this.setState({ cells: twoDee, gen: 0 });
  }
  
  // -- Neighbors -- //
  
  checkNeighbor(){
 //   if(this.state.running){
      let nextLife = JSON.parse(JSON.stringify(this.state.cells));//initialize nextLife  IMMUTABLE
      console.log(nextLife);
      for(let i=0; i<rows; i++){//y
        for(let j=0; j<columns; j++){//x
          this.theHood(j,i, nextLife);//not best to pass variable this way
        }
      }
 //   }
  }
  
  theHood(x,y, nextLife){
    let neighbor = 0;//reset count each iteration
    //count alive neighbors
    if(y>0 && x>0 && this.state.cells[y-1][x-1]===1){neighbor++;};//TL    // check for edges
    if(y>0 && this.state.cells[y-1][x]===1){neighbor++;};//TM
    if(y>0 && x+1<columns && this.state.cells[y-1][x+1]===1){neighbor++;};//TR
    
    if(x>0 && this.state.cells[y][x-1]===1){neighbor++;};//L
    if(x+1<columns && this.state.cells[y][x+1]===1){neighbor++;};//R
    
    if(y+1<rows && x>0 && this.state.cells[y+1][x-1]===1){neighbor++;};//BL
    if(y+1<rows && this.state.cells[y+1][x]===1){neighbor++;};//BM
    if(y+1<rows && x+1<columns && this.state.cells[y+1][x+1]===1){neighbor++;};//BR
    
    //check rules
    if (this.state.cells[y][x] === 1){//alive rules
      if (neighbor <2){
        //dies
        nextLife[y][x]=0;
      }
      if (neighbor === 2 || neighbor === 3){
        //lives
        nextLife[y][x]=1;
      }
      if (neighbor > 3){
        //dies
        nextLife[y][x]=0;
      }
    }
    else{
      if (neighbor === 3){
        //becomes alive
        nextLife[y][x]=1;
      }
    }
    if(x==columns-1 && y==rows-1){
      console.log("go to next Gen");
      this.setState({ cells: nextLife, gen: ++this.state.gen});
    }//update state after last
  }
  
  manual(x, y){
    console.log(x,y);
    let tempArr = this.state.cells;
    (tempArr[y][x])===0 ? tempArr[y][x]=1 : tempArr[y][x]=0;
    this.setState({ cells: tempArr });
  }
  render() {
    return (
      <div>
        <button onClick={this.Run.bind(this)}>Run</button>
        <button onClick={this.Pause.bind(this)}>Pause</button>
        <button onClick={this.Clear.bind(this)}>Clear</button>
        <button onClick={this.setRandos.bind(this)}>New Random</button>
        <h4>Generation: {this.state.gen}</h4>

         <svg width={width} height={height}>
          {this.state.cells.map(function(row, y) {
            return row.map(function(life, x) {
              return (
                <rect key={`${x},${y}`} x={x*box} y={y*box} width={box} height={box} className={(life===1) ? 'alive':'dead'} stroke='grey' strokeWidth={.25} onClick={this.manual.bind(this, x, y)}/>
              );
            }.bind(this))
          }.bind(this))}
        </svg>
      </div>
    );
  }
}

const app = document.getElementById('app');
ReactDOM.render(<Layout/>, app);

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console