问题
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