title: Implementing Conway's Game of Life in JavaScript with <canvas>
body: <p>I've got some problems implementing Conway's Game of Life in JavaScript. At the <a href="http://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens#Andere_Objekte" rel="nofollow noreferrer">German Wikipedia</a> it says that this pattern here:</p>
  
  <p><img src="https://www.abload.de/img/patterngbd6.jpg" alt="image could not be found"></p>
  
  <p>Will create an empty world after 54 generations and the evolution looks like this:</p>
  
  <p><img src="https://www.abload.de/img/desired_evolutiongxrk.gif" alt="image could not be found"></p>
  
  <p>That means, the second generation looks like this:</p>
  
  <p><img src="https://www.abload.de/img/desired_step2qyew.jpg" alt="image could not be found"></p>
  
  <p>But when using my code, the second generation looks like this and the world doesn't get empty, either:</p>
  
  <p><img src="https://www.abload.de/img/my_step2ub83.jpg" alt="image could not be found"></p>
  
  <p>So my code is obviously wrong, but I don't see my mistake:</p>
  
  <pre><code>var cellSize = 5,   // In px
      fieldSize = 70, // In cells
      canvas = document.getElementById("canvas"),
      ctx = canvas.getContext("2d"),
      thisGeneration = [],
      nextGeneration = [];
  
  // Set canvas size
  canvas.width = canvas.height = cellSize * fieldSize;
  
  
  // Fill the generation array
  for (var i = 0; i &lt; fieldSize; i++){
  
      thisGeneration.push([]);
  
      for (var x = 0; x &lt; fieldSize; x++){
  
          // thisGeneration[thisGeneration.length-1].push( (Math.random() &gt;  0.08)? 0 : 1);
  
          thisGeneration[thisGeneration.length-1].push(0);
  
      }
  
  }
  
  // Draw pattern:
  
  thisGeneration[35][35]      =   thisGeneration[35][36]  = thisGeneration[35][37] =
  
  thisGeneration[36][35]                                  = thisGeneration[36][37] =
  thisGeneration[37][35]                                  = thisGeneration[37][37] =
  
  
  thisGeneration[39][35]                                  = thisGeneration[39][37] =
  thisGeneration[40][35]                                  = thisGeneration[40][37] =
  thisGeneration[41][35]      =   thisGeneration[41][36]  = thisGeneration[41][37] =
  1;
  
  // "slice" causes "nextGeneration" to be a copy, not a reference
  nextGeneration = thisGeneration.slice(0);
  
  setInterval(function(){
  
      for (var y = 0, l = thisGeneration.length, x, l2, n; y &lt; l; y++){
  
          for (x = 0, l2 = thisGeneration[y].length;  x &lt; l2; x++){
  
              ctx.fillStyle = thisGeneration[y][x]? "black" : "white";
              ctx.fillRect(x*cellSize, y*cellSize, cellSize, cellSize);
  
              // n := Number of neighbors of the cell
              n = 0;
  
              if (typeof (thisGeneration[y-1]) != "undefined"){
  
                  n += (
  
                      (thisGeneration     [y-1]   [x-1]   ||0)+
                      (thisGeneration     [y-1]   [ x ]   ||0)+
                      (thisGeneration     [y-1]   [x+1]   ||0)
  
                  );
  
              }
  
              n += (
  
                  (thisGeneration     [ y ]   [x-1]   ||0)+
                  (thisGeneration     [ y ]   [x+1]   ||0)
  
              );
  
              if (typeof (thisGeneration[y+1]) != "undefined"){
  
                  n += (
  
                      (thisGeneration     [y+1]   [x-1]   ||0)+
                      (thisGeneration     [y+1]   [ x ]   ||0)+
                      (thisGeneration     [y+1]   [x+1]   ||0)
  
                  );
  
              }
  
              if (n === 3 &amp;&amp; !thisGeneration[y][x]){
              // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
  
                  nextGeneration[y][x] = 1;
  
              }
  
              if (n &lt; 2 &amp;&amp; thisGeneration[y][x]){
              // Any live cell with fewer than two live neighbours dies, as if caused by under-population.
  
                  nextGeneration[y][x] = 0;
  
              }
  
              if ((n === 2 || n === 3) &amp;&amp; thisGeneration[y][x]){
              // Any live cell with two or three live neighbours lives on to the next generation.
  
                  nextGeneration[y][x] = 1;
  
              }
  
              if (n &gt; 3 &amp;&amp; thisGeneration[y][x]){
              // Any live cell with more than three live neighbours dies, as if by overcrowding.
  
                  nextGeneration[y][x] = 0;
  
              }
  
          }
  
      }
  
      thisGeneration = nextGeneration.slice(0); // "slice" causes "thisGeneration" to be a copy, not a reference
  
  }, 1000);
  </code></pre>
  
  <p>I'd also like to know whether I could improve the performance of the script, because as you can see I use a 2-dimensional array save the cell states.</p>