Java: 如何用相同的算法打乱2个ArrayList?

Java: How to shuffle 2 ArrayList with same algorithm?

我想用算法洗牌 cardList 和 valueList,但是当我对每个使用洗牌集合时,它们使用不同的算法。因此,当我抽出一张牌时,它将是牌组中的一张随机牌,并且不会再次出现同一张牌。

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;
    }
}

编辑:我按照@Cinnam 的建议做了第二个 class,然后使用 For int 随机数洗牌。

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);

}

我认为在你的情况下最好的解决方案是创建一个 class 来保存卡片和价值:

class ValuedCard {

    private String card;
    private int value;

    // constructor, getters/setters...
}

那么你可以只有一个列表 ArrayList<ValuedCard> 并洗牌。

首先回答你的几个问题:

您可以使用地图将值映射到卡片上。这样你就可以通过发送卡来查询价值。

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));

这可行,但并不是那么漂亮。另一种选择是创建一张卡片 class。

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

然后您可以将卡片存储在列表中,一切正常。这可能是最 Java 的方式。您甚至可以为 class 提供一些实用功能。也许您只想发送一套西装和一个数字,而不是完整的字符串。

最后一个选项是将种子发送到随机播放方法。

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

现在开始其他事情:对您的代码的评论。

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

您向此方法发送一个您添加所有内容的列表,然后您 return 该列表。你真的不需要两者都做。你可以做

    ArrayList<String> cardList= card(); 

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

或者您可以只发送列表而不是 return。我更喜欢第一种方法,因为它更干净。

您可以使用 Collections.shuffle() that accepts a Random as a parameter, which you can initialized using the same seed via the setSeed() 方法的重载版本。

因此,在您的代码中,您需要 Random 每个牌组都使用相同的种子,例如:

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);

只需确保将两者混在一起(您需要更好的 OO 设计来封装它)。

另外请注意,在 Collection.shuffle() 中,数组的大小正在被使用 因此在您的情况下,您的两个集合需要具有相同的大小。

在上面的代码示例中,情况并非如此,因为存在错误:

在您的静态 value() 方法中,for 循环需要包含 52,换句话说:

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

在这种情况下,代码结果符合预期。

你的值和你的牌在 2 个单独的 ArrayList 中,所以当你洗牌时,它们会以不同的方式洗牌,并且它们将不再对应。我的建议是创建一个名为 Card 的新 class,有一个包含 Cards 的 ArrayList,然后将其洗牌。

这是一张可能的卡片 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;
}

}

您可以像这样创建一个包 (ArrayList):

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);