English 中文(简体)
Algorithm for count-down timer that can add on time
原标题:

I m making a general timer that has functionality to count up from 0 or count down from a certain number. I also want it to allow the user to add and subtract time. Everything is simple to implement except for the case in which the timer is counting down from some number, and the user adds or subtracts time from it.

For example: (m_clock is an instance of SFML s Clock)

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime;
  } else {
    m_elapsedTime -= 
      m_elapsedTime - m_startingTime + m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

To be a bit more clear, imagine that the timer starts at 100 counting down. After 10 seconds, the above function would look like 100 -= 100 - 100 + 10 which equals 90. If it was called after 20 more seconds it would look like 90 -= 90 - 100 + 30 which equals 70.

This works for normal counting, but if the user calls AddTime() ( just m_elapsedTime += arg ) then the algorithm for backwards counting fails miserably.

I know that I can do this using more members and keeping track of previous times, etc. but I m wondering whether I m missing some implementation that is extremely obvious. I d prefer to keep it as simple as possible in that single operation.

最佳回答

Your code is unnecessarily complex. The following is equivalent:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime = m_clock.GetElapsedTime();
  } else {
    m_elapsedTime = m_startingTime - m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

and hopefully illustrates why AddTime() doesn t work: m_elapsedTime is being replaced on every call to GetElapsedTime(). The simplest solution is track added/subtracted time separately and rework GetElapsedTime() thus:

float Timer::GetElapsedTime() {
  float elapsedTime = m_forward
                      ? m_clock.GetElapsedTime()
                      : m_startingTime - m_clock.GetElapsedTime();
  return elapsedTime + m_addedTime;
}
问题回答

If you want to increase the time remaining, you can simulate that by decreasing the amount of time elapsed.

Your arithmetic expressions are more complex than they need to be: m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime is equivalent to m_elapsedTime = m_clock.GetElapsedTime(), and m_elapsedTime -= m_elapsedTime - m_startingTime + m_clock.GetElapsedTime() is equivalent to m_elapsedTime = m_startingTime - m_clock.GetElapsedTime()`.

At this point, the problem is clear: the old value of m_elapsedTime never affects the subsequent result. I would consider adding in an offset field to handle any changes to the starting value of the timer. At this point, Timer:GetElapsedTime could just be the following:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    return offset + m_clock.GetElapsedTime();
  } else {
    return offset - m_clock.GetElapsedTime();
  }
}

where offset starts at 0 for a count-up and the start value for a count-down. Make sure and watch your signs for updating offset in AddTime()





相关问题
How to add/merge several Big O s into one

If I have an algorithm which is comprised of (let s say) three sub-algorithms, all with different O() characteristics, e.g.: algorithm A: O(n) algorithm B: O(log(n)) algorithm C: O(n log(n)) How do ...

Grokking Timsort

There s a (relatively) new sort on the block called Timsort. It s been used as Python s list.sort, and is now going to be the new Array.sort in Java 7. There s some documentation and a tiny Wikipedia ...

Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Enumerating All Minimal Directed Cycles Of A Directed Graph

I have a directed graph and my problem is to enumerate all the minimal (cycles that cannot be constructed as the union of other cycles) directed cycles of this graph. This is different from what the ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签