Anjesh Shrestha
Anjesh Shrestha

Reputation: 25

Java: How to shuffle 2 ArrayList with same algorithm?

I want to shuffle the cardList and valueList with algorithm, but when i use the shuffle collection for each one, they use different algorithm. So when i pull a card it will be a random card from the deck and the same card does not come up again.

public class BlackJack {

    public static void main(String[] args) {
        Random rand = new Random();
        Scanner input =new Scanner(System.in);
        ArrayList<String> cardList= new ArrayList<String>();
        ArrayList<String> cardShuffle= new ArrayList<String>();
        ArrayList<Integer> valueList= new ArrayList<Integer>();
        ArrayList<String> valueShuffle= new ArrayList<String>();

        cardList = card(cardList); 
        valueList = value(valueList);

        Collections.shuffle(cardList);
        Collections.shuffle(valueList);

        System.out.println(cardList);
        System.out.println(valueList);

    }
    private static ArrayList card(ArrayList<String> cardList){
        String cards = null;
        String suits = null;
        int cardCount = 0;
        for(int s = 1;s<5; s++){

            switch (s){
            case 1: suits = " of Heart"; break;
            case 2: suits = " of Diamond"; break;
            case 3: suits = " of Spades"; break;
            case 4: suits = " of Clubs"; break;
            }

            for(int c = 1;c<14; c++){
                switch (c){
                case 1: cards = "2"; break;
                case 2: cards = "3"; break;
                case 3: cards = "4"; break;
                case 4: cards = "5"; break;
                case 5: cards = "6"; break;
                case 6: cards = "7"; break;
                case 7: cards = "8"; break;
                case 8: cards = "9"; break;
                case 9: cards = "10"; break;
                case 10: cards = "Jack"; break;
                case 11: cards = "Queen"; break;
                case 12: cards = "King"; break;
                case 13: cards = "Ace"; break;
                }
                cardList.add(cardCount, cards + suits);
                cardCount++;
            }
        }

        return cardList;
    }
    private static ArrayList<Integer> value(ArrayList<Integer> valueList){

        int v = 2;
        int counter = 1;
        for(int c = 1;c<52; c++){
            if(v > 10){
                v = 10;
            }
            valueList.add(v);
            v++;
            counter++;
            if(counter>13){
                counter = 1;
                v=2;
            }
        }

        return valueList;
    }
}

Edit: I made a second class as @Cinnam had suggested, then used a For int to shuffle the cards with a random number.

public class BlackJack {

    public static void main(String[] args) {
        Random rand = new Random();
        Scanner input =new Scanner(System.in);

        ArrayList<String> cardList= Cards.card(); 
        ArrayList<Integer> valueList= Cards.value(); 
        ArrayList<String> cardShuffle= new ArrayList<String>();
        ArrayList<Integer> valueShuffle= new ArrayList<Integer>();

        int r = 0;
         for(int i = 0; i < 52; i++){
             r = rand.nextInt(52);
                    cardShuffle.add(i,cardList.get(r));
                    valueShuffle.add(i,valueList.get(r));
             }
        System.out.println(cardShuffle);

}

Upvotes: 1

Views: 835

Answers (4)

dimitrisli
dimitrisli

Reputation: 21381

You can use an overloaded version of the Collections.shuffle() that accepts a Random as a parameter, which you can initialized using the same seed via the setSeed() method.

So in your code you'll need a Random per card deck both using the same seed, example:

Random rand1 = new Random();
rand1.setSeed(123);

Random rand2 = new Random();
rand2.setSeed(123);

//..and further below

Collections.shuffle(cardList, rand1);
Collections.shuffle(valueList, rand2);

Just make sure you shuffle both together (you want better OO design to encapsulate this).

Also be mindful that inside Collection.shuffle() the size of the array is getting used therefore in your case both of your collections need to have the same size.

In the code example above this is not the case since there is a bug:

In your static value() method the for loop needs to be inclusive of 52, in other words:

for(int c = 1;c<=52; c++){

In this case, the code result is as expected.

Upvotes: 1

Astrogat
Astrogat

Reputation: 1625

First a couple of answers to you questions:

You could use a map to keep the values mapped to the cards. That way you can look up the value just by sending in a card.

Map<String, Integer> cardsWithValues = new HashMap<>();
//Fill it by going cardsWithValue.put("2 of Dimonds", 2) for all cards. You can use a loop.

  //Shuffle the cards array, then you can get the values by doing:
   System.out.print(cardsWithValue.get(cards.get(i));

This works, but it's not all that pretty. Another option is just to create a card class.

Public class Card{
    Integer value;
    String cardName;
    public Card(Integer value, String cardName){
        this.value = value;
        this.cardName = cardName;
    }

Then you can just store the Cards in a list, and everything works. This might be the most Java way of doing it. You can even give the class some utility functions. Maybe you just want to send in a suit and a number instead of the full string.

The last option is to send in a seed to the shuffle method.

Long seed = 1234;
Random r = new Random(seed); 
Collections.shuffle(cardsList, r);
r = new Random(seed);
Collections.shuffle(valueList, r);

Now over to something else: A comments on your code.

private static ArrayList card(ArrayList<String> cardList){

You send this method a list that you add everything to, and then you return the list. You don't really don't have to do both. You can either just do

    ArrayList<String> cardList= card(); 

 private static ArrayList card(){
        List<String> cardList = new ArrayList<String>
        //Fill it with stuff 
        return cardList;
    }

or you could just send in the list and not return it. I would prefer the first method, since it's cleaner.

Upvotes: 2

NickJ
NickJ

Reputation: 9559

Your values and your cards are in 2 separate ArrayLists, so when you shuffle them, they'll be shuiffled differently, and they'll no longer correspond. My suggesation is to create a new class called Card, have a single ArrayList with Cards in it, and shuffle that.

Here's a possible Card class:

public class Card {

public static enum Suit {SPADE,HEART,DIAMOND,CLUB};

public static enum Value {

    //The integer parameter is the score. Adjust as needed.
    ACE(1),DEUCE(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7),
    EIGHT(8),NINE(9),TEN(10),JACK(10),QUEEN(10),KING(10);
    int score;
    Value(int score) {
        this.score = score;
    }
}

private Suit suit;
private Value value;

public Card(Suit suit, Value value) {
    this.suit = suit;
    this.value = value;
}

public int getScore() {
    return value.score;
}

}

You can create a pack (ArrayList) like this:

ArrayList<Card> pack = new ArrayList<Card>();

for (Card.Value value : Card.Value.values()) {
    for (Card.Suit suit : Card.Suit.values()) {
        pack.add(new Card(suit, value));
    }
}

//finally, shuffle it:
Collections.shuffle(pack);

Upvotes: 1

Cinnam
Cinnam

Reputation: 1922

I think the best solution in your case is to create a class that will hold both card and value:

class ValuedCard {

    private String card;
    private int value;

    // constructor, getters/setters...
}

Then you can have just one list ArrayList<ValuedCard> and shuffle it.

Upvotes: 4

Related Questions