-
Notifications
You must be signed in to change notification settings - Fork 3
/
memory-game.js
142 lines (127 loc) · 3.9 KB
/
memory-game.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// This module is completely finished! You just need to understand how it works, then integrate it.
/// Module 2
var MemoryGame = (function() {
function Ctor(cardset) {
var slots, //values of shuffled cards;
//sparse array: will have elements deleted as cards
// are removed
length,//total slots, including gaps
there, //position of face-up card if any, or false
_gui = null;
// Helper functions which need access to closure vars;
// some fns will be made public as instance methods:
var reset = function() {
// replaces all removed cards, reshuffles entire board,
// rebuilds board face-down
slots = cardset.values();
length = slots.length;
there = false;
shuffle(slots);
}
reset();
//replaces all removed cards, reshuffles entire board, rebuilds board face-down// reset now as part of init'ing
var gui = function() { //accessor fn
if (arguments.length === 0)
return _gui; //getter
_gui = arguments[0]; //setter
}
var size = function() {
return length;
}
var remainsAt = function(where) {//--> boolean
return slots[where]!==undefined;
}
var valueAt = function(where) {//--> card val
return slots[where];
}
var removeAt = function(where) {
//MATCHED
delete slots[where];
}
var faceupValue = function() {//--> card val
//returns the raw value of one face-up card
//(if any) otherwise false
return valueAt(there);
}
var faceupWhere = function() {//--> integer
//returns the position (a number) of the one
//face-up card (if any), otherwise returns false
return there;
}
var remaining = function() {//--> array of integers
//remaining returns an array of the positions
// of all cards still on the board, including
// faceupWhere() if any
return Object.keys(slots).map(Number);
}
var lift = function(here) {//--> display string
// lift(where) attempts to lift a card.
//if there's a face-down card at position WHERE
// (a single number), return its display value,
//by calling cardset.display(val) callback on the
//card's raw value, otherwise return false if there's
//not currently a face-up card, leave this card face-up.
//if there's already a face up card
if (!isValid(here,length)) return false;
if (!remainsAt(here)) return false;
if (there===here) return false;
// must be a face-down card here; proceed...
var valHere = valueAt(here),
displayHere = cardset.display(valHere);
if (there === false) {
// no current face-up
there = here; //turn here face-up
} else {
// check match with face-up
if (cardset.match(valHere,valueAt(there))) {
// match; remove both:
removeAt(here);
removeAt(there);
if (_gui)
_gui.removeSoon([here,there]);
//optional: report match
console.log("Match!")
} else {
if (_gui)
_gui.hideSoon([here,there]);
}
//either way, turn face-up to face-down:
there = false;
}
if (_gui)
_gui.show(here,displayHere);
return displayHere;
}
// Make some functions public as instance methods:
this.reset = reset;
this.lift = lift;
this.faceupValue = faceupValue;
this.faceupWhere = faceupWhere;
this.remaining = remaining;
this.gui = gui;
this.size = size;
}//end ctor
// Private Functions shared by all boards:
// these could be placed inside ctor,
// but then they would be rebuilt for each instance
function isValid(where,length) {
return (typeof where === 'number')
&& (where%1 === 0)
&& (where>=0)
&& (where<length)
}
function shuffle(array) {
// Knuth-Fisher-Yates, modified from http://bost.ocks.org/mike/shuffle/
var end = array.length, temp, i;
// While there remain elements to shuffle…
while (end>1) {
// Pick a remaining element…
i = Math.floor(Math.random() * end--);
// And swap it with the current element.
temp = array[end];
array[end] = array[i];
array[i] = temp;
}
}
return Ctor;
})();