2

Im learning some javascript and have hit a stumbling block.. I would like to select 2 random values from my array and save them into a variable (which will be another array i guess) called Deal, i can get one random value but not 2.. My code is as follows

var deckOfCards = []; //declaring an empty array to put Cards into later

function Card(name, value, altValue) { //function that defines a card object ( key part is "this")
this.cardName = name;
this.cardValue = value;
this.cardAltValue = altValue || false;
}

var suits = ['Hearts', 'Diamonds', 'Spades', 'Clubs'];
var values = ['Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King'];

for(var i in suits) //loops through each of the suits
{
 for(var j in values) { // loops through each of the cards for the suit

if(values[j] != 'Ace') {//j is the index within the array,
    var cardValue = parseInt(j, 10) + 1; 
    if(cardValue > 10) cardValue = 10;
    deckOfCards.push(new Card(values[j] +' of ' +suits[i], cardValue));//adding   a new card object to deckOfCards
} else {
    deckOfCards.push(new Card(values[j] +' of ' +suits[i], 1, 11));// adding alternate value to deckOfCards
}

   }

  }


var Deal = deckOfCards[Math.floor(Math.random()*deckOfCards.length)];;
console.log(Deal);

Could anyone give me a pointer on this please

Thanks

2
  • How can you put two random values in one variable? Maybe you should make it an array. Commented Oct 29, 2013 at 15:31
  • yes sorry that's what i meant, i will amend question Commented Oct 29, 2013 at 15:32

5 Answers 5

2
function randomCard(deck, numToExtract) {
    var extracted = [];
    for (var i = 0; i < numToExtract; i++){
        extracted.push(deck.splice(Math.floor(Math.random()*deckOfCards.length, 1));
    }
    return extracted;
}

The return value will be an array of cards extracted from the deck, and the deck array will have those cards taken out. You will need to keep track of where the cards are and make sure none 'disappear'.

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

Comments

2

You might consider shuffling the entire deck of cards (randomize all 52 cards), and then dealing becomes simply pulling the top card from the deck.

  • Declare an array of all cards, deckOfCards[], define to list of cards,
  • Declare a shuffle of all cards, ShuffleDeck[]
  • Randomize picking all cards from deckOfCards[], copied into ShuffleDeck[]
  • The deal becomes pulling the top card from ShuffleDeck

An observation that might help is that the shuffled deck only needs to have an index into the defined deckOfCards, so it is just a randomized set of values 0..51 (or 1..52 as you prefer).

//define your cards
deckOfCards[] = ... //left up to you

//define Dealt[], to make checking whether already shuffled, dealt
card = 0 //or 1, however you prefer
while (card<52) {
    Dealt[card] =0; card++;
}


//Shuffle
card = 0 //or 1, however you prefer
while (card<52) {
    //try to pick a card not yet shuffled
    pick = Math.floor(Math.random()*deckOfCards.length);
    while (Dealt[pick]) { //used, pick again
        pick = Math.floor(Math.random()*deckOfCards.length);
    }
    Dealt[card] =1; //used
    ShuffleDeck[card] =pick; card++;
}

//now dealing becomes simply
top=0
//define a function to deal a card
var deal = function() {
    if( !(top<52) ) {
        return -1; //or, handle error here
    }
    result = top;
    top++;
    return result; //work with indices
    //or
    //return deckOfCards[ShuffleDeck[result]];
}
carddealt = deal();

//deal two cards to a Hand,
Hand[player].push( deal() );
Hand[player].push( deal() );

//suppose you want to deal four hands, five cards each
round = 0;
while (round < 5 ) {
    hand = 0;
    while (hand < 4 ) {
        Hand[hand].push( deal() );
    }
}

Alternately, you could drop each card dealt form the shuffled[] as you deal it.

1 Comment

If you implement Fisher-Yates correctly, you don't even need to shuffle the entire array. You could stop at the nth element and elements 0 to n-1 would be randomly selected from the array.
1

You've got a couple choices. You can either just call the same random function against the full deck a second time, then ensure that the second value is different from the first (with a while loop), or you can actually remove the card from the deck the first time, using something like splice, then you can keep calling that until the deck is empty.

The splice option is probably the better one.

12 Comments

I'd say iterating until hitting a different index would actually be better. OP will probably want to use the deck again, and modifying the array would therefore be a pain. Also, even if there's only 2 cards the chance of needing to repeat 10 times is less than 1%. For more than 2 cards the probability of needing to repeat at all decreases dramatically.
would love to see an example of what you mean Zong Zheng Li
@ZongZhengLi The difference is actually pulling from the deck represents reality a little better - you don't have to keep track of which cards have been removed, and you can easily count the number of cards remaining. You can just rebuild the deck with every new hand, since that's a very easy and cheap routine.
@JoeEnos would you mind providing an example please, good explanation but just cannot visualize what is going on, thanks
@JoeEnos Exactly, which is why I advocated the iteration method. If we really wanted to do it properly, we would implement a shuffle algorithm aka Fisher-Yates. It's super simple, can shuffle the entire array in just one pass, and in fact you can stop it at any point and the first n elements will be randomly selected from the array. Much more efficient than O(n^2) rebuilding arrays or O(birthday problem) of iteration.
|
1

Try this:

var Deal = deckOfCards[Math.floor(Math.random()*deckOfCards.length)];
var Deal2 = deckOfCards[Math.floor(Math.random()*deckOfCards.length)];
while (Deal2.equals(Deal)) { // if you want Deal and Deal2 have to different
    Deal2 = deckOfCards[Math.floor(Math.random()*deckOfCards.length)];
}

You need to implement the equals function as well.

function Card(name, value, altValue) {
    this.cardName = name;
    this.cardValue = value;
    this.cardAltValue = altValue || false;

    equals = function(otherObject) {
        return (otherObject.cardName == this.cardName && otherObject.cardValue == this.cardValue && otherObject.cardAltValue == this.cardAltValue)
    }
}

6 Comments

oh so rather than pull out 2 values in same variable, have a variable for each card?
also any reason why your using == as opposed to === which is more strict, or is it not necessary with this example?
@Richlewis you cannot use == nor ===, I have updated my answer, check it out.
This is quite messy, and you've added a bunch of other logic. Just compare the index for equality.
If you want to pull out 2 values in same variable, you will need an array.
|
1
var cardsHeld = {};
for( var x = 0; x < 2; x++ ) {
    var newCard = deckOfCards[Math.floor(Math.random()*deckOfCards.length)];
    //If Not found within current CardsHeld Obj, Append.
    if ( !cardsHeld.hasOwnProperty( newCard.cardName )) {
        cardsHeld[newCard.cardName] = newCard;
    }
}

console.log( cardsHeld );
/**
 * Prints:
 *    Object
 *       Five of Spades: Card
 *       Two of Hearts: Card
 */

Fiddle: http://jsfiddle.net/MguBJ/1/

Comments

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.