创建洗牌程序 Java

Creating a card shuffling program Java

我正在尝试在 java 中创建一个洗牌器,它将执行 "the perfect shuffle"(将一副牌分成相等的两半并交织每张牌,然后再重复一次),方法是同时执行进出洗牌。我有以下代码来执行随机播放。

public class Shuffle {

private static final int shuffleCount = 2;

private static final int valueCount = 52;

public static void main(String[] args){
    System.out.println("Result of " + shuffleCount + "perfect shuffles" );

    int[] value1 = new int[valueCount];
    for (int i = 0; i < value1.length; i++){
    value1[i] = i;
}//ends valueCount for loop
    for (int j = 1; j <= shuffleCount; j++){
        riffleShuffle(value1);
        System.out.println(" " + j +":\n");
        for(int k = 0; k < value1.length; k++){
            System.out.println(" " + value1[k]);
        }
        System.out.println();
    }//ends shuffleCount for loop
    System.out.println();
}

public static void riffleShuffle(int[] value){

    int[] temp = new int[value.length];
    int startFirst =  0;
    int startSecond = value.length / 2;
    for (int i = 0; i < value.length; i+=2){
        temp[i] = value[startFirst];
        temp[i+1] =value[startSecond] ;
        startFirst ++;
        startSecond ++;
}
    for (int i =0; i< value.length; i++)
        value[i] = temp[i];

}

}

我正在尝试将它应用到我的牌组中 class 所以它不会洗牌 0-52,而是洗牌。我的牌组 class 如下所示;

