Why rand.seed dosen't work?

I think the following code should always generate same result since there is rand.Seed in the init function that makes sure the rand.Intn generate same random integer serias. but it actually get different result any time I run it. did I misunderstand the rand.Seed function?

package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

var (
	wg sync.WaitGroup
)
func init(){
	rand.Seed(time.Now().UnixNano())
}

func main(){
	wg.Add(2)
	court := make(chan int)

	go play("James", court)
	go play("Yun", court)

	court <- 1

	wg.Wait()
}

func play(name string, court chan int){
	defer wg.Done()
	for {
		ball, ok := <- court
		if !ok {
			fmt.Printf("player %s won\n", name)
			return
		}
		n := rand.Intn(100)
		if n % 13 == 0{
			fmt.Printf("Player %s missed\n", name)
			close(court)
			return
		}
		fmt.Printf("Player %s Hit %d\n", name, ball)
		court <- ball + 1
	}

}

Thanks

1 Like

It will generate the same sequence once you manage to seed it at the same nano second. But since thats very unlikely to happen, seed is different each time.

1 Like

great, thanks.

wondering why the author want to use this? I mean, if the author wants to use rand.Seed for same result, then why he use Nano second which always generate different result? werld to me…why not just put rand.Seed(1)?

1 Like

Sometimes you just want to re-initialize the RNG with a new “semi-random” seed to generate a new sequence of numbers.

Its a common idiom to use the current time or a new value from the old generator.

1 Like

sorry, what’s RNG? really new to this and still not very clear. you mean use this nano second is kind of semi-random? but it’s actually generating different result every time it runs, so it appears to me it’s completely random instead of semi-random.

1 Like

RNG is Random Number Generator.

And the randomness factor of the current time is not what does actually count here, its just that we want to break the old predictable sequence.

Just consider this scenario.

A couple of years ago a “bot” has been written that was able to play the arcard version of “Asteroids”, after about 2 seconds of gameplay an observation it was able to calculate the seed that was used to init the RNG, from that point on it was also able to consider asteroids not even created yet.

Reinitialising the RNG every now and then with a new seed breaks this predictability and makes it harder to look into the future.

The problem is, if you use a new number from the old sequence, the observer might be able to guess that one as well and just continue as before. If though the current timestamp was used, then the observer can’t now the exact value, as its clock is probably off by a couple of nano seconds and even a single nanosecond difference will generate completely different sequences.

Sometimes though, you actually want reproducability. Consider test runners in many languages that shuffle order of execution. They usually print the seed used and also allow to specify a seed as an argument to recreate old order of execution (as long as you did not insert or remove tests since then).

Another example were procedural level generators, eg for roguelike games. You do not need to store the actual level layout on save, just the seed and regenerate that floor when necessary.

1 Like

Thanks @NobbZ for this detailed explanation!

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.