Step 6: Add a Timer

接下来,你要向匹配游戏中添加**“Timer”**控件。计时器等待指定的毫秒数后,触发一个称为“Tick”的事件。这对于启动操作或定时重复操作很有用。在本例中,你将使用一个计时器,让玩家开始选择两个图标,而如果图标不匹配,则在短暂时间后再次隐藏这两个图标。

添加计时器

  1. 在 Windows 窗体设计器中的工具箱中,请选择**“Timer”(位于“组件”类别中),然后按 Enter 键,或双击该计时器,向窗体中添加一个计时器控件。该计时器的图标名为“Timer1”**,应显示在窗体下的空间中,如下图所示。

    Timer

    计时器

    说明说明

    如果工具箱是空的,请确保在打开工具箱前选择窗体设计器,而不是窗体的后台代码。

  2. 选择**“Timer1”图标以选中该计时器。在“属性”窗口中,从查看事件切换到查看属性。然后将计时器的“Interval”属性设置为 750,但保留“Enabled”属性的设置“False”“Interval”**属性将通知计时器两个计时周期之间的等待时长,或何时触发 Tick 事件。值为 750 时,将通知计时器等待四分之三秒(750 毫秒)后触发 Tick 事件。只有在玩家选择第二个标签后,你才能调用 Start() 方法启动计时器。

  3. 选择 Windows 窗体设计器中的计时器控件,然后按 Enter 键或双击该计时器,以添加空的**“Tick”**事件处理程序。用下列代码替换该代码,或手动将下列代码输入到事件处理程序。

    ''' <summary> 
    ''' This timer is started when the player clicks  
    ''' two icons that don't match, 
    ''' so it counts three quarters of a second  
    ''' and then turns itself off and hides both icons 
    ''' </summary> 
    ''' <remarks></remarks> 
    Private Sub Timer1_Tick() Handles Timer1.Tick
    
        ' Stop the timer
        Timer1.Stop()
    
        ' Hide both icons
        firstClicked.ForeColor = firstClicked.BackColor
        secondClicked.ForeColor = secondClicked.BackColor
    
        ' Reset firstClicked and secondClicked  
        ' so the next time a label is 
        ' clicked, the program knows it's the first click
        firstClicked = Nothing
        secondClicked = Nothing 
    
    End Sub
    
    /// <summary> 
    /// This timer is started when the player clicks  
    /// two icons that don't match, 
    /// so it counts three quarters of a second  
    /// and then turns itself off and hides both icons 
    /// </summary> 
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void timer1_Tick(object sender, EventArgs e)
    {
        // Stop the timer
        timer1.Stop();
    
        // Hide both icons
        firstClicked.ForeColor = firstClicked.BackColor;
        secondClicked.ForeColor = secondClicked.BackColor;
    
        // Reset firstClicked and secondClicked  
        // so the next time a label is 
        // clicked, the program knows it's the first click
        firstClicked = null;
        secondClicked = null;
    }
    

    Tick 事件处理程序将执行三个操作:首先,通过调用 Stop() 方法确保计时器没有运行。然后,它使用两个引用变量 firstClicked 和 secondClicked,使得玩家选择的两个标签的图标再次不可见。最后,它将 firstClicked 和 secondClicked 引用变量重置为 null(Visual C# 中)或 Nothing(Visual Basic 中)。这一步很重要,因为程序本身就是这样重置的。现在,它不跟踪任何 Label 控件,并已准备好让玩家再次选择图标。

    说明说明

    Timer 对象具有 Start() 方法和 Stop() 方法,分别用以启动和停止计时器。如果你在“属性”窗口中将计时器的“Enabled”属性设置为“True”,则只要程序开始运行,计时器就会开始计时。但是,如果保留该属性的设置“False”,则计时器将在 Start() 方法调用之后开始计时。通常,计时器会使用“Interval”属性确定在计时周期之间等待的毫秒数,从而反复触发其 Tick 事件。你可能已经注意到在 Tick 事件中调用计时器的 Stop() 方法的方式。这会将计时器置于“单触发模式”,意味着 Start() 方法调用时,计时器会等待指定的间隔时间,触发单个 Tick 事件,然后停止。

  4. 若要查看正在使用的新计时器,请转至代码编辑器,将以下代码添加到 label_Click() 事件处理程序方法的顶部和底部。(你要将 if 语句添加到顶部,将三个语句添加到底部;该方法的其余部分保持相同。)

    ''' <summary> 
    ''' Every label's Click event is handled by this event handler 
    ''' </summary> 
    ''' <param name="sender">The label that was clicked</param> 
    ''' <param name="e"></param> 
    ''' <remarks></remarks> 
    Private Sub label_Click(ByVal sender As System.Object, 
                            ByVal e As System.EventArgs) Handles Label9.Click, 
        Label8.Click, Label7.Click, Label6.Click, Label5.Click, Label4.Click,  
        Label3.Click, Label2.Click, Label16.Click, Label15.Click, Label14.Click, 
        Label13.Click, Label12.Click, Label11.Click, Label10.Click, Label1.Click
    
        ' The timer is only on after two non-matching  
        ' icons have been shown to the player,  
        ' so ignore any clicks if the timer is running 
        If Timer1.Enabled Then Exit Sub 
    
        Dim clickedLabel = TryCast(sender, Label)
    
        If clickedLabel IsNot Nothing Then 
            ' If the clicked label is black, the player clicked 
            ' an icon that's already been revealed -- 
            ' ignore the click 
            If clickedLabel.ForeColor = Color.Black Then Exit Sub 
    
            ' If firstClicked is Nothing, this is the first icon  
            ' in the pair that the player clicked,  
            ' so set firstClicked to the label that the player  
            ' clicked, change its color to black, and return 
            If firstClicked Is Nothing Then
                firstClicked = clickedLabel
                firstClicked.ForeColor = Color.Black
                Exit Sub 
            End If 
    
            ' If the player gets this far, the timer isn't  
            ' running and firstClicked isn't Nothing,  
            ' so this must be the second icon the player clicked 
            ' Set its color to black
            secondClicked = clickedLabel
            secondClicked.ForeColor = Color.Black
    
            ' If the player gets this far, the player  
            ' clicked two different icons, so start the  
            ' timer (which will wait three quarters of  
            ' a second, and then hide the icons)
            Timer1.Start()
        End If 
    
    End Sub
    
    /// <summary> 
    /// Every label's Click event is handled by this event handler 
    /// </summary> 
    /// <param name="sender">The label that was clicked</param>
    /// <param name="e"></param>
    private void label_Click(object sender, EventArgs e)
    {
        // The timer is only on after two non-matching  
        // icons have been shown to the player,  
        // so ignore any clicks if the timer is running 
        if (timer1.Enabled == true)
            return;
    
        Label clickedLabel = sender as Label;
    
        if (clickedLabel != null)
        {
            // If the clicked label is black, the player clicked 
            // an icon that's already been revealed -- 
            // ignore the click 
            if (clickedLabel.ForeColor == Color.Black)
                return;
    
            // If firstClicked is null, this is the first icon 
            // in the pair that the player clicked,  
            // so set firstClicked to the label that the player  
            // clicked, change its color to black, and return 
            if (firstClicked == null)
            {
                firstClicked = clickedLabel;
                firstClicked.ForeColor = Color.Black;
                return;
            }
    
            // If the player gets this far, the timer isn't 
            // running and firstClicked isn't null, 
            // so this must be the second icon the player clicked 
            // Set its color to black
            secondClicked = clickedLabel;
            secondClicked.ForeColor = Color.Black;
    
            // If the player gets this far, the player  
            // clicked two different icons, so start the  
            // timer (which will wait three quarters of  
            // a second, and then hide the icons)
            timer1.Start();
        }
    }
    

    该方法顶部的代码通过检查**“Enabled”**属性的值来检查计时器是否已启动。这样,如果玩家选择第一个和第二个 Label 控件,且计时器启动,则选择第三个控件将不会执行任何操作。

    该方法底部的代码将 secondClicked 引用变量设置为跟踪玩家选择的第二个 Label 控件,然后将该标签的图标颜色设置为黑色以使其可见。然后,它在单触发模式下启动计时器,以便在等待 750 毫秒后触发单个 Tick 事件。计时器的 Tick 事件处理程序会隐藏这两个图标,并重置 firstClicked 和 secondClicked 引用变量,以便窗体准备就绪以供玩家选择另一对图标。

  5. 保存并运行程序。选择一个图标,它将显示出来。

  6. 选择另一个图标。它会短暂显示,然后两个图标都消失。多次重复此操作。窗体现在跟踪你选择的第一个和第二个图标,并使用计时器在使图标消失之前暂停。

继续或查看