Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I believe you are relying too much to jQuery to implement your game. You use Angular only to bind jQuery events to DOM elements.</p> <p>Your game is a great example for someone new to Angular, so I've written my own version of it.</p> <p>Check out this <a href="http://jsfiddle.net/UQwMa/" rel="nofollow">jsfiddle</a>.</p> <p>Js Code:</p> <pre><code>angular.module('CardFlipperApp', []) /* Card model */ .factory('Card', function() { function Card (number) { this.visible = false; this.cleared = false; this.number = number; }; Card.prototype.show = function() { this.visible = true; }; Card.prototype.hide = function() { this.visible = false; }; Card.prototype.clear = function() { this.cleared = true; }; return Card; }) /* Deck model */ .factory('Deck', function(Card) { function shuffle(array) { var counter = array.length, temp, index; while (counter--) { index = (Math.random() * counter) | 0; temp = array[counter]; array[counter] = array[index]; array[index] = temp; } return array; } function Deck (numberOfCards) { var array = []; for (var i = 1; i &lt;= numberOfCards; i++) { array.push(new Card(i)); array.push(new Card(i)); } this.cards = shuffle(array); }; Deck.prototype.hideAllBut = function(card) { for (var i = 0; i &lt; this.cards.length; i++) { if (this.cards[i] !== card) { this.cards[i].hide(); } } }; Deck.prototype.allCleared = function() { for (var i = 0; i &lt; this.cards.length; i++) { if (!this.cards[i].cleared) { return false; } } return true; }; return Deck; }) .controller('CardFlipperCtrl', function($scope, $timeout, Deck) { var timeoutHandle = null; function nextTick(){ $scope.timer++; timeoutHandle = $timeout(nextTick,1000); } function startTimer() { timeoutHandle = $timeout(nextTick, 1000); } function stopTimer() { if (timeoutHandle) { $timeout.cancel(timeoutHandle); timeoutHandle = null; } } $scope.init = function() { $scope.deck = new Deck(9); stopTimer(); $scope.moves = 0 $scope.timer = 0; $scope.done = false; }; $scope.toggle = function(card) { // double click, do nothing if ($scope.selectedCard === card) { return; } $scope.moves++; if ($scope.moves === 1) { // start timer on 1st move startTimer(); } if ($scope.selectedCard) { if ($scope.selectedCard.number === card.number) { $scope.selectedCard.clear(); card.clear(); if ($scope.deck.allCleared()) { $scope.done = true; stopTimer(); } } else { card.show(); } $scope.selectedCard = null; } else { card.show(); $scope.deck.hideAllBut(card); $scope.selectedCard = card; } }; $scope.init(); // initial deck creation }); </code></pre> <p>Template:</p> <pre><code>&lt;div ng-app="CardFlipperApp"&gt; &lt;div ng-controller="CardFlipperCtrl"&gt; &lt;button ng-click="init()"&gt;Reset&lt;/button&gt; Moves: {{moves}} - Time: {{timer}} &lt;div ng-if="!done" ng-repeat="card in deck.cards"&gt; &lt;div class="card" ng-class="{visible: card.visible, cleared: card.cleared, changeLine: ($index % 6 == 0)}" ng-click="toggle(card)"&gt; &lt;span ng-if="card.visible"&gt;{{card.number}}&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;div ng-if="done" class="done"&gt;Done!&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; </code></pre> <p>Take note of the use of "models" like Card and Deck. Models are not something specific to Angular (a jQuery app could abstract those entities) but in Angular, models can be registered as services inside the IOC and take advantage of DI (Deck depends on Card, controller depends on Deck). </p> <p>The way I find best for doing so, is defining a plain JS "class" inside a service (properties, methods, "static" functions etc) and return the contructor to be registered in Angular. Another component that depends on it, simply calls new ModelClass().</p> <p>Substantial functionality of your app can reside in "models" (code that has nothing to do with Angular). That way, your app is easier to read, understand and test.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload