相同的随机数ruby

时间:2011-12-06 17:51:59

标签: ruby random

嗯,我是一个红宝石新手,我正在尝试用RubyKoans学习,但我对这个测试感到困惑

def test_dice_values_should_change_between_rolls
 48     dice = DiceSet.new
 49     dice.roll(5)
 50     first_time = dice.values
 51    
 52     dice.roll(5)
 53     second_time = dice.values
 54     
 55     assert_not_equal first_time, second_time,
 56       "Two rolls should not be equal"
 57   end

这是DiceSet类

5  class DiceSet
  6    attr_accessor :values
  7 ··
  8    def initialize
  9      @values = []
 10    end
 11 
 12    def roll(times)
 13      @values.clear
 14      times.times do |x|
 15        @values << ( 1 + rand(6))
 16      end
 17     end
 18 ····
 19    end

这里的事情是,每当我运行代码时,它总是生成完全相同的数字集,这就是输出。

Two rolls should not be equal.  <[3, 2, 4, 1, 3]> expected to be != to  <[3, 2, 4, 1, 3]>.

在测试我调用DiceSet.roll两次,对于那两次,我得到完全相同的“随机”数字集合,当他们被认为是不同的权利?我想我可能会创建另一个DiceSet实例以通过测试,但我猜测这不是测试的目标

4 个答案:

答案 0 :(得分:6)

问题是DiceSet#values返回对数组的引用,并且该数组在DiceSet对象的整个生命周期内保持不变。在DiceSet#roll中清除该数组,然后添加新数字。由于对DiceSet#values的两次调用都返回相同的引用,因此第一次滚动的结果将丢失,并且您的测试是将数组与其自身进行比较。

我不熟悉RubyKoans以及它们有什么要求,即如果DiceSet应该存储值等等。如果是,那么最直接的解决方案是使用两个DiceSets或使用Object#dup存储测试返回对象的副本。

但是,请注意,即使代码运行正常,您的测试仍然很脆弱,因为总有两个连续卷可能会返回完全相同的数字。在这种特殊情况下,它相对较小但仍然非常存在。

答案 1 :(得分:1)

以下内容适用于此测试:

class DiceSet
  attr_accessor :values

  def roll (times)
    @values = []
    times.times do |x|
      @values << ( 1 + rand(6) )
    end
  end
end

所以我们正在为每个卷创建新数组。

答案 2 :(得分:0)

最好使用attr_reader而不是attr_accessor(就像Ilya Tsuryev建议的那样)。因为您不希望客户端代码欺骗骰子。 并且使用rand(1..6)更具可读性。

class DiceSet
  attr_reader :values

  def roll(set_size)
    @values = []
    set_size.times { @values.push rand(1..6) }
  end
end

答案 3 :(得分:-1)

每次使用一个新阵列将解决dominikh所指出的参考问题,但正如他所说的那样,并不能保证你连续2次掷骰都有不同的nos。在我的实现中,我记得最后一次抛出并循环,直到我得到一个不同的集合:

class DiceSet
  attr_reader :values, :lastroll
  def initialize
      @values = []
      @lastroll = []
  end
  def roll(n)
      while @values == @lastroll
          @values = Array.new(n) { |i| i = rand(6) + 1 }
      end
      @lastroll = @values
  end
end