如何对数组进行“洗牌”操作?

7
我正在努力创建一个“shuffleDeck()”方法,但遇到了困难。
我的目标是创建一个方法,它将接受一个数组参数(即一副牌),洗牌并返回洗好的牌组。
以下是代码:
class Card
{
    int value;
    String suit;
    String name;

    public String toString()
    {
        return (name + " of " + suit);
    }
}

public class PickACard
{
    public static void main( String[] args)
    {   
        Card[] deck = buildDeck();
        // display Deck(deck); 

        int chosen = (int)(Math.random()* deck.length);
        Card picked = deck[chosen];

        System.out.println("You picked a " + picked + " out of the deck.");
        System.out.println("In Blackjack your card is worth " + picked.value + " points.");

    }

    public static Card[] buildDeck()
    {
        String[] suits = {"clubs", "diamonds", "hearts", "spades" };
        String[] names = {"ZERO", "ONE", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "Jack", "Queen", "King", "Ace" };

        int i = 0;
        Card[] deck = new Card[52];

        for ( String s: suits )
        {   
            for ( int v = 2; v<=14; v++)
            {
                Card c = new Card();
                c.suit = s;
                c.name = names[v];
                if ( v == 14)
                    c.value = 11;
                else if ( v>10)
                    c.value = 10;
                else
                    c.value = v; 

                deck[i] = c;
                i++;
            }
        }
        return deck; 
    }

    public static String[] shuffleDeck( Card[] deck) 
    {
        /** I have attempted to get two index numbers, and swap them. 
        I tried to figure out how to loop this so it kind of simulates "shuffling". 
        */
    }

    public static void displayDeck( Card[] deck)
    {
        for ( Card c: deck) 
        {   
            System.out.println(c.value + "\t" + c);
        }
    }
}

4
将数组转换为List,并调用Collections.shuffle(list) - Sotirios Delimanolis
1
你所发布的代码是没有意义的,因为它缺少了最重要的部分——尝试实现洗牌功能。由于你似乎根本没有尝试过,所以我已投票关闭该帖子。 - Duncan Jones
如果您不想创建一个List,我想另一个选择是使用Arrays#sort(T[], Comparator<T>),除了随机返回-1和1。 - Josh M
顺便提一下,使用枚举而不是字符串数组,如果你这样做,可以简化构建牌组方法。 - user902383
4个回答

11

怎么样:

List<Card> list =  Arrays.asList(deck);
Collections.shuffle(list);

或者一行代码:

Collections.shuffle(Arrays.asList(deck));

Card[]怎么样? - Josh M
2
但是你在一行代码中错过了结果:哪个变量包含了混洗后的内容? ;) - Radio Rogal
1
我错了:Arrays.asList创建一个基于数组的列表,因此当Collections交换此列表中的任何元素时,它与在数组中交换它们相同。 - Radio Rogal
1
@khelwood 哎呀..你说得完全正确。在我的测试用例中,我不小心使用了int。在OP的代码中,他使用了Card,所以它确实有效。我已经回滚了一行代码(修正了拼写错误),并将删除上面的评论。(是的,我确实知道Arrays.asList(int[])的结果是List<int[]>。:)) - Kevin Cruijssen

3
一种方法是将数组转换为列表,然后使用 java.util.Collections.shuffle(array) 对其进行随机排序:
Card[] deck = ...;
List<Card> list = Arrays.asList(deck);
Collections.shuffle(list);

如果您仍需要使用数组而不是列表,您可以添加以下内容:
list.toArray(deck);

这是一个TIO(在线尝试)链接,可以查看数组转换为列表和随机打乱的过程。

以下是TIO代码供参考:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

class M{
  public static void main(String[] a){
    // Original array
    Integer[] array = new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    System.out.println("before: " + Arrays.toString(array));

    // Convert array to list
    List<Integer> list = Arrays.asList(array);
    // And shuffle that list
    Collections.shuffle(list);
    System.out.println("after as list: " + list);

    // (Optional) then convert the list back to an array,
    // and save it in its initial variable (`array` in this case)
    list.toArray(array);
    System.out.println("after as array: " + Arrays.toString(array));
  }
}

1
你不需要执行 list.toArray(deck);。在运行 Collections.shuffle(list); 之后,deck 已经被洗牌了。这是因为 Arrays.asList() 返回的列表是数组的视图。 - user4910279

0

0

如果这是一个学校项目(我认为是的),你可能不允许使用内置函数,如Collections::shuffle()。如果是这种情况,那么你必须尝试模拟随机性(在编程中可能会出现意外困难)。

创建随机感的最常见方法是使用RNG(随机数生成器)。就像你所说的

我已经尝试获取两个索引号,并交换它们。

正确。洗牌的一种方法是每次选择一张牌,并随机选择另一张牌来交换位置。

  • 你知道牌组总共有52张牌。
  • 你有一个随机生成器来选择一个随机索引。
  • 你有一种编程语言和循环结构。

有了这些工具,你可以很容易地实现自己的洗牌函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接