简体   繁体   中英

Better way than “switch” in javascript

I am very new to javascript and I have a little problem.

As my first "project", I want my program to give me a random poker card. Nothing to great, but I'm trying to figure out an elegant way to do it. By now my only idea is to give a random number between 1 and 52 a specific card, but there got to be a better way.

Here is my current code :

function newCard() {
var card_id = document.getElementById("card_id");
var c1 = Math.floor(Math.random() * 52) + 1;
switch(c1) {
    case 1:
        c1 = "ace of spades";
        break;
    case 2:
        c1 = "2 of spades";
        break;
    case 3:
        c1 = "3 of spades";
        break;  


    // ...I think you get the idea here


         } 

card_id.innerHTML = c1;
}

Do you have a hint for me, how to make this quicker/better ?

 function newCard() { // Pick from 0 to 51, not 1 to 52 var cardId = Math.floor(Math.random() * 52); var ranks = ["ace", "2", "3", "4", "5", "6", "7", "8", "9", "ten", "jack", "queen", "king"]; var suits = ["spades", "hearts", "diamonds", "clubs"]; // % is the modulo operator, so 0 => 0, 1 => 1, ... 12 => 12, 13 => 0, 14 => 1, ... // Math.floor(cardId / 13) gets the suit (0, 1, 2, 3) return ranks[cardId % 13] + " of " + suits[Math.floor(cardId / 13)]; } for (var i = 0; i < 10; i++) { console.log(newCard()); } 

UPDATE

Because this has led to a bit of discussion around dealing from a non-infinite deck (not repeating cards), here's a typical solution that produces a full deck, shuffles it, and then deals out the cards. cardIdToEnglish is basically the above solution. shuffle is a Fisher-Yates shuffle . Note that using pop deals from the end of the deck, which may seem odd, but also note that this is irrelevant. :-)

 function cardIdToEnglish(id) { var ranks = ["ace", "2", "3", "4", "5", "6", "7", "8", "9", "ten", "jack", "queen", "king"]; var suits = ["clubs", "diamonds", "hearts", "spades"]; return ranks[id % 13] + " of " + suits[Math.floor(id / 13)]; } function shuffle(arr) { // Fisher-Yates shuffle var n = arr.length; for (var i = 0; i < arr.length - 2; i++) { var j = Math.floor(Math.random() * (n - i)) + i; // Swap a[i] and a[j] var temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } function newDeck() { var deck = []; for (var i = 0; i < 52; i++) { deck.push(i); } shuffle(deck); return deck; } var deck = newDeck(); for (var i = 0; i < 52; i++) { var card = deck.pop(); console.log(cardIdToEnglish(card)); } 

I would create an array of all the cards as objects of the suits and ranks (using nested forEach loops for ease - iterating over the suits and ranks arrays) and then use the random number to generate a card id. This would then give the rank and suit of that card. Then i remove the card from the deck - to prevent it from being dealt twice and decrement the count of available cards). Doing it this way means that the selected card is random and not duplicated. I also put in a button that resets it all and allows further dealing of the 10 card hand.

 var deck = []; function setCards(){ var suits = ["Spades", "Hearts", "Diamonds", "Clubs"]; var ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "Ten", "Jack", "Queen", "King"]; //creates an array of card objects that have the rank and suit as properties //eg: deck = [ {suit: "Spades", rank: "Ace"}, {suit: "Spades", rank: "2"},...etc] suits.forEach(function(suit){ ranks.forEach(function(rank){ var card = {}; card.suit = suit; card.rank = rank; deck.push(card); }); }); } function newCard(count) { //decreases the count of the deck since some cards have already been dealt var remainingCards = 52 - count; var index = Math.floor(Math.random() * remainingCards); var card= deck[index]; deck.splice(index,1); //removes the selected card from the deck return card; } function dealCards() { document.getElementById('hand').innerHTML = '<dt>My Hand </dt>'; setCards(); for (var i = 0; i < 10; i++) { var card = newCard(i); document.getElementById('hand').innerHTML += '<dd>'+ card.rank + ' of ' + card.suit + '</dd>'; } } 
 <button type="button" onclick="dealCards()">Deal New Hand</button> <hr/> <dt id = "hand"></dt> 

Here's an idea:

var deck = ['ace of spades', 'two of spades', 'three of spades', '...']; 
// and so on, all 52 cards
var rand = Math.floor(Math.random() * 52);

console.log(deck[rand]); // will print a random card from the deck

Optionally, you could also remove the drawn card from the deck, if you'd like to continue "the game".

deck.splice(rand, 1);

After this, you would need to regenerate the random for a smaller deck:

rand = Math.floor(Math.random() * deck.length); 

That's an interesting problem. Here is what I'm thinking... Number cards go from 2 to 9. If we continue to use integers as card values, jack, queen, king, and ace could be represented as 10, 11, 12, and 13, respectively.

But of course, we have four of each of those values in the form of the four suits. A quick google search reveals that in English speaking countries the relative value of the suits could be ranked from lowest to highest as clubs, diamonds, hearts, and spades.Therefore, we could say that 2 - 13 are the clubs, 14 - 25 the diamonds, 26 - 37 the hearts, and 28 - 49 the spades. Following this formula, your random number should be between 2 and 49.

So with this in mind, you could write a function that does some math to determine the exact card based on the generated number. Obviously, you cannot deal the same card twice, so once a number is generated, it should be stored in an array of dealt cards. Each time you generate a number you will want to check to see if that number is in the dealt cards array. If it is, you will want to generate another number. I have an idea for an approach for setting up and checking this array. If you think my idea is worth pursuing, let me know and I'll add it to this answer.

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