1

I am having an issue with the following code that simulates a card deck.

The deck is created properly (1 array containing 4 arrays (suits) containing 13 elements each (face values)) and when I use the G.test(); function it is correctly pulling 13 random cards but then returns 39x "Empty" (A total of 52).

I hate to ask for help, but I have left the problem overnight and then some and I still cannot find the reason that this is happening. I appreciate any and all insight that can be offered.

var G = {};
G.cards = [[], [], [], []];

G.newCard = function(v) { //currently a useless function, tried a few things
    return v;
};

G.deck = {    
    n: function() { //new deck
        var x; var list = [];
        list.push(G.newCard("A"));

        for (x = 2; x <= 10; x += 1) {
            list.push(G.newCard(x.toString()));
        }

        list.push(G.newCard("J"), G.newCard("Q"), G.newCard("K"));

        for (x = 0; x < G.cards.length; x += 1) {
            G.cards[x] = list;
        }
    },

    d: function() { //random card - returns suit & value
        var s; var c; var v; var drawn = false; var n;

        s = random(0, G.cards.length);
        c = random(0, G.cards[s].length);
        n = 0;

        while (!drawn) {
            if (G.cards[s].length > 0) {
                if (G.cards[s][c]) {
                    v = G.cards[s].splice(c, 1);
                    drawn = true;
                } else {
                    c = random(0, G.cards[s].length);
                }
            } else {
                s = (s + 1 >= G.cards.length) ? 0 : s + 1;
                n += 1;
                console.log(s);
                if (n >= G.cards.length) {
                    console.log(n);
                    return "Empty";

                }
            }
        }
        return {s: s, v: v[0]};
    },
}; //G.deck

G.test = function() {
    var x; var v;
    G.deck.n();
    for (x = 0; x < 52; x += 1) {
        v = G.deck.d();
        console.log(v);
    }
}; 
Deminal
  • 13
  • 2
  • This is the random function, forgot to include: random = function(min, max) { return Math.floor(min + Math.random() * max); }; – Deminal May 20 '17 at 23:21
  • That random function might be part of the problem - see this answer: http://stackoverflow.com/a/1527820/3586783 – pacifier21 May 20 '17 at 23:26
  • Nope! Of course after I give in and post, I figure out the issue... When I am splicing from the G.cards[s], it isn't just splicing S it's splicing from all 4 arrays at once... I still don't understand the why but at least I have somewhere to start looking. – Deminal May 20 '17 at 23:32
  • Ahh, but to be fair that random function would've been a problem, if my min hadn't been 0s. Thanks for catching that =D – Deminal May 20 '17 at 23:33
  • I was just going to comment about that. Yes - you are assigning the same array reference to all suits. You will need to copy the list into each G.cards so each list is a unique reference. You want something like this: G.cards[x] = list.slice(); – pacifier21 May 20 '17 at 23:33
  • Also I see that if `G.cards[s].length > 0` is false you move `s` to the next suit but do not randomize again to take new value for `c`. – Todor Simeonov May 20 '17 at 23:33

2 Answers2

0

Replace

for (x = 0; x < G.cards.length; x += 1) {
    G.cards[x] = list;
}

with

for (x = 0; x < G.cards.length; x += 1) {
    G.cards[x] = list.slice();
}

as this prevents all elements of G.cards[x] binding to the same (single) array instance.

If all elements bind to the same instance, mutating one element equals mutating all elements. list.slice() creates a new copy of list and thus a new array instance to prevent the aforementioned issue.

le_m
  • 19,302
  • 9
  • 64
  • 74
0

I won't go through your code, but I built a code that will do what you wanted. I only built this for one deck and not multiple deck play. There are two functions, one will generate the deck, and the other will drawn cards from the deck, bases on how many hands you need and how many cards you wanted for each hand. One a card is drawn, it will not be re-drawn. I might publish a short article for how a card dealing program work or similar in the short future at http://kevinhng86.iblog.website.

function random(min, max){
   return Math.floor(Math.random() * (max - min)) + min;
}


function deckGenerate(){
    var output = [];
    var face = {1: "A", 11: "J", 12: "Q", 13: "K"};
    // Heart Space Diamond & Club;
    var suit = ["H", "S", "D", "C"];
    // Delimiter between card identification and suit identification.
    var d = "-";

    for(i = 0; i < 4; i++){
        output[i] = [];
        for(ind = 0; ind < 13; ind++ ){
           card = (ind + 1);
           output[i][ind] = (card > 10) || (card === 1)? face[card] + d + suit[i] : card.toString() + d + suit[i];
        }
     }
     return output;
}

function randomCard(deck, hand, card){
    var output = [];
    var randS = 0;
    var randC = 0;
    if( hand * card > 52 ) throw("Too many card, I built this for one deck only");

    for(i = 0; i < hand; i++){
        output[i] = [];
        for(ind = 0; ind < card; ind++){
            randS = random(0, deck.length);
            randC = random(0, deck[randS].length);
            output[i][ind] = deck[randS][randC];
            deck[randS].splice(randC,1);
            if(deck[randS].length === 0) deck.splice(randS,1);
        }
    }

    document.write( JSON.stringify(deck, null, 2) );

    return output;
}


var deck = deckGenerate()
document.write( JSON.stringify(deck, null, 2) );

document.write("<br><br>");

var randomhands = randomCard(deck, 5, 8);

document.write("<br><br>");
document.write("<br><br>");


document.write( JSON.stringify(randomhands, null, 2) );
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Kevin Ng
  • 2,146
  • 1
  • 13
  • 18