簡體   English   中英

有問題的if陳述

[英]Problematic if-Statement

我已經嘗試過兩次或三次問這個問題,但無法正確地定相,所以我想再嘗試一次。 我正在制作訓練秒表應用程序。 該應用程序的功能是計數10秒,讓學員有10秒的准備時間。 時間到了20秒后,學員將在20秒內進行艱苦的鍛煉。 之后,有10秒的休息時間。 然后循環回到20秒鍛煉,並繼續此循環8輪。

我的問題是它將開始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!";                    
    }

您試圖實現的是所謂的有限狀態機 通過計時器來推斷本機的狀態使得很難理解和閱讀代碼。 我將以更直接的方式存儲狀態。 正如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();
}

這是使用枚舉跟蹤階段的要點。 這似乎比跟蹤秒表和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進行轉換可能並不完美,但是應該可以傳達這種想法。

您正在使用

timer.Restart()

這將重置計時器,因此它將再次執行第一種情況。 查看Stopwatch的MSDN文檔。 當然,此答案假設您正在使用Stopwatch類作為計時器。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM