随机播放一个数组,以便每个值都有不同的索引

时间:2014-06-25 22:28:03

标签: java arrays shuffle

我编写了一个方法来重排String数组 因此,任务是为名称列表的给定字符串数组实现WhiteElephant概念。应生成与原始元素匹配的赋值。 我编写了一个方法来选择一个随机数并使用一个映射来存储这些值,以便每个值都有不同的索引。但这只打印出5个值。我现在很困惑。

public static String[] generateAssignments(final String[] participants) {

    Random r = new Random();
    int size = participants.length;
    HashMap val = new HashMap();
    int change = 0;
    String[] assignments = new String[6];
    System.out.println("Using arrays");


    for(int i=0; i<size;i++){
        for(int j =0; j<size; j++){
            change = r.nextInt(size);
            if(val.containsValue(change) || change==i){
                continue;
            }
            else val.put(i, change);
            assignments[i] = participants[change];
            System.out.println(assignments[i]);
            break;
        }   

    }

    return assignments;
}

感谢您的投入。 谢谢, 幸运

4 个答案:

答案 0 :(得分:2)

如果你的shuffle方法是随机的(或伪随机的),那么单元测试几乎是不可能的,因为输出是非确定性的。如果您允许播种随机数生成器,那么您可以确保在给定相同种子的情况下输出是一致的,但这并不表示随机性。

您还可以多次运行随机播放方法,并检查每张卡片在每个索引处显示的是相等的次数。在足够多的模拟中,这应该有助于说明随机性。

答案 1 :(得分:1)

仅供参考 - 您的shuffle()代码和测试都存在一些逻辑错误。我不会在这里谈到这些;希望有一个好的测试可以让你找出问题!


围绕Random数据编写测试很难。

最好的选择是将Random的实例传递到您的shuffle()方法,或者它包含class。然后在测试用法中,您可以传入已使用已知值播种的Random实例。鉴于Random代码每次都会表现相同并且您控制输入数组,您的测试将是确定性的;您可以放心地assert对已排序集合中的每个对象。

这种方法的唯一缺点是,您将无法通过测试来阻止您重新编写shuffle()方法,只需将元素每次重新排序到此指定内容中订购。但这可能过度思考了;通常我们可以相信我们未来的自我。


另一种方法是假设在随机世界中,给定足够的时间,将实现每种数据的可能性。

我在测试6面骰子的roll()方法时使用了这种方法。我需要确保从1-6获得所有值是可能的。我不想让方法签名或Die构造函数复杂化以接受Random的实例。我也对使用已知种子的测试没有信心,并且总是断言3(即)。

相反,我假设给定足够的卷,1-6中的所有值最终都会被滚动。我写了一个无限调用roll的测试,直到返回1-6的所有值。然后我在测试中添加了timeout,如果上述条件没有得到满足,它将在1秒后失败。

@Test(timeout = 1000)
public void roll_shouldEventuallyReturnAllNumbersBetweenOneAndSixInclusively() {
    Die die = new Die();
    Set<Integer> rolledValues = new HashSet<Integer>();
    int totalOfUniqueRolls = 0;
    while (rolledValues.size() < Die.NUM_SIDES) {
        if (rolledValues.add(die.roll())) {
            totalOfUniqueRolls += die.getFaceValue();
        }
    }
    assertEquals(summation(1, Die.NUM_SIDES), totalOfUniqueRolls);
}

最糟糕的情况是它在1秒后失败(尚未发生),但它通常会在大约20毫秒内通过。

答案 2 :(得分:1)

测试必须是可重复的:如果它取决于随机的东西,它就无用了。

我建议您使用 mocking ,因此CUT(测试中的代码)不使用在生产中实例化的真实Random类,而是使用可预测的不同类编写的行为,使您有可能对两个或三个项目做出一些重要的断言。

答案 3 :(得分:0)

您的shuffle()方法似乎总会返回相同的结果。因此,如果测试中包含许多元素的输入测试数组,只需指定您期望的确切输出数组。

看起来你正在尝试编写一个非常通用的测试。相反,您的测试应该非常具体:给定一个特定的输入A,那么您期望一个特定的输出B.