Do something randomly within a certain time frame

2019-08-26 05:54发布

I have a timer with interval of 1000 ms. I want to do something at random time but within a given time frame. E.g. If I specify the time frame to be for example 10 seconds, 1-10, 11-20, 21-30 and so on. This means that in the first 10 seconds something will happen between the 1st time frame 1 to 10 seconds at random. E.g. could happen in the 2nd second or the 8th second. Then again from 11 to 20 seconds something occurs again any time between the second time frame. E.g. this could be the 13th or the 15th second. Note that the timer has to be continuous e.g. from 1 to 100 seconds. Here if I specifiy the time frame to be 10 we will have ten time frames. 1-10,11-20,21-30 ....91-100. Since I need to know the exact time of the events that will occur. Therefore do not think that resetting the timer might solve the problem.

Thanks for you reply and examples with explanation are greatly appreciated.

3条回答
Viruses.
2楼-- · 2019-08-26 06:36

Your question is not very clear, so let me suppose the something that will happen as a function. let's say func1 happens in [1-10], func2 happens in [11-20] and so on.

  • implement a function called random that outputs a bool (to judge whether execute or not).
  • define a set of flags for each bin of time interval to track whether we already executed the specified function for this period or not yet (flag1, flag2, ...).
  • set your timer.Interval to 1 sec
  • define a global variable (count), and increase it by 1 each timer.tick
  • use some conditions here :

    if(count>0 && count<=10)
    { 
       if(flag1 && random()) {func1(); flag1=false;} 
    }
    
    if(count>10 && count<=20)
    { 
       if(flag2 && random()) {func2(); flag2=false;} 
    }
    

and so on

查看更多
forever°为你锁心
3楼-- · 2019-08-26 06:38

I don't think any of the first 3 answers have it right, so let me try: what you are saying is that time is ticking, and in each slice of N seconds, you want one event to occur at a random time in that slice. If that is the case, then whenever the time is a multiple of N seconds, get a random number between 0 and N, and generate the event at that time. For example, in pseudo-code:

time = 0
delta_time = 1 second
max_time = 100 seconds
slice_time = 10 seconds
// decide when event of first slice will occur; can't be at 0: get random # 
// in range [delta_time, slice_time]:
next_rand_time = random(delta_time, slice_time)
setup timer to fire at interval of delta_time, each time do the following (callback): 
    time += delta_time
    // is it time to fire the event yet? allow for round-off error:
    if abs(time - next_rand_time) < 0.0001:
        generate event
    // is it time to decide when next random event will be? 
    if modulo(time, slice_time) == 0: 
        // can't be on left boundary; get random # in range [delta_time, slice_time]:
        next_rand_time = time + random(delta_time, slice_time)

The 5 variables (time, delta_time, etc) are likely going to be data members of the class that uses the timer, and the callback will be a method of the class. Provide some code in your post for further details.

查看更多
4楼-- · 2019-08-26 06:43

Just keep track of the actual offset for each frame, and take that into account as you generate new event times:

void RunEvents(TimeSpan interval, TimeSpan duration)
{
    Random random = new Random();
    TimeSpan eventOffset = new TimeSpan();
    Stopwatch sw = Stopwatch.StartNew();

    while (sw.Elapsed < duration)
    {
        TimeSpan nextEvent = eventOffset +
            TimeSpan.FromSeconds(random.NextDouble() * interval.TotalSeconds);

        TimeSpan delay = nextEvent - sw.Elapsed;

        if (delay.Ticks > 0)
        {
            Thread.Sleep(delay);
        }

        eventOffset += interval;
    }
}

In other words, compute the nextEvent by adding the time left over in the previous interval after the previous event to the start time of the current interval, along with a random length of time within the actual interval.

Then, wait enough time between now and that next event.

Finally, update the offset and interval remainder so that they can be used for the next round.

Notes:

  1. The above assume you dispense with the timer itself completely, and use the above instead. If that's not appropriate, then you should be more specific about how the timer itself is supposed to relate to the events you are randomly generating.
  2. EDIT: I have a vague sense that I could have combined eventOffset and sincePrevious into a single value. But it's late here and I figure that's something easily left as an exercise for the reader. :) I finally figured out why this was bugging me: I don't need the sincePrevious in the above at all! Sigh. Code has been edited to correct for my mistake.
  3. The above uses Thread.Sleep() for the delay. IMHO, it would be better to make the method async and use Task.Delay() instead. But I wanted to keep the example simple, and there's no way to know from the question as asked what actually is the best way to handle the delay itself.
查看更多
登录 后发表回答