0

この単純なペア ゲームを作成し、すべてのコードをapp.jsに詰め込みました。それをプレイするには、単純に画面上でカードをペアにする必要があります。ペアにするたびにcard、移動回数、ゲーム タイマーなどのゲーム変数を含むオブジェクトがコンソールに出力されます。これらのゲーム変数が表示されるはずです。画面の右下にありますが、CardFlipperコントローラーの$scope. どうすればいいですか?関数とオブジェクトをコントローラー内に移動する必要がありますか? Angular JS を使用するのはこれが初めてなので、これを行うためのより良いプラクティスまたはより効率的な方法を提案してください。ここに私の app.js があります:

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

app.filter('シャッフル', function() {
  リターン関数(配列) {
    var カウンター = array.length、temp、index;
    while (カウンター--) {
        インデックス = (Math.random() * カウンター) | 0;
        temp = 配列[カウンター];
        配列[カウンター] = 配列[インデックス];
        配列[インデックス] = temp;
    配列を返します。
  }
});

app.directive('カード', function() {
  リターン関数(スコープ、要素){
    element.bind('クリック', function(e) {
      e.preventDefault();
      RevealCard($(this).children('a'));
      console.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 タイマー = setInterval(関数(){
  card.timer++;
}、1000);

var明らかにカード=関数(選択){
  if (card.count!=1) {
    // 最初の動き: データを保存
    card.pair = pick.data('ペア');
    card.count = 1;
    turnCard('ワイプ');
    turnCard('フリップ', ピック, card.pair);
  } そうしないと {
    // 二手目: 比較
    if (picked.data('pair')==card.pair) {
      if (!picked.hasClass('flip')) {
        turnCard('win',picked,picked.data('pair'));
      } そうしないと {
        turnCard('ワイプ');
      }
    } そうしないと {
      turnCard('フリップ', ピック, pick.data('ペア'));
    }
    card.count = 2;
    card.moves++;
  }
};

var turnCard = function(結果、選択、ペア) {
  スイッチ (結果) {
    ケース「フリップ」:
      pick.toggleClass('flip').html(ペア);
      壊す;
    ケース「勝つ」:
      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>

カードやデッキなどの「モデル」の使用に注意してください。モデルは Angular に固有のものではありません (jQuery アプリはこれらのエンティティを抽象化できます) が、Angular ではモデルを IOC 内のサービスとして登録し、DI を利用できます (デッキはカードに依存し、コントローラーはデッキに依存します)。

これを行うのに最適な方法は、サービス (プロパティ、メソッド、「静的」関数など) 内でプレーンな JS "クラス" を定義し、Angular に登録されるコンストラクターを返すことです。それに依存する別のコンポーネントは、単純に new ModelClass() を呼び出します。

アプリの実質的な機能は、「モデル」(Angular とは関係のないコード) に含めることができます。そうすれば、アプリは読みやすく、理解しやすく、テストしやすくなります。

于 2013-11-04T16:37:50.107 に答える