--- /dev/null
+<script>
+function TicTacToeCntl(){
+ this.cellStyle= {
+ 'height': '20px',
+ 'width': '20px',
+ 'border': '1px solid black',
+ 'text-align': 'center',
+ 'vertical-align': 'middle',
+ 'cursor': 'pointer'
+ };
+ this.reset();
+ this.$watch('$location.hashPath', this.readUrl);
+}
+TicTacToeCntl.prototype = {
+ dropPiece: function(row, col) {
+ if (!this.winner && !this.board[row][col]) {
+ this.board[row][col] = this.nextMove;
+ this.nextMove = this.nextMove == 'X' ? 'O' : 'X';
+ this.setUrl();
+ }
+ },
+ reset: function(){
+ this.board = [
+ ['', '', ''],
+ ['', '', ''],
+ ['', '', '']
+ ];
+ this.nextMove = 'X';
+ this.winner = '';
+ this.setUrl();
+ },
+ grade: function(){
+ var b = this.board;
+ this.winner =
+ row(0) || row(1) || row(2) ||
+ col(0) || col(1) || col(2) ||
+ diagonal(-1) || diagonal(1);
+ function row(r) { return same(b[r][0], b[r][1], b[r][2]);}
+ function col(c) { return same(b[0][c], b[1][c], b[2][c]);}
+ function diagonal(i) { return same(b[0][1-i], b[1][1], b[2][1+i]);}
+ function same(a, b, c) { return (a==b && b==c) ? a : '';};
+ },
+ setUrl: function(){
+ var rows = [];
+ angular.foreach(this.board, function(row){
+ rows.push(row.join(','));
+ });
+ this.$location.hashPath = rows.join(';') + '/' + this.nextMove;
+ },
+ readUrl: function(value) {
+ if (value) {
+ value = value.split('/');
+ this.nextMove = value[1];
+ angular.foreach(value[0].split(';'), function(row, i){
+ this.board[i] = row.split(',');
+ }, this);
+ this.grade();
+ } else {
+ this.reset();
+ }
+ }
+};
+</script>
+<h3>Tic-Tac-Toe</h3>
+<div ng:controller="TicTacToeCntl">
+Next Player: {{nextMove}}
+<div ng:show="winner">Player {{winner}} has won!</div>
+<table>
+ <tr ng:repeat="row in board" style="height:15px;">
+ <td ng:repeat="cell in row" ng:style="cellStyle"
+ ng:click="dropPiece($parent.$index, $index)">{{cell}}</td>
+ </tr>
+</table>
+<button ng:click="reset()">reset board</button>
+</div>