共用方式為


教學課程:將定時器新增至數學測驗 WinForms 應用程式

在本系列四個教學課程中,您將製作數學測驗。 測驗包含四個隨機數學問題,測驗者會嘗試在指定的時間內回答。

測驗使用定時器控件。 此控件背後的程式代碼會追蹤經過的時間,並檢查測驗者答案。

在本第三個教學課程中,您將瞭解如何:

  • 將定時器控件新增至 Windows Forms 應用程式。
  • 為定時器新增事件處理程式。
  • 撰寫程式代碼來檢查使用者的答案、顯示訊息,並填入正確的答案。

先決條件

本教學課程是以先前的教學課程為基礎,從 建立數學測驗 WinForms 應用程式開始。 如果您尚未完成這些教學課程,請先完成這些教學課程。

新增倒數定時器

若要追蹤測驗期間的時間,您可以使用定時器元件。 您也需要變數來儲存剩餘的時間量。

  1. 新增名為 timeLeft 的整數變數,其方式與您在先前教學課程中宣告變數的方式相同。 將 timeLeft 宣告放在其他宣告之後。 您的程式代碼看起來應該像下列範例。

    public partial class Form1 : Form
    {
        // Create a Random object called randomizer 
        // to generate random numbers.
        Random randomizer = new Random();
    
        // These integer variables store the numbers 
        // for the addition problem. 
        int addend1;
        int addend2;
    
        // These integer variables store the numbers 
        // for the subtraction problem. 
        int minuend;
        int subtrahend;
    
        // These integer variables store the numbers 
        // for the multiplication problem. 
        int multiplicand;
        int multiplier;
    
        // These integer variables store the numbers 
        // for the division problem. 
        int dividend;
        int divisor;
    
        // This integer variable keeps track of the 
        // remaining time.
        int timeLeft;
    

  1. Windows Forms 設計工具中,將 Timer 控件從 工具箱元件 類別移動到您的表單。 控件會出現在設計視窗底部的灰色區域中。

  2. 在表單上,選取您剛才新增的定時器圖示,並將其 Interval 屬性設定為 1000。 由於此間隔以毫秒為單位,因此值 1000 會導致定時器每秒引發 Tick 事件。

檢查答案

因為定時器會每秒引發 Tick 事件,所以檢查 Tick 事件處理程式中經過的時間是合理的。 檢查該事件處理程式中的答案也很實用。 如果時間用完,或答案正確,測驗應該結束。

在您撰寫該事件處理程式之前,請新增名為 CheckTheAnswer() 的方法,以判斷數學問題的解答是否正確。 這個方法應該與其他方法一致,例如 StartTheQuiz()。 您的程式代碼看起來應該像下列範例。

/// <summary>
/// Check the answers to see if the user got everything right.
/// </summary>
/// <returns>True if the answer's correct, false otherwise.</returns>
private bool CheckTheAnswer()
{
    if ((addend1 + addend2 == sum.Value)
        && (minuend - subtrahend == difference.Value)
        && (multiplicand * multiplier == product.Value)
        && (dividend / divisor == quotient.Value))
        return true;
    else
        return false;
}

此方法會決定數學問題的解答,並將結果與 NumericUpDown 控件中的值進行比較。 在此程式代碼中:

  • Visual Basic 版本會使用 Function 關鍵詞,而不是一般的 Sub 關鍵詞,因為此方法會傳回值。

  • 您無法使用鍵盤輕鬆輸入乘法符號(×)或除號(÷),因此 C# 和 Visual Basic 接受星號(*)進行乘法,並接受除法的斜線標記(/)。

  • 在 C# 中,&&logical and 運算符。 在 Visual Basic 中,對等運算子為 AndAlso。 您可以使用 logical and 運算子來檢查多個條件是否成立。 在此情況下,如果值都正確,此方法會傳回 true的值。 否則,方法會傳回 false的值。

  • if 語句會使用 NumericUpDown 控件的 Value 屬性來存取控件目前的值。 在下一節中,您會使用相同的 屬性,在每個控件中顯示正確的答案。

將事件處理程式新增至定時器

既然您已經有辦法檢查答案,您可以撰寫 Tick 事件處理程式的程式代碼。 此程式代碼會在定時器引發 Tick 事件之後每秒執行一次。 這個事件處理程式會呼叫 CheckTheAnswer()來檢查測驗者答案。 它也會檢查測驗中經過多少時間。

  1. 在窗體上,按兩下 Timer 控件,或選取它,然後選取 [Enter]。 這些動作會新增 Tick 事件處理程式。 程式代碼編輯器隨即出現,並顯示 Tick 處理程式的方法。

    針對 C#,它會在連結事件處理程式的 Form1.Designer.cs 程式代碼檔案中新增一行程式代碼:

    timer1.Tick += new EventHandler(timer1_Tick);
    

    針對 Visual Basic,不需要該行,但事件處理程式包含執行相同動作的 handles Timer1.Tick

  2. 將下列語句新增至新的事件處理程式方法。

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (CheckTheAnswer())
        {
            // If CheckTheAnswer() returns true, then the user 
            // got the answer right. Stop the timer  
            // and show a MessageBox.
            timer1.Stop();
            MessageBox.Show("You got all the answers right!",
                            "Congratulations!");
            startButton.Enabled = true;
        }
        else if (timeLeft > 0)
        {
            // If CheckTheAnswer() returns false, keep counting
            // down. Decrease the time left by one second and 
            // display the new time left by updating the 
            // Time Left label.
            timeLeft = timeLeft - 1;
            timeLabel.Text = timeLeft + " seconds";
        }
        else
        {
            // If the user ran out of time, stop the timer, show
            // a MessageBox, and fill in the answers.
            timer1.Stop();
            timeLabel.Text = "Time's up!";
            MessageBox.Show("You didn't finish in time.", "Sorry!");
            sum.Value = addend1 + addend2;
            difference.Value = minuend - subtrahend;
            product.Value = multiplicand * multiplier;
            quotient.Value = dividend / divisor;
            startButton.Enabled = true;
        }
    }
    

