Angular: Card game
Amazing demo
by Freewind
HTML
<script src="http://code.angularjs.org/angular-1.0.0rc9.js"></script>
<script type="text/ng-template" id="tile.html">
<div ng-click="onFlip(tile)" class="tile" ng-class="{flipped: tile.flipped, matched: tile.matched}">
<div class="back"><img ng-src="https://github.com/IgorMinar/Memory-Game/raw/master/app/img/back.png"/></div>
<div class="front"><img ng-src="https://github.com/IgorMinar/Memory-Game/raw/master/app/img/{{tile.display}}.png"/></div>
</div>
</script>
<div ng-controller="GridCtrl" >
<div>Pairs left to match: {{unmatchedPairs}}</div>
<div>Matching: {{guesses[0].display}}</div>
<table class="tiles" ng-click="newGameIfFinished()" ng-class="{won: unmatchedPairs == 0}">
<tr ng-repeat="row in grid">
<td ng-repeat="tile in row">
<flip-tile tile="tile" on-flip="flipTile"></flip-tile>
</td>
</tr>
</table>
<div>{{message}}</div>
</div>
CSS
/* app css stylesheet */
@-webkit-keyframes spin {
from { -webkit-transform: scale(0.8) rotateX(180deg) rotateZ(0); }
to { -webkit-transform: scale(0.8) rotateX(180deg) rotateZ(-360deg); }
}
body {
font-family: Segoe UI;
fonz-size: 16pt;
}
.menu {
list-style: none;
border-bottom: 0.1em solid black;
margin-bottom: 2em;
padding: 0 0 0.5em;
}
.menu:before {
content: "[";
}
.menu:after {
content: "]";
}
.menu > li {
display: inline;
}
.menu > li:before {
content: "|";
padding-right: 0.3em;
}
.menu > li:nth-child(1):before {
content: "";
padding: 0;
}
.tiles {
-webkit-perspective: 1000px;
-webkit-transition: all 1s ease-in-out;
}
.tiles.won:hover {
cursor: pointer;
-webkit-transform: scale(0.9);
}
.tile {
-webkit-transition: all 0.4s ease-in-out;
-webkit-transform-style: preserve-3d;
position: relative;
width: 165px;
height: 200px;
}
.tile:hover {
-webkit-transform: rotateX(20deg);
}
.tile.flipped {
-webkit-transform: rotateX(180deg);
}
.tile.flipped.matched {
-webkit-transform: scale(0.8) rotateX(180deg);
opacity: 0.7;
}
.won .matched {
-webkit-animation: spin 1s 2 linear;
}
.front {
position: absolute;
-webkit-backface-visibility: hidden;
-webkit-transform: rotateX(180deg);
}
.back {
position: absolute;
-webkit-backface-visibility: hidden;
}
JavaScript
angular.module('myApp', [])
.directive('flipTile', function() {
return {
restrict: 'E',
scope: {tile: 'evaluate', onFlip: 'evaluate'},
templateUrl: 'tile.html'
};
});
function Tile(title) {
this.title = title;
this.display = 'back';
this.flipped = false;
this.matched = false;
this.show = function() {
this.display = this.title;
this.flipped = true;
};
this.hide = function() {
this.display = 'back';
this.flipped = false;
};
}
function GridCtrl($scope) {
$scope.grid = newGame();
$scope.guesses = [];
var canStartNew = false;
$scope.newGameIfFinished = function() {
if ($scope.unmatchedPairs != 0) {
return false;
}
if (!canStartNew) {
canStartNew = true;
return false;
}
canStartNew = false;
$scope.grid = newGame();
$scope.guesses = [];
};
function getTile(tileDeck) {
var i = Math.floor(Math.random()*tileDeck.length);
return tileDeck.splice(i, 1)[0];
}
/* Create an array with two of each tileName in it */
function makeDeck(tileNames) {
var tileDeck = [];
for (var i = 0; i < tileNames.length; i++) {
tileDeck.push(new Tile(tileNames[i]));
tileDeck.push(new Tile(tileNames[i]));
}
return tileDeck;
}
/* Make a 2-D array with the specified number of rows and columns */
function makeGrid(numRows, numCols) {
var grid = new Array(numRows);
for (var row = 0; row < numRows; row++) {
for (var col = 0; col < numCols; col++) {
grid[row] = new Array(numCols);
}
}
return grid;
}
/* Fill the grid with tiles picked at random */
function newGame() {
//var tileNames = ['foo', 'bar', 'baz', 'bon', 'fir', 'fur', 'onz', 'huq'];
var tileNames = ['8-ball',...