2015-01-04 171 views
1

我已經嘗試過詢問這個問題兩三次之前,但一直沒有能夠正確的階段,所以我想再試一次。我正在製作一個訓練秒錶應用程序。該應用程序的功能是計數10秒,讓受訓者10秒準備。一旦這段時間過去了,20秒鐘的時間內,受訓者需要20秒的艱苦訓練。之後,休息時間有10秒鐘。然後循環回20秒鍛鍊並繼續這個循環8輪。有問題的if語句

我的問題是,它將開始10秒的準備,但然後它循環回10秒計時器。出於某種原因,我的if else語句不斷循環回到準備時間。 我正在使用if語句的秒錶和時間跨度。

private void timer_Tick(object sender, EventArgs e) 
    { 
     //throw new NotImplementedException(); 
     //timer timespan is more than zero, start stopwatch(get the prepare counter going) 
     if (timerWatch.Elapsed < new TimeSpan(0, 0, 11))// if its 5sec 
     { 
      milllisecond = timerWatch.ElapsedMilliseconds; 
      second = milllisecond/1000; 
      milllisecond = milllisecond % 1000; 
      minute = second/60; 
      second = second % 60; 
      hour = minute/60; 
      minute = minute % 60; 
      txtblTime.Text = minute.ToString("00") + ":" + second.ToString("00"); 
     } 
     else if (timerWatch.Elapsed >= new TimeSpan(0, 0, 10) && timerWatch.Elapsed < new TimeSpan(0, 0, 21))//more than 4sec 
     { 
      timerWatch.Restart(); 

      milllisecond = timerWatch.ElapsedMilliseconds; 
      second = milllisecond/1000; 
      milllisecond = milllisecond % 1000; 
      minute = second/60; 
      second = second % 60; 
      hour = minute/60; 
      minute = minute % 60; 
      txtblTime.Text = minute.ToString("00") + ":" + second.ToString("00"); 

      txtblPrepare.Visibility = System.Windows.Visibility.Collapsed; 
      txtblGo.Visibility = System.Windows.Visibility.Visible; 
     } 
     else if (timerWatch.Elapsed < new TimeSpan(0, 0, 21)) 
     { 
      timerWatch.Restart(); 

      milllisecond = timerWatch.ElapsedMilliseconds; 
      second = milllisecond/1000; 
      milllisecond = milllisecond % 1000; 
      minute = second/60; 
      second = second % 60; 
      hour = minute/60; 
      minute = minute % 60; 

      txtblTime.Text = minute.ToString("00") + ":" + second.ToString("00"); 
      txtblGo.Visibility = System.Windows.Visibility.Collapsed; 
     } 
     else 
      txtblTime.Text = "Times Up!";      
    } 
+4

爲什麼不使用Enum跟蹤狀態或模式'{Prep,WorkOut,Rest}'並根據該類型的var設置定時器間隔。其他一些東西如切換控件也可能會影響價值。這樣,每當定時器關閉時,就會知道一個階段結束並前進到下一個階段。也許在開始週期/測試/比賽之前添加一個「無」。 – Plutonix

+2

最好使用某種狀態機設計問題,您正試圖實施。去谷歌上查詢。無論如何,你爲什麼重新啓動計時器。我認爲這是導致問題的原因,因爲定時器在第一種情況以外的情況下重置。 –

+0

什麼是定時器實例的類? –

回答

0

您正在使用

timer.Restart() 

其重置計時器,所以它再次執行第一種情況。檢查Stopwatch的MSDN文檔。這個答案當然假定你正在使用秒錶類定時器。

我認爲,它會至少執行一次這些情況以重置計時器。

3

以下是使用Enum跟蹤階段的要點。這似乎比跟蹤秒錶和TimeSpans更容易......當計時器關閉時,事情就會改變。

private enum Phases 
{ 
    Stopped, 
    Prep, 
    WorkOut, 
    Rest 
} 

private Phases thisPhase;  // phase tracker 
private int workOutCount;  // 8 cycle counter 

private void Timer1_Tick(object sender, EventArgs e) 
{ 
    Timer1.Enabled = false; 

    // ToDo: Fiddle with controls as needed 
    // also the durations...not sure if a new Prep 
    // follows the final rest or if they are the same 
    switch (thisPhase) { 
     case Phases.Stopped: 
      // start things off 
      thisPhase = Phases.Prep; 
      Timer1.Interval = 10000; 
      // prep time 
      break; 

     case Phases.Prep: 
      workOutCount = 1; 
      thisPhase = Phases.WorkOut; 
      Timer1.Interval = 20000; 
      // work out time 
      break; 

     case Phases.WorkOut: 
      thisPhase = Phases.Rest; 
      Timer1.Interval = 10000; 
      // rest time 
      break; 

     case Phases.Rest: 
      workOutCount += 1; 

      if (workOutCount == 8) { 
       thisPhase = Phases.Prep; 
       // perhaps to None, if there is an instruction timeout 
       Timer1.Interval = 10000; 
       // prep time 
       // actually means 10sec rest + 10 prep before next workout task 
      } else { 
       // next workout starts in... 
       Timer1.Interval = 10000; 
       // prep time 
      } 

      break; 
    } 
    Timer1.Enabled = true; 
} 

從VB轉換可能不完美,但它應該傳達的想法。

5

你試圖實施的是所謂的finite-state machine。推定這臺機器的狀態使計時器很難理解和閱讀代碼。我會以更直接的方式存儲狀態。作爲Plutonix說,使用枚舉

public enum TrainingState 
{ 
    Stopped, // The state machine is not working yet or has finished its work. 
    Preparing, 
    Working, 
    Resting 
} 

此外,您將需要一個計數器,用於循環

private TrainingState _state = TrainingState.Stopped; 
private int _roundNo; 

現在你可以制定狀態轉換這樣

private void ChangeState() 
{ 
    switch (_state) { 
     case TrainingState.Stopped: 
      //TODO: Initialize and start the timer, display state 
      _state = TrainingState.Preparing; 
      break; 
     case TrainingState.Preparing: 
      //TODO: Adjust timer intervall for working phase, display state 
      _roundNo = 1; // We are going into the first round 
      _state = TrainingState.Working; 
      break; 
     case TrainingState.Working: 
      //TODO: Adjust timer intervall for resting phase, display state 
      _state = TrainingState.Resting; 
      break; 
     case TrainingState.Resting: 
      if (_roundNo == 8) { 
       _state = TrainingState.Stopped; 
       //TODO: stop timer, display state 
      } else { 
       //TODO: Adjust timer intervall for working phase, display state 
       _roundNo++; // We are going into the next round 
       _state = TrainingState.Working; 
      } 
      break; 
    } 
} 

你會的數量必須在啓動時和內部調用此方法timer_Tick

private void timer_Tick(object sender, EventArgs e) 
{ 
    ChangeState(); 
} 

private void btnStart_Click(object sender, EventArgs e) 
{ 
    ChangeState(); 
} 
+0

對不起,請問,在timer_Tick啓動時和啓動時如何調用此方法? –

+0

我看你是怎麼開始的。如果您是通過單擊按鈕開始的,請在按鈕單擊事件處理程序中調用'ChangeState();'。否則,在窗體的構造函數或Form_Load事件中調用它。並在'timer_Click'中調用'ChangeState();'。 –