0

I am making a card game where each card should appear, but only once. I have seen some other solutions but can't apply them to my game.

Here is my code

int max = 32;
int min = 1;
Random r = new Random();
int number = r.nextInt(max - min + 1) + min;
String myString = String.valueOf(number);

final ImageView imgTable = (ImageView) findViewById(R.id.imageView2);

if (myString.equals("1")) {

    final Bitmap card1 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz7);
    imgTable.setImageBitmap(card1);
}
if (myString.equals("2")) {

    final Bitmap card2 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz8);
    imgTable.setImageBitmap(card2);
}
Matrosov Oleksandr
  • 25,505
  • 44
  • 151
  • 277
  • Shuffling and then iterating through the shuffled deck is the obvious solution. What's your objection to using it? – pjs Aug 23 '16 at 13:57

4 Answers4

0

You're doing things the hard way, trying to make them randomly. Instead, make them sequentially then shuffle the deck. Let's say you have 52 cards. Make an array holding the values 0...51 in order. Then you can shuffle by doing

for(int i=0; i<52;i++) {
   int toSwap= Random.nextInt(52);
   swapIndices(cardArray, i, toSwap);
}

where swapIndices swaps the cards at the 2 indices in the array. That will shuffle the deck and give you a random arrangement.

ddb
  • 2,423
  • 7
  • 28
  • 38
Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • This is a biased shuffle, see http://stackoverflow.com/a/859264/2166798 for explanation. – pjs Aug 23 '16 at 14:02
0

A long time ago I created a card game too.

I used simple logic like this for shuffling card in deck

int arr[] = new int[52] //card have 52 card without joker
for(int i=1;i<=52;i++){
    arr[i-1] = i; // add number 1-52 to arr
}
Random r = new Random();
for(int i=0;i<52;i++){
    int number1 = r.nextInt(52);
    int number2 = r.nextInt(52);
    int tmp = arr[number1];
    arr[number1] = arr[number2];
    arr[number2] = tmp;
} // this looping for shuffle the array

later you can print or use the array from index 0

aiwiguna
  • 2,852
  • 2
  • 15
  • 26
  • i dont want to shuffle the deck, it works fine with random, i simply want each card to only appear once, but thanks anyway! – Christian Paul Aug 22 '16 at 14:15
  • to make your card only appear once it more easy to make a deck from it first, because checking every time your randoming is very bad attempt – aiwiguna Aug 22 '16 at 14:16
  • Why not just use [`Collections.shuffle`](http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle(java.util.List))? – pjs Aug 23 '16 at 14:58
0

First off, I'd say that I think it would be easier / cleaner to simply shuffle the deck first and draw however many 'n' cards off the top. If you are, for some reason, tied to selecting cards at random and need to check for duplicates, simply have a set that you store the seen strings into and check to make sure that you didn't randomly select one already used.

public static Set<String> seenCards = new HashSet<>();

public static void displayRandomCard() {
    int max = 32;
    int min = 1;
    String myString = null;
    while (myString == null && seenCards.size() < 32) {
        Random r = new Random();
        int number = r.nextInt(max - min + 1) + min;
        myString = String.valueOf(number);
        if (seenCards.contains(myString)) {
            myString = null;
        } else {
            seenCards.add(myString);
        }
    }
    if (null == myString) {
        // throw some exception, etc
    }
    final ImageView imgTable = (ImageView) findViewById(R.id.imageView2);
    if (myString.equals("1")) {
        final Bitmap card1 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz7);
        imgTable.setImageBitmap(card1);
    }
    if (myString.equals("2")) {
        final Bitmap card2 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz8);
        imgTable.setImageBitmap(card2);
    }
}
Aaron Davis
  • 1,731
  • 10
  • 13
0

I would do like this

int max = 32;
int min = 1;
int generated = 0;
Random r = new Random();
int[] indexes = int[max-min+1];
for(int i=0; i<max-min+1; i++) {
    indexes[i] = i+min;
}

while (generated < max - min + 1) {

    int rand = r.nextInt(max - min + 1 - generated) + min;

    number = indexes[rand-1]; //get card number

    //avoid it will used again by putting it as last generated at the bottom of the indexes array
    int temp = indexes[max-min-generated];
    indexes[max-min-generated] = indexes[rand-1];
    indexes[rand-1] = temp;

    generated++;

    String myString = String.valueOf(number);

    final ImageView imgTable = (ImageView) findViewById(R.id.imageView2);

    if (myString.equals("1")) {

        final Bitmap card1 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz7);
        imgTable.setImageBitmap(card1);
    }
    else if (myString.equals("2")) {

        final Bitmap card2 = BitmapFactory.decodeResource(getResources(), R.mipmap.herz8);
        imgTable.setImageBitmap(card2);
    }
    else if ([...]) {
        [...]
    }
    [...]

}
ddb
  • 2,423
  • 7
  • 28
  • 38