0

I'm working on an applet program that displays 10 random cards from a deck of 52 cards. I used a for loop to cycle through 10 cards and give them a random card from the images I downloaded. When I compile and run the applet, I sometimes get repeats. Can someone give me any pointers on how I could go about this without repeats?

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color; 
import java.util.Random;

public class Unit12Assignment1 extends Applet
{ 
     Image card[] = new Image[10];

public void init()
{
    String deckImages[] = {"cards_gif/c1.gif", "cards_gif/c2.gif", "cards_gif/c3.gif", "cards_gif/c4.gif",
        "cards_gif/c5.gif", "cards_gif/c6.gif", "cards_gif/c7.gif", "cards_gif/c8.gif", "cards_gif/c9.gif", 
        "cards_gif/c10.gif", "cards_gif/cj.gif", "cards_gif/ck.gif", "cards_gif/cq.gif",
        "cards_gif/s1.gif", "cards_gif/s2.gif", "cards_gif/s3.gif", "cards_gif/s4.gif",
        "cards_gif/s5.gif", "cards_gif/s6.gif", "cards_gif/s7.gif", "cards_gif/s8.gif",
        "cards_gif/s9.gif", "cards_gif/s10.gif", "cards_gif/sj.gif", "cards_gif/sk.gif",
        "cards_gif/sq.gif", "cards_gif/d1.gif", "cards_gif/d2.gif", "cards_gif/d3.gif",
        "cards_gif/d4.gif", "cards_gif/d5.gif", "cards_gif/d6.gif", "cards_gif/d7.gif",
        "cards_gif/d8.gif", "cards_gif/d9.gif", "cards_gif/d10.gif", "cards_gif/dj.gif",
        "cards_gif/dk.gif", "cards_gif/dq.gif", "cards_gif/h1.gif", "cards_gif/h2.gif",
        "cards_gif/h3.gif", "cards_gif/h4.gif", "cards_gif/h5.gif", "cards_gif/h6.gif",
        "cards_gif/h7.gif", "cards_gif/h8.gif", "cards_gif/h9.gif", "cards_gif/h10.gif",
        "cards_gif/hj.gif", "cards_gif/hk.gif", "cards_gif/hq.gif"};

    for( int i = 0; i < card.length; i++ )
    {
        int x = (int)(Math.random() * 52);
        card[i] = getImage(getDocumentBase(), deckImages[x]);
    }

}

public void paint(Graphics g)
{
    setBackground( Color.green );
    int x = -60;

    for( int i = 0; i < card.length / 2; i++ )
    {
        x = x + 90;
        g.drawImage(card[i], x, 30, this);
    }

    x = -60;

    for( int i = card.length / 2; i < card.length; i++ )
    {
        x = x + 90;
        g.drawImage(card[i], x, 150, this);
    }
}
}
Peter O.
  • 32,158
  • 14
  • 82
  • 96
tedclark72
  • 77
  • 1
  • 6

3 Answers3

2

There are various posibilities. You can detect duplicities and in such a case generate new indices until you get a unique one. Other option can be to shuffle an array of indices and then take the first 10. Be creative, it is not a hard task.

Another Possibility:

// TODO initialize this to -1
int chosen[] = new int[10];
    for( int i = 0; i < card.length; i++ )
    {
      int x = (int)(Math.random() * 52);

      for(int j=0; j< chosen.length; j++)
        if(x==chosen[j])
        {
          x++;
          j=0;
          if(x>51)
            x=0;
        }
        card[i] = getImage(getDocumentBase(), deckImages[x]);
        chosen[i] = x;
    }

This is not strictly random, but you can be sure that it does end even if you meet a random number generator that is implemented like: return 42;

1

Due to the random generator the cards get selected. To avoid duplicates you can store previous generated numbers of that round, too. So you can enforce the generator to pick as long a new number since it chooses a new one by comparing the picked number with the previous ones.

j0j0j0
  • 97
  • 2
  • 8
-1

It is called Fisher-Yates shuffle (or Fisher-Yates-Knuth shuffle). Basically, equivalent to selecting 6 winning lottery balls out of 59. Link to description http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

Pseudocode (closer to C++, hope I don't make a lot of mistakes)

void swap(int& a, int& b) {
    int t = a;
    a = b;
    b = t;
}

// in-place shuffle
void shuffle(int cards[], int n) { // sample n non-repeating cards from the deck
    int last_index = 51;
    for(int k = 0; k != n; ++k) {
        int idx = random(last_index); // random shall produce number from 0 to last_index inclusively
        if (idx != last_index) {
            swap(cards[idx], cards[last_index]);
        }
        --last_index;
    }
}

int cards[52];  

for(int k = 0; k != 52; ++k) {
    cards[k] = k;
}

shuffle(cards, 10);

// now last 10 positions in cards array are sampled cards 
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • Shouldn't advocate implementing your own when Java provides `Collections.shuffle()`. – pjs May 18 '15 at 00:57
  • @pjs `Collections.shuffle()` is clearly wrong answer. It shuffles ALL cards simultaneously, which is NOT what @Tedion asked. Please return back my browny points and next time READ CAREFULLY what's asked and what's answered, thank you – Severin Pappadeux May 18 '15 at 20:39
  • You first line advocates Fisher-Yates shuffle, and that's exactly what `Collections.shuffle()` implements. If you don't want the whole set shuffled, then [Floyd's subset selection](https://eyalsch.wordpress.com/2010/04/01/random-sample/) is the better choice. – pjs May 18 '15 at 21:17
  • @pjs No, it is not. If there would be an interface Collection.partial_shullfe(int n), that would be good answer. You were asked to select subset of the whole set, and your proposed answer is to shuffle whole set because there is a handy function. Please, next time READ CAREFULLY what's asked and what's answered, thank you. – Severin Pappadeux May 19 '15 at 00:14
  • Try reading carefully yourself. The question was in Java, and a "solution" not in Java that you "hope" doesn't contain many mistakes is a crappy answer. My proposed answer (in the linked question) is to use Floyd's algorithm, and in the language being asked about. – pjs May 19 '15 at 01:02