Nick
Nick

Reputation: 3

How to stop getting the same number using random

I made this for class to get 7 random cards. Now want to modify it to get 21 random cards that are not repeating. I am trying to build another program that is a card guessing game. I have modified it to give me 21 cards but I always get repeating cards. I was thinking maybe use a seed. But I dont know enough about them to use them effectively.

import java.util.*;

public class SuchaDeal
{
  public static void main(String[] args)
  {
    Random generator = new Random();       
    int i = 1;   
    String cardSuit;
    int card;    // a card number from 0 to 51
    int cardNum;
    String cardRank = "";

    while (i <= 21)   // loop through 21 times
    {
      card = generator.nextInt(52);   // Returns 0 – 51 
      cardNum = card % 13;    // number between 0-12 for the rank    
      //classify card into suits here

      if ( card  <= 12) 
      {
        cardSuit = " Clubs ";  
      }
      else if ( card  >= 13 && card <= 25  )
      {
        cardSuit = " Diamonds "; 
      }
      else if ( card  >= 26 && card <= 38)
      {
        cardSuit = " Spades "; 
      }
      else
      {
        cardSuit = " Hearts ";
      }

      //name the ranks
      switch (cardNum)
      {
        case 0: cardRank = "Ace";    break;
        case 10: cardRank = "Jack";  break;
        case 11: cardRank = "Queen"; break;
        case 12: cardRank = "King";  break; 
        default: cardRank = "" + (cardNum + 1);
      }
      //print the results   
      System.out.println("Card " + i + " is a " + cardRank + (" of ") + cardSuit);

      i++; // increment the counter
    }
  }
}

I know it is not the most pretty code but this is one of the first programs that I am going to write in java.

Upvotes: 0

Views: 257

Answers (2)

Bricky
Bricky

Reputation: 2745

If you want to use this approach, you should increment i only when the card you've made is unique, perhaps storing the created cards in some array, and then checking if the newly generated card is already present, discarding it and re-running the loop/calculation if it is present.

However, if you're going to build a full deck, this approach is pretty naive - because the likelihood of randomly producing a unique card gets lower and lower as the number of cards already produced gets higher and higher. (Once you have 51 cards, you'll likely have to run this loop upwards of 52 times before you randomly generate the only remaining card)

Instead, you could build out a deck of 52 cards programmatically, or as a hard-coded array, and then use a shuffling algorithm like Fisher-Yates:

 static void shuffleArray(int[] ar)
  {
    // If running on Java 6 or older, use `new Random()` on RHS here
    Random rnd = ThreadLocalRandom.current();
    for (int i = ar.length - 1; i > 0; i--)
    {
      int index = rnd.nextInt(i + 1);
      // Simple swap
      int a = ar[index];
      ar[index] = ar[i];
      ar[i] = a;
    }
  }

Now, you have a 'full deck' that's been randomly shuffled. Then, take the first 21 cards using Arrays.copyOfRange:

Arrays.copyOfRange(cardArray, 0, 20);

Upvotes: 2

Adrian Shum
Adrian Shum

Reputation: 40066

As suggested in comment, you should do a deck shuffling instead of generating individual cards by random.

Another suggestion I will give is to properly model a card and suit.

pseudo-code:

enum Suit {
    SPADE, HEART, DIAMOND, CLUB
}

class Card {
    private Suit suit;
    private int number;  // 1 = Ace... 13 = King
    Card(Suit suit, int number) {....}

    // Getters, toString(), equals(), hashCode()
    // no setters, as this is good candidate for immutable class
}

Main logic

List<Card> deck = new ArrayList<>();
for (suit : Suit.values) {
    for (num = 1 to 13) {
        deck.add(new Card(suit, num));
    }
}
// now you have a deck of 52 cards

// shuffle the decek
Collections.shuffle(deck);

// take first 20 card from deck, by whatever way you like

Upvotes: 0

Related Questions