Share via


教程:向数学测验 WinForms 应用添加计时器

在本系列的四个教程中,你将创建一个数学测验。 测验包含四个随机数学问题,测验者需要尝试在指定的时间内回答这些问题。

测验使用计时器控件。 此控件背后的代码跟踪运行时间,并检查测验者的答案。

在第三个教程中,你将了解如何:

  • 添加计时器控件。
  • 为计时器添加事件处理程序。
  • 编写代码以检查用户的答案、显示消息并填写正确的答案。

先决条件

本教程基于前面的教程(从创建数学测验 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;
    

重要

使用此页右上角的编程语言控件查看 C# 代码片段或 Visual Basic 代码片段。

Programming language control for Microsoft Learn

  1. 在“Windows 窗体设计器”中,将“工具箱”的“组件”类别中的 Timer 控件移到窗体中 。 此控件显示在设计窗口底部的灰色区域内。

  2. 在窗体中,请选择刚才添加的“timer1”图标,并将其“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。 在这种情况下,如果值都正确,则方法返回值 true。 否则,此方法将返回值 false

  • if 语句使用 NumericUpDown 控件的 Value 属性访问控件的当前值。 下一部分使用相同的属性在每个控件中显示正确答案。

向计时器添加事件处理程序

现已具有检查答案的方法,接下来可以编写 Tick 事件处理程序的代码。 在计时器引发 Tick 事件后,此代码每秒运行一次。 此事件处理程序通过调用 CheckTheAnswer() 来检查测验者的答案。 它还检查测验已消耗的时间。

  1. 在窗体中,双击“计时器”控件,或将其选中,然后选择 Enter 键 。 这些操作将向计时器添加 Tick 事件处理程序。 代码编辑器将出现并显示 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 秒 。 然后,Timer 控件的 Start() 方法将开始倒计时。

运行应用

  1. 保存并运行程序。

  2. 选择“开始测验”。 计时器将开始倒计时。 当时间用完时,测验将结束,并显示答案。

  3. 开始另一个测验,并提供数学题的正确答案。 在时间限制内回答正确时,将出现一个消息框、开始按钮变为可用并且计时器停止。

    Screenshot that shows a completed quiz with 19 seconds remaining. The Start the quiz button is available.

后续步骤

请继续学习下一教程,了解如何自定义数学测验。