Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save alanrsoares/9cb21cfd7001ca84265a to your computer and use it in GitHub Desktop.
Save alanrsoares/9cb21cfd7001ca84265a to your computer and use it in GitHub Desktop.
A Pen by Alan R. Soares.
<html ng-app='app'>
<head>
<meta name="description" content="AngularJs solution for Conway's Game of Life - http://en.wikipedia.org/wiki/Conway's_Game_of_Life" />
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css"/>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootswatch/3.2.0/slate/bootstrap.min.css" />
<meta charset="utf-8">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" />
</head>
<body>
<div class="container" ng-controller='GameController as vm'>
<div class="page-header text-center">
<h1>
<span class="text-muted">Conway's</span> Game of Life
</h1>
</div>
<div>
<div class="buttons-container">
<button class="btn btn-primary"
ng-disabled="!vm.thumbs.length"
ng-click="vm.reset()">
NEW
</button>
<button class="btn btn-success"
ng-click="vm.save()">
SAVE
</button>
<button class='btn btn-default'
ng-show="!vm.isStarted"
ng-click="vm.life.next()">
NEXT
</button>
<label for="autoplay" class="btn btn-default">
<input id="autoplay" type="checkbox"
ng-model="vm.isStarted"
ng-change="vm.togglePlay()"> Autoplay
</label>
</div>
</div>
<table class='grid'>
<tr ng-repeat="row in vm.board">
<td ng-repeat="cell in row"
ng-class="{'alive':cell.isAlive}"
ng-click="cell.toggle()">
</td>
</tr>
</table>
<div class="thumbs-container">
<div class="thumb-container"
ng-repeat="thumb in vm.thumbs">
<div>
<table class="grid-thumb"
ng-click="vm.load(thumb)">
<tr ng-repeat="row in thumb">
<td ng-repeat="cell in row"
ng-class="{'alive':cell.isAlive}">
</td>
</tr>
</table>
</div>
<div class="icon-close-thumb" ng-click="vm.thumbs.splice($index,1)">
<i class="fa fa-trash"></i>
<span class='text-small'>delete</span>
</div>
</div>
</div>
</div>
</body>
</html>
//app.js
(function(){
'use strict';
angular.module('app', ['app.controllers']);
}());
//app.controllers.js
(function(){
'use strict';
var app = angular.module('app.controllers', ['app.services']);
app.controller('GameController',GameController);
GameController.$inject = ['$interval','board','life'];
function GameController($interval, board, life){
var vm = this;
vm.thumbs = [];
vm.reset = reset;
vm.interval = 300;
vm.load = load;
vm.togglePlay = togglePlay;
vm.save = save;
function togglePlay(){
if(!vm.isStarted && vm.timer){
$interval.cancel(vm.timer);
vm.isStarted = false;
return;
}
vm.isStarted = true;
vm.timer = $interval(vm.life.next, vm.interval);
}
function save(){
var board = angular.copy(vm.board);
console.log(board);
vm.thumbs.push(board);
}
function load(thumb){
reset();
vm.life = life.createNew(thumb);
vm.board = vm.life.board;
}
function reset(){
if(vm.isStarted) vm.togglePlay();
var seed = board.createNew(15);
vm.life = life.createNew(seed);
vm.board = vm.life.board;
vm.isStarted = false;
}
(function activate(){
reset();
vm.life = life.createNew(window.initialSeed);
vm.board = vm.life.board;
vm.togglePlay();
}());
}
}());
//app.services.js
(function(){
'use strict';
var app = angular.module('app.services',[]);
app.factory('cell', cell);
app.factory('board', board);
app.factory('life', life);
function cell(){
return{
createNew: function(position, options){
return new Cell(position, options);
}
};
function Cell(position, options){
var defaults = {
isAlive: false
};
return {
position: position,
isAlive: options && options.isAlive,
toggle: function(){this.isAlive = !this.isAlive;},
lives: function(){this.isAlive = true;},
dies: function(){this.isAlive = false;},
getAliveNeighbors: function(board){
var y = this.position.y;
var x = this.position.x;
var prevRow = board[y - 1] || [];
var nextRow = board[y + 1] || [];
var neighbors = [
prevRow[x - 1], prevRow[x], prevRow[x + 1],
board[y][x - 1], board[y][x + 1],
nextRow[x - 1], nextRow[x], nextRow[x + 1],
];
return neighbors.reduce(function(prev, curr) {
if(curr){
return prev += +!!curr.isAlive;
}
return prev += 0;
}, 0);
}
};
}
}
board.$inject = ['cell'];
function board(cell){
return {
createNew: createNew
};
function createNew(size){
var newBoard = [];
for(var y = 0; y < size; y++){
newBoard[y] = [];
for(var x = 0; x < size; x++){
newBoard[y][x] = cell.createNew({y: y, x: x});
}
}
return newBoard;
}
}
life.$inject = ['cell'];
function life(cell){
return {
createNew: createNew
};
function createNew(seed){
var height = seed.length;
var width = seed[0].length;
var previousBoard = [];
var board = angular.copy(seed);
return{
next: next,
board: board
};
function newCellState(previousBoard, x, y){
var oldCell = previousBoard[y][x];
var newCell = cell.createNew(oldCell.position, {isAlive: oldCell.isAlive});
var neighbors = newCell.getAliveNeighbors(previousBoard);
newCell.isAlive = newCell.isAlive
? neighbors >= 2 && neighbors <= 3
: neighbors === 3;
return newCell;
}
function next(){
previousBoard = angular.copy(board);
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
board[y][x] = newCellState(previousBoard, x, y);
}
}
}
}
}
}());
window.initialSeed = [[{"position":{"y":0,"x":0}},{"position":{"y":0,"x":1}},{"position":{"y":0,"x":2}},{"position":{"y":0,"x":3}},{"position":{"y":0,"x":4}},{"position":{"y":0,"x":5}},{"position":{"y":0,"x":6}},{"position":{"y":0,"x":7},"isAlive":false},{"position":{"y":0,"x":8}},{"position":{"y":0,"x":9}},{"position":{"y":0,"x":10}},{"position":{"y":0,"x":11}},{"position":{"y":0,"x":12}},{"position":{"y":0,"x":13}},{"position":{"y":0,"x":14}}],[{"position":{"y":1,"x":0}},{"position":{"y":1,"x":1}},{"position":{"y":1,"x":2},"isAlive":false},{"position":{"y":1,"x":3},"isAlive":true},{"position":{"y":1,"x":4},"isAlive":true},{"position":{"y":1,"x":5},"isAlive":true},{"position":{"y":1,"x":6},"isAlive":false},{"position":{"y":1,"x":7},"isAlive":false},{"position":{"y":1,"x":8}},{"position":{"y":1,"x":9},"isAlive":true},{"position":{"y":1,"x":10},"isAlive":true},{"position":{"y":1,"x":11},"isAlive":true},{"position":{"y":1,"x":12},"isAlive":false},{"position":{"y":1,"x":13}},{"position":{"y":1,"x":14}}],[{"position":{"y":2,"x":0}},{"position":{"y":2,"x":1}},{"position":{"y":2,"x":2},"isAlive":false},{"position":{"y":2,"x":3},"isAlive":false},{"position":{"y":2,"x":4},"isAlive":false},{"position":{"y":2,"x":5},"isAlive":false},{"position":{"y":2,"x":6}},{"position":{"y":2,"x":7},"isAlive":false},{"position":{"y":2,"x":8}},{"position":{"y":2,"x":9},"isAlive":false},{"position":{"y":2,"x":10},"isAlive":false},{"position":{"y":2,"x":11},"isAlive":false},{"position":{"y":2,"x":12}},{"position":{"y":2,"x":13}},{"position":{"y":2,"x":14}}],[{"position":{"y":3,"x":0}},{"position":{"y":3,"x":1},"isAlive":true},{"position":{"y":3,"x":2}},{"position":{"y":3,"x":3}},{"position":{"y":3,"x":4}},{"position":{"y":3,"x":5}},{"position":{"y":3,"x":6},"isAlive":true},{"position":{"y":3,"x":7}},{"position":{"y":3,"x":8},"isAlive":true},{"position":{"y":3,"x":9}},{"position":{"y":3,"x":10}},{"position":{"y":3,"x":11}},{"position":{"y":3,"x":12}},{"position":{"y":3,"x":13},"isAlive":true},{"position":{"y":3,"x":14}}],[{"position":{"y":4,"x":0}},{"position":{"y":4,"x":1},"isAlive":true},{"position":{"y":4,"x":2}},{"position":{"y":4,"x":3}},{"position":{"y":4,"x":4}},{"position":{"y":4,"x":5}},{"position":{"y":4,"x":6},"isAlive":true},{"position":{"y":4,"x":7}},{"position":{"y":4,"x":8},"isAlive":true},{"position":{"y":4,"x":9}},{"position":{"y":4,"x":10}},{"position":{"y":4,"x":11}},{"position":{"y":4,"x":12}},{"position":{"y":4,"x":13},"isAlive":true},{"position":{"y":4,"x":14}}],[{"position":{"y":5,"x":0}},{"position":{"y":5,"x":1},"isAlive":true},{"position":{"y":5,"x":2}},{"position":{"y":5,"x":3}},{"position":{"y":5,"x":4}},{"position":{"y":5,"x":5}},{"position":{"y":5,"x":6},"isAlive":true},{"position":{"y":5,"x":7},"isAlive":false},{"position":{"y":5,"x":8},"isAlive":true},{"position":{"y":5,"x":9}},{"position":{"y":5,"x":10}},{"position":{"y":5,"x":11}},{"position":{"y":5,"x":12}},{"position":{"y":5,"x":13},"isAlive":true},{"position":{"y":5,"x":14}}],[{"position":{"y":6,"x":0}},{"position":{"y":6,"x":1},"isAlive":false},{"position":{"y":6,"x":2}},{"position":{"y":6,"x":3},"isAlive":true},{"position":{"y":6,"x":4},"isAlive":true},{"position":{"y":6,"x":5},"isAlive":true},{"position":{"y":6,"x":6},"isAlive":false},{"position":{"y":6,"x":7}},{"position":{"y":6,"x":8},"isAlive":false},{"position":{"y":6,"x":9},"isAlive":true},{"position":{"y":6,"x":10},"isAlive":true},{"position":{"y":6,"x":11},"isAlive":true},{"position":{"y":6,"x":12}},{"position":{"y":6,"x":13},"isAlive":false},{"position":{"y":6,"x":14}}],[{"position":{"y":7,"x":0}},{"position":{"y":7,"x":1}},{"position":{"y":7,"x":2}},{"position":{"y":7,"x":3},"isAlive":false},{"position":{"y":7,"x":4},"isAlive":false},{"position":{"y":7,"x":5},"isAlive":false},{"position":{"y":7,"x":6}},{"position":{"y":7,"x":7}},{"position":{"y":7,"x":8}},{"position":{"y":7,"x":9},"isAlive":false},{"position":{"y":7,"x":10},"isAlive":false},{"position":{"y":7,"x":11},"isAlive":false},{"position":{"y":7,"x":12}},{"position":{"y":7,"x":13}},{"position":{"y":7,"x":14}}],[{"position":{"y":8,"x":0}},{"position":{"y":8,"x":1}},{"position":{"y":8,"x":2}},{"position":{"y":8,"x":3},"isAlive":true},{"position":{"y":8,"x":4},"isAlive":true},{"position":{"y":8,"x":5},"isAlive":true},{"position":{"y":8,"x":6}},{"position":{"y":8,"x":7}},{"position":{"y":8,"x":8}},{"position":{"y":8,"x":9},"isAlive":true},{"position":{"y":8,"x":10},"isAlive":true},{"position":{"y":8,"x":11},"isAlive":true},{"position":{"y":8,"x":12},"isAlive":false},{"position":{"y":8,"x":13}},{"position":{"y":8,"x":14}}],[{"position":{"y":9,"x":0}},{"position":{"y":9,"x":1},"isAlive":true},{"position":{"y":9,"x":2}},{"position":{"y":9,"x":3},"isAlive":false},{"position":{"y":9,"x":4},"isAlive":false},{"position":{"y":9,"x":5},"isAlive":false},{"position":{"y":9,"x":6},"isAlive":true},{"position":{"y":9,"x":7}},{"position":{"y":9,"x":8},"isAlive":true},{"position":{"y":9,"x":9},"isAlive":false},{"position":{"y":9,"x":10},"isAlive":false},{"position":{"y":9,"x":11},"isAlive":false},{"position":{"y":9,"x":12}},{"position":{"y":9,"x":13},"isAlive":true},{"position":{"y":9,"x":14}}],[{"position":{"y":10,"x":0}},{"position":{"y":10,"x":1},"isAlive":true},{"position":{"y":10,"x":2}},{"position":{"y":10,"x":3}},{"position":{"y":10,"x":4}},{"position":{"y":10,"x":5}},{"position":{"y":10,"x":6},"isAlive":true},{"position":{"y":10,"x":7}},{"position":{"y":10,"x":8},"isAlive":true},{"position":{"y":10,"x":9}},{"position":{"y":10,"x":10}},{"position":{"y":10,"x":11}},{"position":{"y":10,"x":12},"isAlive":false},{"position":{"y":10,"x":13},"isAlive":true},{"position":{"y":10,"x":14}}],[{"position":{"y":11,"x":0}},{"position":{"y":11,"x":1},"isAlive":true},{"position":{"y":11,"x":2}},{"position":{"y":11,"x":3}},{"position":{"y":11,"x":4}},{"position":{"y":11,"x":5}},{"position":{"y":11,"x":6},"isAlive":true},{"position":{"y":11,"x":7}},{"position":{"y":11,"x":8},"isAlive":true},{"position":{"y":11,"x":9}},{"position":{"y":11,"x":10}},{"position":{"y":11,"x":11}},{"position":{"y":11,"x":12}},{"position":{"y":11,"x":13},"isAlive":true},{"position":{"y":11,"x":14}}],[{"position":{"y":12,"x":0}},{"position":{"y":12,"x":1},"isAlive":false},{"position":{"y":12,"x":2}},{"position":{"y":12,"x":3},"isAlive":false},{"position":{"y":12,"x":4},"isAlive":false},{"position":{"y":12,"x":5},"isAlive":false},{"position":{"y":12,"x":6},"isAlive":false},{"position":{"y":12,"x":7},"isAlive":false},{"position":{"y":12,"x":8},"isAlive":false},{"position":{"y":12,"x":9}},{"position":{"y":12,"x":10}},{"position":{"y":12,"x":11}},{"position":{"y":12,"x":12}},{"position":{"y":12,"x":13},"isAlive":false},{"position":{"y":12,"x":14}}],[{"position":{"y":13,"x":0}},{"position":{"y":13,"x":1}},{"position":{"y":13,"x":2}},{"position":{"y":13,"x":3},"isAlive":true},{"position":{"y":13,"x":4},"isAlive":true},{"position":{"y":13,"x":5},"isAlive":true},{"position":{"y":13,"x":6}},{"position":{"y":13,"x":7}},{"position":{"y":13,"x":8}},{"position":{"y":13,"x":9},"isAlive":true},{"position":{"y":13,"x":10},"isAlive":true},{"position":{"y":13,"x":11},"isAlive":true},{"position":{"y":13,"x":12}},{"position":{"y":13,"x":13}},{"position":{"y":13,"x":14}}],[{"position":{"y":14,"x":0}},{"position":{"y":14,"x":1}},{"position":{"y":14,"x":2}},{"position":{"y":14,"x":3}},{"position":{"y":14,"x":4}},{"position":{"y":14,"x":5}},{"position":{"y":14,"x":6}},{"position":{"y":14,"x":7}},{"position":{"y":14,"x":8}},{"position":{"y":14,"x":9}},{"position":{"y":14,"x":10}},{"position":{"y":14,"x":11}},{"position":{"y":14,"x":12}},{"position":{"y":14,"x":13}},{"position":{"y":14,"x":14}}]];
.text-center{
text-align: center;
}
.grid{
margin: auto;
border-spacing: 0;
border: solid 2px #111;
tr{
td{
&.alive{
background: #fff;
}
&:hover{
cursor:pointer;
}
margin: 0;
padding: 0;
border: solid 1px #111;
width: 22px;
height: 22px;
}
}
&-thumb{
tr{
td{
height:3px;
width:3px;
&.alive{
background: #fff;
}
}
}
}
}
.buttons-container{
text-align: center;
margin: 20px auto;
}
.thumbs-container{
margin: 15px auto;
width: 357px;
}
.thumb-container{
border: solid 1px #6f6;
display:inline-block;
height: 47px;
width: 47px;
margin: 0 2px;
overflow: hidden;
.icon-close-thumb{
position: relative;
top: 0;
font-size: 12px;
padding: 2px;
color: #c33;
background: rgba(400,400,400,0.9);
height: 25px;
transition: 0.5s;
cursor: pointer;
.text-small{
font-size: 10px;
}
}
&:hover{
.icon-close-thumb{
top: -20px;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment