0

I am relatively new to JavaScript and I am build a little app which randomly generates a card from a set of 52 cards (I stored all possibilities in an array). But I want to make sure that the same card can not be generated twice. I was not able to find a way to do so.

var cardType = ["A♠","2♠","3♠","4♠","5♠","6♠","7♠","8♠","9♠","10♠","J♠","Q♠","K♠"];

function generateCard()
{
var card = cardType[Math.round(Math.random() * (cardType.length - 1))];
}

The spade symbols are not actually in my array I just put it in for visibility.

4 Answers 4

3

Pre shuffle the array and pop one card at time, from the array

var cardType = ["A♠","2♠","3♠","4♠","5♠","6♠","7♠","8♠","9♠","10♠","J♠","Q♠","K♠"];

//shuffles array
cardType.sort(function() { return 0.5 - Math.random() });

function generateCard()
{    
    return cardType.pop();
}

When you get undefined it means you got all the cards

Sign up to request clarification or add additional context in comments.

6 Comments

Good answer, +1 from me
I'm not convinced by that sort helper function - it's using a non-deterministic comparator to an O(n log n) function, when a decent Knuth-Fisher-Yates shuffle will work in O(n) time.
to be perfectly honest, i just copied the function from css-tricks.com/snippets/javascript/shuffle-array cause performance doesnt matter when its 13 items and a one-off operation
@Dogoku find a better site - whoever wrote that doesn't know what they're doing.
@Dogoku FWIW, algorithm #1 on that page appears to be the correct Knuth shuffle, but the implementor deserves to be shot for using parseInt to round the random number!
|
3

Keep track of already generated cards, check to see if the newly generated card already exists, and if it does, generate a new card :

var already_generated = [];
var cardType = ["A♠","2♠","3♠","4♠","5♠"...];

function generateCard() {
    var card = cardType[Math.round(Math.random() * (cardType.length - 1))];

    if ( already_generated.indexOf(card) == -1 ) {
        already_generated.push(card);
    }else{
        if (already_generated.length < cardType.length) generateCard();
    }
}

Older browsers will need a shim for Array.indexOf, which can be found at MDN

As a sidenote, the original array could be sliced, but this just seems easier unless you for some reason have to change the original array !

9 Comments

If you generate all the cards and call generating fn, your execution will get into trouble
@OzrenTkalčecKrznarić - Yes it will, I didn't add a check for that, as it seemed rather obvious, but I'll add it now.
the fundamental problem, with this code (and the one posted in the question) is that you define your array inside the function, meaning it's reset every time the function is called, meaning you have to keep track of what cards you already have. see my answer for a much more efficient solution
@Dogoku - If it floats your boat, I'll move it for you.
I think this algorithm is horrible. It'll work OK for a few cards, but it'll be really inefficient the more cards you generate. Being recursive it could even cause stack overflow errors.
|
0

I would just:

  • make your ordered set of cards (i.e. a "pack")
  • use an effective shuffling algorithm to make a "deck" from the "pack"
  • use deck.pop() to just take successive cards from that deck

Having an abstraction to represent a deck of cards will likely prove useful as you develop your application. It might seem like overkill now, but it'll be worth it in the long run. Done properly, it should be re-usable in other projects too.

Comments

-2

Use the delete keyword.

Sample:

var x = [1,2,3];
delete x[1]; // delete element '2'
for (i in x) { 
  console.log(x[i]); // outputs 1, 3
}

5 Comments

But the length is still the same, messing up the random card generation.
bad answer on two counts - delete on an array will just make the element undefined, not remove it, and you shouldn't use for ... in on arrays, only on objects.
I know where you are heading, bit please give OP a real example
for (var i in x) as well, or you're not declaring i.
The delete operator removes a property from an object. That's it. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… for more info.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.