简体   繁体   中英

How can I create a while loop with many conditions in javascript?

I'm trying to create a poker program that will generate a hand of 5 random cards. One problem that I've run into is that the program will occasionally generate the same card twice.

THe best way I've thought of to fix this would be to implement a while loop that looks like this.

while (randFace == randFace2 && randSuit == randSuit2) || (randFace2 == randFace3 && randSuit2 == randSuit3) { 

randSuit2 = Math.round(Math.random()*3);                    
randFace2 = Math.round(Math.random()*13);   

}

This breaks the syntax of a while loop though and refuses to run.

Is there any way to create a while loop similar to the one above with many complex conditions... only one that's syntactically valid?

Thanks!

Yes, add more parenthesis.

while ((randFace == randFace2 && randSuit == randSuit2) || (randFace2 == randFace3 && randSuit2 == randSuit3))  {
    // Do whatever
}

A while loop will test everything in the parenthesis immediately following the while keyword. You can nest conditions infinitely within those parenthesis using more parenthesis or whatever operators you please, as long as whatever is in those parenthesis can be evaluated to true or false.

it looks like you're missing a parenthesis

while ((randFace == randFace2 && randSuit == randSuit2) || (randFace2 == randFace3 &&      randSuit2 == randSuit3)) { 

randSuit2 = Math.round(Math.random()*3);                    
randFace2 = Math.round(Math.random()*13);   

}

Just use parenthesis to group a condition, like this :

while( (randFace == randFace2 && randSuit == randSuit2) || (randFace2 == randFace3 && randSuit2 == randSuit3)) { 
randSuit2 = Math.round(Math.random()*3);                    
randFace2 = Math.round(Math.random()*13);   
}

It sounds to me like a XY problem , so notice that this answer doesn't reply to the question's subject but to the problem itself.

First, you should use Math.floor , because Math.round will give you a non-uniform distribution:

function randomInt(max) {
    return Math.floor(Math.random() * (max + 1))
} 

Then you have to store all this values somewhere, right? So why you don't use an object or an array? I would assume you're using a deck of 52 cards. If you have a convention like:

  • Hearts: index 0 - 12
  • Diamonds: index 13 - 25
  • Clubs: index 26 - 38
  • Spades: index 39 - 51

Then your "deck" representation is just an array of int:

var deck = [];
for (var i = 0; i < 52; i++)
  deck.push(i);

Now you can create a "playing deck" just shuffling the regular one:

// Using the Fisher Yates shuffle: http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

function shuffle(array) {
  var len = array.length;
  var shuffled = array.slice();

  while (len--) {
    random = randomInt(len + 1);
    // swap
    shuffled[len] = [shuffled[random], shuffled[random] = shuffled[len]][0];
  }

  return shuffled;
}

// creating a new, shuffled deck from the original
var playingDeck = shuffle(deck);

And use the playingDeck to actually distribute your card. Let's say you want to give the first 5 cards to a player1:

var player1Hand = playingDeck.splice(0, 5);

Then your player1Hand will be a five elements array, where the elements are token from the "top of the playing deck" (the first five elements). Therefore if you're querying now the playingDeck.length , will be 47 . You want to give other 5 cards to the player 2? Same code:

var player2Hand = playingDeck.splice(0, 5);

And if you want to shuffle the card in the middle of the game? Just shuffle the playingDeck and assign it to itself:

playingDeck = shuffle(playingDeck);

You could also draw a single card from the top:

var card = playingDeck.shift();

(Notice that in this case it's not a list of card – array - but a card itself – number.)

And basically use any Array methods you want, simulating a real deck.

As you can see it's a more natural way to deal with simulated cards, you don't have to concatenate many condition in your loop to draw some cards.

I would use the convention I mentioned at the beginning, but keep in mind that if you want to have a different representation of the card it's okay too: the method described still works and you don't have to change the code; only the array's value are different, so only the generation of the deck. For instance, you could have strings:

var deck = ["1H", "2H", /*etc*/, "10H", "JH", "QH", "KH", /* etc */];

Where the last letter is the suit, and the remains are the value of the card. Or you could actually use an object too:

var deck = [{"suit": "Hearts", "face": "1"}, /* etc */];

It really doesn't matter. What makes easier for you to deal with. But the rest of the approach will be still the same.

Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM