0

我制作了这个简单的配对游戏,将我所有的代码都放在app.js中。要玩它,您只需在屏幕上配对卡片:每次配对时,card对象都会打印到控制台,其中包含游戏变量,例如移动次数、游戏计时器等。这些游戏变量应该会显示出来在屏幕的右下方,但我似乎无法通过CardFlipper控制器的$scope. 我该怎么做?我应该在控制器内移动我的功能和对象吗?这是我第一次使用 Angular JS,所以请随时提出更好的做法或更有效的方法来做到这一点。这是我的 app.js:

var app = angular.module('memoApp', []);

app.filter('shuffle', function() {
  返回函数(数组){
    var counter = array.length, temp, index;
    而(反--){
        索引 = (Math.random() * 计数器) | 0;
        临时=数组[计数器];
        数组[计数器] = 数组 [索引];
        数组[索引] = 温度;
    } 返回数组;
  }
});

app.directive('card', function() {
  返回函数(范围,元素){
    element.bind('click', function(e) {
      e.preventDefault();
      揭示卡($(this).children('a'));
      控制台.log(卡);
    });
  }
});

功能 CardFlipper($scope) {
    $scope.deck = [
      1, 2, 3, 4, 5, 6, 7, 8, 9,
      1、2、3、4、5、6、7、8、9
    ];
    $scope.card = 卡片;
 };

 /* 游戏 */

变量卡 = {
  计数:0,
  对:0,
  移动:0,
  计时器:0
};

var timer = setInterval(function(){
  card.timer++;
}, 1000);

varrevealCard = function(picked) {
  if (card.count!=1) {
    // 第一步:存储数据
    card.pair =pick.data('pair');
    卡数 = 1;
    转牌('擦除');
    turnCard('flip', pick, card.pair);
  } 别的 {
    // 第二步:比较
    if (picked.data('pair')==card.pair) {
      if (!picked.hasClass('flip')) {
        turnCard('win',pick,pick.data('pair'));
      } 别的 {
        转牌('擦除');
      }
    } 别的 {
      turnCard('flip', pick, pick.data('pair'));
    }
    卡数 = 2;
    卡片.moves++;
  }
};

var turnCard = function(结果,挑选,对){
  开关(结果){
    案例“翻转”:
      pick.toggleClass('flip').html(pair);
      休息;
    案例“赢”:
      pick.addClass('flip').html(card.pair);
      $('ul#game .flip').addClass('win');
      休息;
    案例“擦除”:
      $('ul#game li').find('a').removeClass('flip').html('');
      休息;
  }
};
4

1 回答 1

1

我相信您过于依赖 jQuery 来实现您的游戏。您只使用 Angular 将 jQuery 事件绑定到 DOM 元素。

你的游戏是 Angular 新手的一个很好的例子,所以我编写了我自己的版本。

看看这个jsfiddle

JS代码:

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 <= 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 < this.cards.length; i++) {
            if (this.cards[i] !== card) {
                this.cards[i].hide(); 
            }
        }
    };

    Deck.prototype.allCleared = function() {
        for (var i = 0; i < 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
});

模板:

<div ng-app="CardFlipperApp">
    <div ng-controller="CardFlipperCtrl">
        <button ng-click="init()">Reset</button>
        Moves: {{moves}} - Time: {{timer}}
        <div ng-if="!done" ng-repeat="card in deck.cards">
            <div class="card" ng-class="{visible: card.visible, cleared: card.cleared, changeLine: ($index % 6 == 0)}" ng-click="toggle(card)">
                <span ng-if="card.visible">{{card.number}}</span>
            </div>
        </div>
        <div ng-if="done" class="done">Done!</div>
    </div>
</div>

注意像 Card and Deck 这样的“模型”的使用。模型不是 Angular 特有的东西(jQuery 应用程序可以抽象这些实体),但在 Angular 中,模型可以在 IOC 内注册为服务并利用 DI(Deck 依赖于 Card,控制器依赖于 Deck)。

我发现这样做的最佳方式是在服务中定义一个普通的 JS“类”(属性、方法、“静态”函数等)并返回要在 Angular 中注册的构造函数。另一个依赖它的组件,只需调用 new ModelClass()。

您的应用程序的大量功能可以驻留在“模型”(与 Angular 无关的代码)中。这样,您的应用程序就更易于阅读、理解和测试。

于 2013-11-04T16:37:50.107 回答