Creating a card shuffling program Java

本小妞迷上赌 提交于 2019-12-20 03:59:50

问题


I am trying to create a card shuffler within java that will perform "the perfect shuffle" (splitting the deck in two equal halves and interleaving each card, then repeating one more time), by performing both in and out shuffles. I have the following code to perform the 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];

}

}

I am trying to implement it into my deck class so rather than shuffle numbers 0-52, instead it will shuffle a deck of cards. My deck class looks as follows;

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;

I find my problems stemming from trying to implement it into my shuffle method within my deck 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

anyone any ideas? All help greatly appreciated, thanks. PS. I am trying to avoid using the quick collection class method wherever i can, im new to java and want to understand things fully first before using collection classes.


回答1:


I'm not sure what you mean by the perfect shuffle. Is there anything wrong with java's Collections.shuffle method?

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



回答2:


So, you want your deck (a table) split in 2 and then have it merged one card from each.

Here is how you can do it :

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) will accept any Object. You can call it like this :

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

You can change Integer by Card if you need to.




回答3:


I didn't really understand what you're trying to do in your shuffle method, but here goes my suggestion:

First, you don't need private int size;//number of cards in deck in your deck since you can call cards.size(). Is is also not recommended, since your deck size and you list size could be different. Just stick with your size method: public int size(){return cards.size();} or in you case, since you're treating it always like a common deck of cards, you can just use a constant of 52.

But I don't really like fixed stuff, then the following method will shuffle a deck of any size:

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

}

EDIT: I think I understood a little more what you wanted, take a look at this:

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



回答4:


Typical shuffles in programs are done with what is referred to as a Fisher-Yates shuffle, which randomizes a list of elements. I presume you want to emulate a perfect shuffle where each card is iterlaced with the others. Here is one way of doing that.

Most of this is boiler plate to demonstrate the method. The method mergeShuffle is the one you may be interested in.

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



回答5:


A simpler way (interleaving while spliting):

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


来源:https://stackoverflow.com/questions/59397518/creating-a-card-shuffling-program-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!