Search code examples
javascriptconways-game-of-life

Options on making the code more clean


I made this simple game of life simulation and wondering if I can make the code cleaner

What options do I have?

jsfiddle: https://jsfiddle.net/04vazdrb/

 /*
     Conway's Game Of Life in JavaScript
    */

window.onload = function() {

    var gridHeight = 400;
    var gridWidth = 400;
    var theGrid = createCellArr(gridWidth);
    var mirrorGrid = createCellArr(gridWidth);
    var genCounter = 0;

    seed();
    tick();
    //main loop
    function tick() {
      drawGrind();
      updateGrid();
      counter();
      requestAnimationFrame(tick);
    }
    /* Returns an array with n elements and places an empty 
       array in each of them using a FOR loop.
    */
    function createCellArr(rows) {
      var arr = [];
      for (var i = 0; i < rows; i++) {
        arr[i] = [];
      }
      return arr;
    }

    // Populating & filling the grid randomly.
    function seed() {
      // Iterate through rows
      for (var j = 0; j < gridHeight; j++) {
        // /iterate through columns
        for (var k = 0; k < gridWidth; k++) {
          //get a raw random number bettwen 0-1
          var randomBinary = Math.floor(Math.random() * 2);
          // checking the state
          theGrid[j][k] = randomBinary;
        }
      }
    }

    // draw each grid cell in the array as a pixel on a Canvas
    function drawGrind() {
      var c = document.getElementById("gridCanvas");
      var ctx = c.getContext("2d"); // get the context
      ctx.clearRect(0, 0, 400, 400); // clear the canvas ahead of each redraw - (x, y, width, height)

      //iterate through rows
      for (var j = 1; j < gridHeight; j++) {
        //iterate through the coloumns
        for (var k = 1; k < gridWidth; k++) {
          if (theGrid[j][k] === 1) { // alive cell
            ctx.fillStyle = "#71bc4a"; // hot red!
            ctx.fillRect(j, k, 1, 1) // fill a cell (x, y, width, height) 
          }
        }
      }

    }

    // Update the grid - game logic
    function updateGrid() {
      //iterate through rows
      for (var j = 1; j < gridHeight - 1; j++) {
        //iterate through columns
        for (var k = 1; k < gridWidth - 1; k++) {
          var totalCells = 0;
          //add up the total values for the surrounding cells
          totalCells += theGrid[j - 1][k - 1]; // top left
          totalCells += theGrid[j - 1][k]; //top center
          totalCells += theGrid[j - 1][k + 1]; //top right
          totalCells += theGrid[j][k - 1]; //middle left
          totalCells += theGrid[j][k + 1]; //middle right
          totalCells += theGrid[j + 1][k - 1]; //bottom left
          totalCells += theGrid[j + 1][k]; //bottom center
          totalCells += theGrid[j + 1][k + 1]; //bottom right

          //apply the rules to each cell
          if (theGrid[j][k] === 0) {
            switch (totalCells) {
              case 3:
                // if cell is dead and has 3 neighbours, switch it on
                mirrorGrid[j][k] = 1;
                break;
              default:
                mirrorGrid[j][k] = 0; //otherwise leave it dead

            }
            //apply rules to living cell
          } else if (theGrid[j][k] === 1) {
            switch (totalCells) {
              case 0:
              case 1:
                mirrorGrid[j][k] = 0; //die of lonelines
                break;
              case 2:
              case 3:
                mirrorGrid[j][k] = 1; //carry on living
                break;
              case 4:
              case 5:
              case 6:
              case 7:
              case 8:
                mirrorGrid[j][k] = 0; //die of overcrowding
                break;
              default:
                mirrorGrid[j][k] = 0; //   
            }
          }
        }
      }
      ////iterate through rows
      for (var j = 0; j < gridHeight; j++) {
        //iterate through columns
        for (var k = 0; k < gridWidth; k++) {
          //copy mirrorGrid to theGrid
          theGrid[j][k] = mirrorGrid[j][k];
        }
      }
    }
    // Generation counter
    function counter() {
      genCounter++;
      document.getElementById("generationCount").innerHTML = "Generation: " + genCounter;
    }

  } //]]>

Solution

  • You can abstract the action of looping each cell in it's own function, like this:

    function forEachCell(doSomething) {
        // Iterate through rows
        for (var y = 0; y < gridHeight; y++) {
            // Iterate through columns
            for (var x = 0; x < gridWidth; x++) {
                doSomething(x, y);
            }
        }
    }
    

    Have a look: https://jsfiddle.net/uzrabeq0/