创建洗牌程序 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));
}
}
我正在尝试在 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));
}
}