簡體   English   中英

創建洗牌程序Java

[英]Creating a card shuffling program Java

我正在嘗試在 java 中創建一個洗牌器,通過執行進出洗牌來執行“完美洗牌”(將牌組分成兩等分並交錯每張牌,然后再重復一次)。 我有以下代碼來執行隨機播放。

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

}

}

我正在嘗試將它實現到我的甲板類中,而不是將數字 0-52 洗牌,而是將一副牌洗牌。 我的甲板課程如下所示;

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;

我發現我的問題源於試圖在我的套牌類中將它實現到我的 shuffle 方法中。

    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

有人有什么想法嗎? 非常感謝所有幫助,謝謝。 附注。 我盡量避免在任何可能的地方使用快速集合類方法,我是 Java 新手,想在使用集合類之前首先完全理解事物。

我不確定你所說的完美洗牌是什么意思。 java 的 Collections.shuffle 方法有什么問題嗎?

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

所以,你希望你的牌組(一張桌子)一分為二,然后從每張牌中合並一張牌。

您可以這樣做:

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

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

我不太明白你在 shuffle 方法中想要做什么,但我的建議是:

首先,你不需要private int size;//number of cards in deckprivate int size;//number of cards in deck因為你可以調用cards.size() 也不推薦,因為您的甲板尺寸和您的列表尺寸可能不同。 只要堅持你的 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));
    }   
}

程序中的典型 shuffle 是通過所謂的Fisher-Yates shuffle 完成的,它隨機化一個元素列表。 我想你想模擬一個完美的洗牌,每張卡片都與其他卡片交錯。 這是這樣做的一種方法。

大部分是樣板來演示方法。 方法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));
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM