Game of Life

In this example below you will see how to do a Game of Life with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by JanMP, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright JanMP ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Game of Life</title>
  
  
  <link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.min.css'>

      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div class="ui container segment">
  <div id='react-container'></div>
</div>
  <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.min.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/JanMP/game-of-life-OMdGJy */
body {
  padding-top: 2em;
  background-color: silver;
}

.alive {
  fill: green;
}

.dead {
  fill: silver;
}

input[type="range"] {
  width: 100%;
  -webkit-appearance: none;
  border: 1px solid #ddd;
  padding: 0;
  height: 0;
  margin-top: 1rem;
  margin-bottom: 1rem;
}

input[type="range"]:focus {
  border-color: #ccc;
  outline: none !important;
}

input[type="range"]::-moz-range-track {
  background: none;
  border: 0;
}

input[type="range"]::-moz-focus-outer {
  border: 0;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  height: 1.5rem;
  width: 1.5rem;
  background: #fff;
  background: #fff linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -o-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -moz-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  border-radius: 100%;
  box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
}

input[type="range"]::-moz-range-thumb {
  height: 1.5rem;
  width: 1.5rem;
  background: #fff;
  background: #fff linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -o-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  background: #fff -moz-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
  border-radius: 100%;
  box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15), 0 0 0 1px rgba(34, 36, 38, 0.15) inset;
}


/*Downloaded from https://www.codeseek.co/JanMP/game-of-life-OMdGJy */
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var timer;

var makeIterator = function makeIterator(fkt) {
  return function (field) {
    return field.map(function (column, x) {
      return column.map(function (cell, y) {
        return fkt(field, column, cell, x, y);
      });
    });
  };
};

var makeField = function makeField(width, height) {
  var cells = [];
  for (var x = 0; x < width; x++) {
    cells[x] = [];
    for (var y = 0; y < height; y++) {
      cells[x][y] = false;
    }
  }
  return cells;
};

var _iterate = makeIterator(function (field, column, cell, x, y) {
  var sum = 0;
  for (var i = x - 1; i <= x + 1; i++) {
    var xs = i;
    if (xs === -1) {
      xs = field.length - 1;
    }
    if (xs === field.length) {
      xs = 0;
    }
    for (var j = y - 1; j <= y + 1; j++) {
      var ys = j;
      if (ys === -1) {
        ys = column.length - 1;
      }
      if (ys === column.length) {
        ys = 0;
      }
      if (field[xs][ys] && (xs !== x || ys !== y)) {
        sum++;
      }
    }
  }
  if (sum === 2 && field[x][y]) {
    return true;
  }
  if (sum === 3) {
    return true;
  }
  return false;
});

var seedRandom = makeIterator(function (field, colun, cell, x, y) {
  return Math.random() > 0.5;
});

var Cell = React.createClass({
  displayName: "Cell",
  toggleCell: function toggleCell() {
    this.props.toggleCell(this.props.x, this.props.y);
  },
  render: function render() {
    var _props = this.props,
        x = _props.x,
        y = _props.y,
        size = _props.size,
        alive = _props.alive;

    if (true) {
      return React.createElement("circle", {
        cx: x * size + size / 2,
        cy: y * size + size / 2,
        r: size / 2,
        className: alive ? "alive" : "dead",
        onClick: this.toggleCell
      });
    } else {
      return React.createElement("rect", {
        x: x * size, y: y * size, width: size, height: size,
        fill: alive ? "green" : "none"
      });
    }
  }
});

