教程:向数学测验 WinForms 应用添加计时器
在本系列的四个教程中,你将创建一个数学测验。 测验包含四个随机数学问题,测验者需要尝试在指定的时间内回答这些问题。
测验使用计时器控件。 此控件背后的代码跟踪运行时间,并检查测验者的答案。
在第三个教程中,你将了解如何:
- 添加计时器控件。
- 为计时器添加事件处理程序。
- 编写代码以检查用户的答案、显示消息并填写正确的答案。
先决条件
本教程基于前面的教程(从创建数学测验 WinForms 应用开始)构建。 如果尚未完成这些教程,请先完成这些教程。
添加倒计时计时器
若要在测验期间持续跟踪时间,请使用计时器组件。 还需要一个变量来存储剩余的时间量。
添加名为“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 代码片段。
在“Windows 窗体设计器”中,将“工具箱”的“组件”类别中的 Timer 控件移到窗体中 。 此控件显示在设计窗口底部的灰色区域内。
在窗体中,请选择刚才添加的“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()
来检查测验者的答案。 它还检查测验已消耗的时间。
在窗体中,双击“计时器”控件,或将其选中,然后选择 Enter 键 。 这些操作将向计时器添加 Tick 事件处理程序。 代码编辑器将出现并显示 Tick 处理程序的方法。
将下面的语句添加到新事件处理程序方法。
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() 方法将开始倒计时。
运行应用
保存并运行程序。
选择“开始测验”。 计时器将开始倒计时。 当时间用完时,测验将结束,并显示答案。
开始另一个测验,并提供数学题的正确答案。 在时间限制内回答正确时,将出现一个消息框、开始按钮变为可用并且计时器停止。
后续步骤
请继续学习下一教程,了解如何自定义数学测验。