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
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
6 Comments
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.parseInt to round the random number!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
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
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
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.for (var i in x) as well, or you're not declaring i.