0

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)

Spidfire
  • 5,433
  • 6
  • 28
  • 36
  • 2
    Assign every card a running number instead of a sign. Then you could simply test the distance from one card to the next (on a sorted list). If that distance is > 1, you have no sequence. – Yoshi Jul 25 '12 at 09:43
  • BTW does h7 means 7 and st means t? I'm not aware of this game :P – Tamil Jul 25 '12 at 09:45
  • 1
    @Tamil h7 is "7 of hearts" and "st" is "Ten of spades" in his encoding. – RB. Jul 25 '12 at 09:51
  • I don't understand your algortihm. Which arrays do you want to match against each other? You have one of cards, the order array and 4 input array examples. – Bergi Jul 25 '12 at 10:22

4 Answers4

1

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

Community
  • 1
  • 1
Jacob George
  • 2,559
  • 1
  • 16
  • 28
0

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;
RB.
  • 36,301
  • 12
  • 91
  • 131
0

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?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

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/

nikoshr
  • 32,926
  • 33
  • 91
  • 105