Random dice rolls are not random

Simple newbie problem that I weirdly couldn't call for a solution.

I am making a simple dice roll simulator, so I can compare the intransitive bones as well as the normal ones, however the problem is that if I make two bones with the same number of faces and values ​​on the mentioned faces, both bones roll the same value every time. (i.e. each roller creates a different number, but both bones have the same value)

Here's my code:

class Die(values: Int*) {
  private val rand: util.Random = new util.Random(compat.Platform.currentTime)
  private val high = values.size + 1
  private val low  = values(0)
  def roll(): Int  = rand.nextInt(high - low) + low
  def this(vals: Range) = this(vals: _*)

  def rollAndCompareTo(that: Die): Symbol = {
    val a = this.roll()
    val b = that.roll()
    if(a > b) 'GT
    else if (a < b) 'LT
    else 'EQ
  }
}

object Program extends App {
  val d61 = new Die(1 to 6)
  val d62 = new Die(1 to 6)

  for(_ <- 1 to 100)
    println(d61 rollAndCompareTo d62)
}

      

In 100% of cases, the program does not print anything except 'EQ

because the two bones, despite the fact that different instances created at different times, always reset the same value.

I also tried adding a delay so the seed difference is bigger, but that doesn't help either.

What would I do to fix this?

+3


source to share


4 answers


Try to leave a seed for your Random instance, or use

new util.Random(System.currentTimeMillis)

      



The specificity of your seed is important if you make a lot of calls in a short amount of time.

+3


source


As other comments said, you can use a single rand in the companion object, then you don't have to worry about seed resolution. Consider using SecureRandom else using this to seed your only regular resource. Random case to avoid overhead or possibly blocking of SecureRandom behavior



object Die {
  // consider using java.security.SecureRandom or using that to seed a util.Random
  private[Die] val rand: util.Random = new util.Random(compat.Platform.currentTime)
}

class Die(values: Int*) {
  private val high = values.size + 1
  private val low = values(0)
  def roll(): Int = Die.rand.nextInt(high - low) + low
  def this(vals: Range) = this(vals: _*)

  def rollAndCompareTo(die: Die): Symbol = {
    val a = this.roll()
    val b = die.roll()
    if (a > b) 'GT
    else if (a < b) 'LT
    else 'EQ
  }
}

object Program extends App {
  val d61 = new Die(1 to 6)
  val d62 = new Die(1 to 6)

  for (_ <- 1 to 100)
    println(d61 rollAndCompareTo d62)
}

      

+1


source


You can simply choose fixed seeds that are different from each other. Also, compat.Platform.currentTime () and System.currentTimeMillis () work fine (2014 MacBook Pro). You can try System.nanoTime () in case two objects are created within one millisecond. But really, fixed seeds are better, for example. for testing.

Also, it looks completely like Java - with mutable state, side effects, etc. If you are thinking of learning Scala the way its creators encouraged it (as functional as possible), check out a book by Paul Chiusano and Rúnar Bjarnason titled Functional Programming in Scala (Manning Press, Early Access, http: // manning. com / bjarnason / ). They have an entire chapter on purely functional state using a random number generator example. Or see the NICTA example: https://github.com/NICTA/rng

0


source


Consider java.security.SecureRandom

what turns out to be much more unpredictable than java.util.Random

linear congruential generators.

For a more detailed discussion, take a look, for example fooobar.com/questions/36709 / ... and http://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html .

0


source







All Articles