方法會在測驗進行期間的每一秒執行。 程式代碼會先檢查 CheckTheAnswer() 傳回的值。

  • 如果所有答案都正確,該值會 true,而測驗會結束:

    • 定時器會停止。
    • 賀電隨即出現。
    • startButton 控件的 Enabled 屬性會設定為 true,讓測驗者可以啟動另一個測驗。
  • 如果 CheckTheAnswer() 傳回 false,程式代碼會檢查 timeLeft 的值

    • 如果這個變數大於 0,定時器會從 timeLeft 減 1。 它也會更新 timeLabel 控件的 Text 屬性,以顯示測驗者剩餘的秒數。
    • 如果時間已經用完,定時器會停止並變更timeLabel 文字為時間到了! 消息框宣布測驗結束,並顯示答案。 [開始] 按鈕會再次可供使用。

啟動定時器

若要在測驗開始時啟動定時器,請將三行新增至 StartTheQuiz() 方法的結尾,如下列範例所示。

/// <summary>
/// Start the quiz by filling in all of the problem 
/// values and starting the timer. 
/// </summary>
public void StartTheQuiz()
{
    // Fill in the addition problem.
    // Generate two random numbers to add.
    // Store the values in the variables 'addend1' and 'addend2'.
    addend1 = randomizer.Next(51);
    addend2 = randomizer.Next(51);

    // Convert the two randomly generated numbers
    // into strings so that they can be displayed
    // in the label controls.
    plusLeftLabel.Text = addend1.ToString();
    plusRightLabel.Text = addend2.ToString();

    // 'sum' is the name of the NumericUpDown control.
    // This step makes sure its value is zero before
    // adding any values to it.
    sum.Value = 0;

    // Fill in the subtraction problem.
    minuend = randomizer.Next(1, 101);
    subtrahend = randomizer.Next(1, minuend);
    minusLeftLabel.Text = minuend.ToString();
    minusRightLabel.Text = subtrahend.ToString();
    difference.Value = 0;

    // Fill in the multiplication problem.
    multiplicand = randomizer.Next(2, 11);
    multiplier = randomizer.Next(2, 11);
    timesLeftLabel.Text = multiplicand.ToString();
    timesRightLabel.Text = multiplier.ToString();
    product.Value = 0;

    // Fill in the division problem.
    divisor = randomizer.Next(2, 11);
    int temporaryQuotient = randomizer.Next(2, 11);
    dividend = divisor * temporaryQuotient;
    dividedLeftLabel.Text = dividend.ToString();
    dividedRightLabel.Text = divisor.ToString();
    quotient.Value = 0;

    // Start the timer.
    timeLeft = 30;
    timeLabel.Text = "30 seconds"; 
    timer1.Start();
}

當您的測驗開始時,此程式代碼會將 timeLeft 變數設定為 30,並將 timeLabel 控件的 Text 屬性設定為 30 秒。 然後定時器控件的 Start() 方法會啟動倒數計時。

執行您的應用程式

  1. 儲存程式並加以執行。

  2. 選擇 開始測驗。 定時器會開始倒數。 當時間用完時,測驗會結束,答案隨即出現。

  3. 開始另一個測驗,並提供數學問題的正確答案。 當您在時間限制內正確回答時,消息框隨即開啟、開始按鈕可供使用,定時器會停止。

    顯示已完成測驗且剩餘 19 秒的螢幕快照。[開始測驗] 按鈕可供使用。

下一步

前進到下一個教學課程,以瞭解如何自定義數學測驗。