AngularJS sample : game of life
by tchatel
HTML
<script src="http://code.angularjs.org/1.0.0rc1/angular-1.0.0rc1.js"></script>
<div ng:app ng-controller="GameOfLifeCntl">
<h1>AngularJS Game of Life</h1>
Height: <input type="text" ng-model="height"/>
Width: <input type="text" ng-model="width"/>
<button ng-click="newGame()">New</button>
<button ng-click="next()">Next</button>
<table id="board">
<tr ng-repeat="row in board">
<td ng-repeat="cell in row" ng-click="toggle($parent.$index, $index)"
class="{{cellClass($parent.$index, $index)}}">
<span ng-show="cell">O</span>
</td>
</tr>
</table>
<p class="history" ng-show="history.length > 0">Previous steps (click to rewind)</p>
<table class="history">
<tr>
<td ng-repeat="step in history" ng-click="$parent.step($index)">{{$index}}</td>
</tr>
</table>
</div>
CSS
h1 {
font-size: 1.3em;
color: #844;
font-style: bold;
}
table#board td {
width: 1.5em;
height: 1.5em;
text-align: center;
vertical-align: middle;
border: solid 1px #ddd;
}
table#board td.new {
background-color: #efe;
}
table#board td.die {
background-color: #fee;
}
.history {
color: #777;
}
table.history td {
width: 1.5em;
height: 1.5em;
text-align: center;
vertical-align: middle;
border: solid 1px #eee;
}
JavaScript
function GameOfLifeCntl($scope, $http, $resource) {
$scope.newGame = function () {
$scope.history = [];
$scope.board = init($scope.height, $scope.width);
};
$scope.next = function () {
$scope.history.push($scope.board);
$scope.board = computeNext($scope.board);
};
$scope.step = function (index) {
$scope.board = $scope.history[index];
$scope.history = $scope.history.slice(0, index);
};
$scope.toggle = function (row, cell) {
$scope.history = []; // Reset history as it is no longer accurate
$scope.board[row][cell] = !$scope.board[row][cell];
};
$scope.cellClass = function (row, cell) {
if (willDie($scope.board, row, cell)) {
return "die";
}
if (newCell($scope.board, row, cell)) {
return "new";
}
return "";
};
$scope.height = 10;
$scope.width = 20;
$scope.newGame();
function init(height, width) {
var board = [];
for (var h = 0 ; h < height ; h++) {
var row = [];
for (var w = 0 ; w < width ; w++) {
row.push(false);
}
board.push(row);
}
return board;
}
function computeNext(board) {
var newBoard = [];
for (var r = 0 ; r < board.length ; r++) {
var newRow = [];
for (var c = 0 ; c < board[r].length ; c++) {
newRow.push(willLive(board, r, c) || newCell(board, r, c));
}
newBoard.push(newRow);
}
return newBoard;
}
function willLive(board, row, cell) {
return cellAt(board, row, cell)
&& neighbours(board, row, cell) >= 2
&& neighbours(board, row, cell) <= 3;
}
function willDie(board, row, cell) {
return cellAt(board, row, cell)
&& (neighbours(board, row, cell) < 2
||...