I'm trying to create an Javascript card game but i need to match to 4 following up numbers in a list. But i always create some insane layered loop thing like:
cards = [{card:'h7'},{card:'c8'},{card:'h9'},{card:'st'}]
var sorted = ['7','8','9','t','j','q','k','a']
var found4 = false
for(var i =0;i < 5;i++){
var found = 0;
for(var j = 0;j < 4;j++){
for(var c in cards){
if(cards[c].card.charAt(1) == sorted[i+j]){
found++
}
}
}
if(found == 4){
found4 = true
}
}
Are there better ways to match an array?
some input examples:
'7','8','9','t' => true
'j','q','k','a' => true
'7','8','k','a' => false
'j','k','7','a' => false
(the input is not sorted)
You can write a prototype method for Array (You can refer to the following post) as
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] == obj) {
return i;
}
}
return false;
}
var sorted = ['7', '8', '9', 't', 'j', 'q', 'k', 'a']
function check(arr) {
index = sorted.contains(arr[0])
if (index === false) {
return false;
}
count = 1
for (var i = 1; i < 4; i++) {
sortedIndex = index + i > sorted.length ? index + i - sorted.length : index + i
if (sorted[sortedIndex] == arr[i]) count++;
}
if (count == 4) {
return true;
}
return false;
}
console.log(check(['j','q','k','a']))
you can see it work here
I would have separate fields for suit and value. This then makes it much easier to test if the values are in order. Note that the code below does not include range checking, or other validation, but I'm assuming that is taken care of.
// Suit is [c]lubs, [d]iamonds, [h]earts, or [s]pades
// Value is from Ace (1) to King (13). Jack is 11, and Queen is 12.
cards = [
{suit:'h', value: 7 } // 7 of hearts
{suit:'c', value: 8 } // 8 of clubs
{suit:'h', value: 9 } // 9 of hearts
{suit:'s', value: 10 } // Ten of spades
{suit:'s', value: 11 } // Jack of spades
]
if (cards.length <= 1)
{
// Having 0 or 1 cards means they are, by definition, in order.
return true;
}
// Test each card (starting with the second) to ensure that it is
// 1 greater than it's predecessor.
var previousValue = cards[0].value;
for(var i = 1; i < cards.length; i++){
if (previousValue + 1 != cards[i].value)
{
// This card is not the next card in sequence, so
// the hand is not in order.
return false;
}
}
return true;
First, your algorithm should work on all arrays (no fixed lengths etc), so lets get chars to find:
var tofind = cards.map(function(c){return c.card.charAt(1);});
When all your pieces have length one, there is a very simple function to help you:
return sorted.join("").indexOf(tofind.join(""))!=-1;
However, I don't understand your approach completely. This loop:
for (var c in cards)
if (cards[c].card.charAt(1) == sorted[i+j])
found++
seems odd to me. First, cards
is an array, so don't use a for-in-loop. But if you search all cards for the current letter you want to match, how does this have anything to do with order?
A possible solution using Underscore and keeping your data structure
function test(seq,expected) {
var res=isSequence(seq);
if (res===expected)
console.log( seq.join(',')+" : success");
else
console.log( seq.join(',')+" : fail");
}
function isSequence(seq) {
var sorted = ['7','8','9','t','j','q','k','a'], l=seq.length, i, ix;
if (l===0) return true;
ix=_.indexOf(sorted, seq[0]);
if (ix===-1) return false;
if (ix>sorted.length-l) return false;
for (i=1;i<l;i++) {
if ( sorted[ix+i]!==seq[i] )
return false;
}
return true;
}
var cards = [{card:'h7'},{card:'c8'},{card:'h9'},{card:'st'}]
test( _.map(cards, function(obj) {
return obj.card.charAt(1);
}), true );
test(['7','8','9','t'] , true);
test(['j','q','k','a'] , true);
test(['7','8','k','a'] , false);
test(['j','k','7','a'] , false);
And a Fiddle http://jsfiddle.net/KDrDy/2/