【问题标题】:Java: How to shuffle 2 ArrayList with same algorithm?Java:如何用相同的算法洗牌 2 个 ArrayList?
【发布时间】:2015-12-10 16:44:39
【问题描述】:

我想用算法对 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 的建议做了第二堂课,然后使用 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);

}

【问题讨论】:

  • 你的 cardShuffle 和 valueShuffle 数组永远不会被使用。
  • 看起来您需要创建一个可以同时接收 ArrayList 并对其进行随机播放的方法。我在您的代码中没有看到。我看到了两种不同的方法来打乱两个不同的数据集

标签: java algorithm shuffle


【解决方案1】:

我认为在你的情况下最好的解决方案是创建一个同时持有卡片和价值的类:

class ValuedCard {

    private String card;
    private int value;

    // constructor, getters/setters...
}

那么你可以只拥有一个列表ArrayList&lt;ValuedCard&gt; 并随机播放它。

【讨论】:

  • 很好的解决方案,但我会使用枚举值和卡片类型。
  • @barak1412 同意,我试图使其简单且类似于 OP 的原始代码。
  • @Cinnam 通过使用您的解决方案,我相信它会将所有卡保存在一个地方,并在每次调用时覆盖。我确实使用了另一个类来将卡片和值保存在数组列表中,当被调用时,我可以在主类中对其进行初始化。
  • @AnjeshShrestha Collections.shuffle() 将洗牌集合的元素,无论它们是什么。对于Strings、ValuedCards 或任何其他对象,它的工作方式相同。
【解决方案2】:

首先回答你的问题:

您可以使用映射来保持映射到卡片的值。这样一来,您只需发送卡片即可查看价值。

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

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

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

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

最后一个选项是将种子发送到 shuffle 方法。

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

现在转到其他内容:代码中的 cmets。

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

您向此方法发送一个列表,将所有内容添加到该列表中,然后返回该列表。你真的不必两者都做。你可以这样做

    ArrayList<String> cardList= card(); 

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

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

【讨论】:

    【解决方案3】:

    您的值和卡片位于 2 个单独的 ArrayList 中,因此当您将它们洗牌时,它们会以不同的方式洗牌,并且它们将不再对应。我的建议是创建一个名为 Card 的新类,在其中包含一个包含 Cards 的 ArrayList,然后对其进行洗牌。

    这是一个可能的 Card 类:

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

    【讨论】:

      【解决方案4】:

      您可以使用Collections.shuffle() 的重载版本,它接受Random 作为参数,您可以通过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++){
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-13
        • 2012-11-12
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多