public class Deck {


private List<Card> cards;


private int size;//number of cards in deck


public Deck(String[] faces, String[] suits, int[] values){
   cards = new ArrayList<Card>();
   for(String suit: suits) 
       for(int value = 0; value < values.length && value < faces.length; value++){
           Card a = new Card(faces[value], suit, values[value]);
           cards.add(a);
       }
   size = cards.size();
   shuffle();

}//ends deck

public boolean isEmpty(){
    return cards.isEmpty() && size == 0;
}//ends isEmpty

public int size(){
        return cards.size();
}//ends size

public void shuffle(){
    for (int i = cards.size() - 1; i > 0; i--){
    int pos =  0;
    Card a = cards.remove(pos);
    cards.add(i, a);
    }

}//ends shuffle

public Card deal(){
    size --;
    Card a = cards.get(size);
    return a;
}//ends Card deal

@Override
public String toString(){
    String deck_rtn = "\nsize = " + size + "\n\nUndealt cards: \n\n";

    for(int k = size -1; k >= 0; k--){
        deck_rtn = deck_rtn + cards.get(k);
            if (k != 0){
            deck_rtn = deck_rtn + ", ";
            }//ends first if

            if ((size - k) % 2 == 0) {
            deck_rtn = deck_rtn + "\n";
            }//ends second if

    }

    deck_rtn = deck_rtn + "\nDealt cards: \n";
    for (int k = cards.size() - 1; k >= size; k--){
        deck_rtn = deck_rtn + cards.get(k);
        if (k != size){
        deck_rtn = deck_rtn + ", ";
        }
        if ((k - cards.size()) % 2 ==0){
        deck_rtn = deck_rtn + ", ";
        }
    }

    deck_rtn = deck_rtn + "\n";
    return deck_rtn;

我发现我的问题源于尝试将它实现到我的套牌中的洗牌方法中 class。

    public void shuffle(){
    for (int i = cards.size() - 1; i > 0; i--){
    int pos =  0;
    Card a = cards.remove(pos);
    cards.add(i, a);
    }

}//ends shuffle

有人有什么想法吗?非常感谢所有帮助,谢谢。 PS。我试图尽可能避免使用快速收集 class 方法,我是 java 的新手,并且想在使用收集 classes.

之前先完全理解事情

我不确定你所说的完美随机播放是什么意思。 java的Collections.shuffle方法有什么问题吗?

    List<Card> cards = new ArrayList<>(52);
    Collections.shuffle(cards);

因此,您希望将您的套牌(table)一分为二,然后将其从每张牌中合并一张。

以下是您的操作方法:

public static Object[] riffleShuffle(Object[] deck){
    if (deck.length < 2) return deck; // nothing to shuffle
    Object[][] split = split(deck);
    return merge(split[0], split[1]);
}

private static Object[][] split(Object[] deck) {
    Object[][] split = new Object[2][];
    int pivot = (deck.length + 1) / 2; //rounded up
    split[0] = copy(deck, 0, pivot);
    split[1] = copy(deck, pivot, deck.length);
    return split;

}

private static Object[] merge(final Object[] o1, final Object[] o2) {
    Object[] merged = new Object[o1.length + o2.length];
    for (int i=0; i<merged.length; i++){
        if (i%2==0) merged[i] = o1[i/2];
        else merged[i] = o2[i/2];
    }
    return merged;
}

private static Object[] copy(Object[] source, int start, int end){
    Object[] copy = new Object[end - start];
    for (int i=start; i < end; i++){
        copy[i-start] = source[i];
    }
    return copy;
}

riffleShuffle(Object[] deck) 将接受任何对象。你可以这样称呼它:

Integer[] values = {1,2,3,4,5,6,7,8,9,10,11,12,13};
Object[]  result = riffleShuffle(values);
if (result instanceof Integer[]) {
    values = (Integer[]) result;
    System.out.println(Arrays.toString(values));//[1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13, 7]
}

如果需要,您可以将 Integer 更改为 Card

我不太明白你想用随机播放方法做什么,但我的建议是:

首先,你的套牌中不需要 private int size;//number of cards in deck,因为你可以召唤 cards.size()。也不推荐,因为您的牌组大小和列表大小可能不同。只需坚持您的大小方法:public int size(){return cards.size();} 或者在您的情况下,因为您始终将其视为一副普通的纸牌,您可以只使用常数 52。

但是我不太喜欢固定的东西,那么下面的方法可以洗任意大小的一副牌:

public void suffle(){

    //let's first split the deck in two
    List<Card> firstHalf = new ArrayList<>();
    List<Card> secondHalf = new ArrayList<>();

    int halfSize = cards.size()/2;
    if(cards.size()%2 != 0){ //in case the number of cards is odd we have to add one more card to the first half
        halfSize += 1;
    }


    for(int i = 0; i < cards.size(); i++){
        if(i < halfSize){
            firstHalf.add(cards.get(i));
        }else{
            secondHalf.add(cards.get(i));
        }
    } //now we have a split deck, the firstHalf contains the top of the deck and the second half contains the bottom


    cards = new ArrayList<>();//empty the main deck to remake it

    while(firstHalf.size > 0){ //the first half will always be bigger or have the same size
        cards.add(firstHalf.get(0)); //always get the first card, since we will remove it next
        firstHalf.remove(0);
        if(secondHalf.size() > 0){ //now we are interleaving the cards
            cards.add(secondHalf.get(0));
            secondHalf.remove(0);
        }
    } 

    //now your deck is shuffled

}

编辑: 我想我更明白你想要什么了,看看这个:

public static void riffleShuffle(List<Cards> value){

    List<Cards> temp = new ArrayList<>();
    int startFirst =  0;
    int startSecond = value.size() / 2;
    for (int i = 0; i < value.size(); i += 2){
        temp.add(value.get(startFirst));
        temp.add(value.get(startSecond);
        startFirst ++;
        startSecond ++;
    }
    value = new ArrayList<>();
    for (int i =0; i< value.size(); i++){
        value.add(temp.get(i));
    }   
}

程序中的典型随机播放是通过所谓的 Fisher-Yates 随机播放完成的,它随机化元素列表。我想你想模拟一个完美的洗牌,其中每张牌都与其他牌交织在一起。这是一种方法。

其中大部分是用于演示该方法的样板。 mergeShuffle 方法是您可能感兴趣的方法。

  public static void main(String[] args) {
      String suit = "CDHS";
      String rank = "KQJT98765432A";

      // create a deck of cards..
      String[] deck = IntStream.range(0, 52).mapToObj(
            i -> "" + rank.charAt(i % 13) + suit.charAt(i / 13)).toArray(
                  String[]::new);
      // show it
      display(deck);
      deck = mergeShuffle(deck);
      System.out.println();
      display(deck);
   }

   public static void display(String[] deck) {
      int i = 0;
      for (String card : deck) {
         System.out.print(card + " ");
         i++;
         if (i % 13 == 0) {
            System.out.println();
         }
      }
   }

   public static String[] mergeShuffle(String[] deck) {
      String[] shuffledDeck = new String[52];
      if (deck.length != 52) {
         System.out.println("You're not playing with a full deck. :)");
         return null;
      }

      int i = 0; // destination index of the shuffled deck
      for (int k = 0; k < 26; k++) {
         shuffledDeck[i++] = deck[k];
         shuffledDeck[i++] = deck[k + 26];
      }
      return shuffledDeck;
   }
}

更简单的方法(拆分时交织):

public void suffle(){

    //let's first split the deck in two
    List<Card> firstHalf = new ArrayList<>();
    List<Card> secondHalf = new ArrayList<>();

    while(cards.size() > 0){//we will split the cards while interleaving them
        firstHalf.add(cards.get(0));
        cards.remove(0);
        if(cards.size() > 0){
            secondHalf.add(cards.get(0));
            cards.remove(0);
        }
    }

    //now just put the two parts together
    cards = new ArrayList<>();
    for(int i = 0; i < firstHalf.size(); i++){
        cards.add(firstHalf.get(i));
    }
    for(int i = 0; i < secondHalf.size(); i++){
        cards.add(secondHalf.get(i));
    }
}