1

I'm trying to generate a card deck for the game SET, or, for those who don't know what that is, I'm trying to fill an array with unique elements of the form [a, b, c, d], where 0 <= a, b, c, d <= 2 (81 elements). So, I want [[0, 0, 0, 0,], [0, 0, 0, 1], ... , [2, 2, 2, 2]] (the order doesn't matter). This is the code I have so far:

var deck = [],
    count = [0, 0, 0, 0];
for (var i = 0; i < 81; i++) { // go through all combos
    deck.push(count); // append the current modification of count to deck
    // increment count by 1, carrying "tens" if necessary
    for (var j = 3; count[j] === 2; j--) {
        // if the "digit" is 2, make it 0 since it overflows
        count[j] = 0;
    }
    // j is the first "digit" of count that isn't already 2, so we add 1 to it
    count[j]++;
}

Instead, what this seems to do is fill the deck array with the last modification of count; if the upper bound on i is 81, this is [0, 0, 0, 0] since it rolls over all the way around, and if you change the bound to anything lower it will respond accordingly. Why does this happen? What mistake have I made?

Bluefire
  • 13,519
  • 24
  • 74
  • 118
  • Because you push the same array to deck 81 times, so alter any of them's value will reflect to all in that array, try use `count = count.slice()` to create a new one from previous each iteration. – fuyushimoya Aug 04 '15 at 03:18

1 Answers1

1

Just remember that you're pushing the same count into deck each iteration, which means any alternation to count will reflect to all other counts in deck, as they're all reference to same array

You can use .slice to clone a new array with same value from previous count.

var deck = [],
    count = [0, 0, 0, 0];
for (var i = 0; i < 81; i++) { // go through all combos

    // Clone a new array from previous one.
    count = count.slice();


    deck.push(count); // append the current modification of count to deck
    // increment count by 1, carrying "tens" if necessary
    for (var j = 3; count[j] === 2; j--) {
        // if the "digit" is 2, make it 0 since it overflows
        count[j] = 0;
    }
    // j is the first "digit" of count that isn't already 2, so we add 1 to it
    count[j]++;
}
console.log(deck);
fuyushimoya
  • 9,715
  • 3
  • 27
  • 34
  • How come it's the same count though? I modify it every time. I thought JS didn't reference objects like that (like Java etc)? – Bluefire Aug 04 '15 at 03:26
  • 1
    In your post, the item you pushed into the `deck` and the `count` are reference to same `array`, so when you modify either of them, another will reflect the change. So you need to make the count reference to a different array each iteration, then it's modification will not reflected by items in `deck`, as they're now reference to different array now. – fuyushimoya Aug 04 '15 at 03:45
  • You can find more from http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – fuyushimoya Aug 04 '15 at 03:46
  • Or simply use `count=[]` to reinitiate an empty array. – Joy Aug 04 '15 at 04:13