var PlayField = React.createClass({
  displayName: "PlayField",
  getInitialState: function getInitialState() {
    return {
      cells: seedRandom(makeField(this.props.tilesX, this.props.tilesY))
    };
  },
  componentWillReceiveProps: function componentWillReceiveProps(newProps) {
    var iteration = this.props.iteration;
    while (iteration < newProps.iteration) {
      this.iterate();
      iteration++;
    };
    if (newProps.clear) {
      this.setState({ cells: makeField(newProps.tilesX, newProps.tilesY) });
      this.props.receipt({ clear: false });
    };
    if (newProps.reset) {
      this.setState({ cells: seedRandom(makeField(newProps.tilesX, newProps.tilesY)) });
      this.props.receipt({ reset: false });
    };
  },
  iterate: function iterate() {
    this.setState({ cells: _iterate(this.state.cells) });
  },
  toggleCell: function toggleCell(x, y) {
    var cells = this.state.cells;
    cells[x][y] = !cells[x][y];
    this.setState({ cells: cells });
  },
  render: function render() {
    var _this = this;

    return React.createElement(
      "svg",
      {
        width: this.props.tilesX * this.props.tileSize,
        height: this.props.tilesY * this.props.tileSize
      },
      _(this.state.cells).map(function (column, x) {
        return column.map(function (cell, y) {
          return React.createElement(Cell, { key: "cell" + x + "." + y,
            x: x, y: y, size: _this.props.tileSize,
            toggleCell: _this.toggleCell,
            alive: _this.state.cells[x][y] });
        });
      }).flatten().value()
    );
  }
});

var PlayButton = React.createClass({
  displayName: "PlayButton",
  handleClick: function handleClick(event) {
    this.props.setRunning(!this.props.running);
  },
  render: function render() {
    var fkStr = this.props.running ? "pause" : "play";
    return React.createElement(
      "button",
      { className: "ui icon button", onClick: this.handleClick },
      React.createElement("i", { className: fkStr + " icon" })
    );
  }
});

var App = React.createClass({
  displayName: "App",
  getInitialState: function getInitialState() {
    var tilesX = 90;
    var tilesY = 60;
    return {
      tilesX: tilesX,
      tilesY: tilesY,
      tileSize: this.calcTileSize(tilesX),
      running: true,
      iteration: 0,
      reset: false,
      clear: false
    };
  },
  calcTileSize: function calcTileSize(tilesX) {
    var width = $("#react-container").width();
    if (tilesX) {
      return width / tilesX;
    } else {
      return width / this.state.tilesX;
    }
  },
  handleResize: function handleResize() {
    this.setState({ tileSize: this.calcTileSize() });
  },


  componentDidMount: function componentDidMount() {
    window.addEventListener('resize', this.handleResize);
    this.setRunning(true);
  },

  componentWillUnmount: function componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  },

  setRunning: function setRunning(running) {
    var _this2 = this;

    this.setState({ running: running });
    if (running) {
      timer = window.setInterval(function () {
        _this2.setState({ iteration: _this2.state.iteration + 1 });
      }, 10);
    } else {
      if (timer) {
        clearInterval(timer);
      }
    }
  },
  reset: function reset() {
    this.setState({
      reset: true,
      iteration: 0
    });
  },
  clear: function clear() {
    this.setState({
      clear: true,
      iteration: 0
    });
  },
  handleSlider: function handleSlider(event) {
    this.setRunning(false);
    this.setState({
      tilesX: event.target.value,
      tilesY: Math.round(event.target.value * 2 / 3),
      tileSize: this.calcTileSize(event.target.value),
      reset: true,
      iteration: 0
    });
  },
  receipt: function receipt(obj) {
    this.setState(obj);
  },
  render: function render() {
    return React.createElement(
      "div",
      null,
      React.createElement(
        "h1",
        { className: "ui header" },
        "Conway's Game of Life"
      ),
      React.createElement(
        "div",
        { className: "ui segment" },
        React.createElement(
          "div",
          { className: "ui large basic label" },
          "Iteration : ",
          this.state.iteration,
          " "
        ),
        React.createElement(PlayButton, { running: this.state.running, setRunning: this.setRunning }),
        React.createElement(
          "button",
          { className: "ui" + (this.state.reset ? " active" : "") + " button", onClick: this.reset },
          "Reset"
        ),
        React.createElement(
          "button",
          { className: "ui" + (this.state.clear ? " active" : "") + " button", onClick: this.clear },
          "Clear"
        ),
        React.createElement(
          "div",
          { className: "ui segment" },
          React.createElement(
            "label",
            null,
            "Size: ",
            this.state.tilesX,
            " x ",
            this.state.tilesY
          ),
          React.createElement("input", { type: "range", onChange: this.handleSlider, value: this.state.tilesX, min: 30, max: 90, step: 1 })
        )
      ),
      React.createElement(PlayField, _extends({}, this.state, { receipt: this.receipt }))
    );
  }
});

window.onload = function () {
  React.render(React.createElement(App, null), document.querySelector("#react-container"));
};

Comments