Step 3: Assign a Random Icon to Each Label

If the game always hides the same icons in the same locations, it's not challenging. You need to assign the icons randomly to the Label controls in your form. To do that, you add an AssignIconsToSquares() method.

To assign a random icon to each label

  1. Before adding the following code, consider how the method works. There's a new keyword: foreach in Visual C# and For Each in Visual Basic. (One of the lines is commented out on purpose, which is explained at the end of this procedure.)

    ''' <summary>
    ''' Assign each icon from the list of icons to a random square
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AssignIconsToSquares()
    
        ' The TableLayoutPanel has 16 labels,
        ' and the icon list has 16 icons,
        ' so an icon is pulled at random from the list
        ' and added to each label
        For Each control In TableLayoutPanel1.Controls
            Dim iconLabel = TryCast(control, Label)
            If iconLabel IsNot Nothing Then
                Dim randomNumber = random.Next(icons.Count)
                iconLabel.Text = icons(randomNumber)
                ' iconLabel.ForeColor = iconLabel.BackColor
                icons.RemoveAt(randomNumber)
            End If
        Next
    
    End Sub
    
    /// <summary>
    /// Assign each icon from the list of icons to a random square
    /// </summary>
    private void AssignIconsToSquares()
    {
        // The TableLayoutPanel has 16 labels,
        // and the icon list has 16 icons,
        // so an icon is pulled at random from the list
        // and added to each label
        foreach (Control control in tableLayoutPanel1.Controls)
        {
            Label iconLabel = control as Label;
            if (iconLabel != null)
            {
                int randomNumber = random.Next(icons.Count);
                iconLabel.Text = icons[randomNumber];
                // iconLabel.ForeColor = iconLabel.BackColor;
                icons.RemoveAt(randomNumber);
            }
        }
    } 
    
  2. Add the AssignIconsToSquares() method as shown in the previous step. You can put it just below the code you added in Step 2: Add a Random Object and a List of Icons.

    There's something new in your AssignIconsToSquares() method: a foreach loop in Visual C# and For Each in Visual Basic. You use a For Each loop any time you want to do the same action again and again. In this case, you want to execute the same statements for every label in your TableLayoutPanel, as explained by the following code. The first line creates a variable named control that stores each control one at a time while that control has the statements in the loop executed on it.

    For Each control In TableLayoutPanel1.Controls
        ' The statements you want to execute 
        ' for each label go here
        ' The statements use iconLabel to access 
        ' each label's properties and methods
    Next
    
    foreach (Control control in tableLayoutPanel1.Controls)
    {
        // The statements you want to execute 
        // for each label go here
        // The statements use iconLabel to access 
        // each label's properties and methods
    }
    

    Note

    The names iconLabel and control are used because they are descriptive. You could replace these names with any names, and it would work exactly the same as long as you changed the name in each statement inside the loop.

    The AssignIconsToSquares() method goes through each Label control in the TableLayoutPanel and executes the same statements for each of them. Those statements pull a random icon from the list that you added in Step 2: Add a Random Object and a List of Icons. (That's why you included two of each icon in the list, so there would be a pair of icons assigned to random Label controls.)

    Look more closely at the code that runs inside the foreach or For Each loop. This code is reproduced here.

    Dim iconLabel = TryCast(control, Label)
    If iconLabel IsNot Nothing Then
        Dim randomNumber = random.Next(icons.Count)
        iconLabel.Text = icons(randomNumber)
        ' iconLabel.ForeColor = iconLabel.BackColor
        icons.RemoveAt(randomNumber)
    End If
    
    Label iconLabel = control as Label;
    if (iconLabel != null)
    {
        int randomNumber = random.Next(icons.Count);
        iconLabel.Text = icons[randomNumber];
        // iconLabel.ForeColor = iconLabel.BackColor;
        icons.RemoveAt(randomNumber);
    }
    

    The first line converts the control variable to a Label named iconLabel. The line after that is an if statement that checks to make sure the conversion worked. If the conversion does work, the statements in the if statement run. The first line in the if statement creates a variable named randomNumber that contains a random number that corresponds to one of the items in the icons list. To do this, it uses the Next method of the Random object that you created earlier. The Next method returns the random number. This line also uses the Count property of the icons list to determine the range from which to choose the random number. The next line assigns one of the icon list items to the Text property of the label. The commented-out line is explained later in this topic. Finally, the last line in the if statement removes from the list the icon that has been added to the form.

    Remember, if you're not sure about what some part of the code does, you can rest the mouse pointer over a code element and review the resulting tooltip.

  3. You need to call the AssignIconsToSquares() method as soon as the program starts. If writing Visual C# code, add a statement just below the call to the InitializeComponent() method in the Form1 constructor, so your form calls your new method to set itself up before it's shown.

    public Form1()
    {
        InitializeComponent();
    
        AssignIconsToSquares();
    }
    

    For Visual Basic, first add the constructor, and then add the method call to the constructor. Before the AssignIconsToSquares() method you just created, start by typing the code Public Sub New(). When you press the ENTER key to move to the next line, IntelliSense should make the following code appear to complete the constructor.

    Public Sub New()
        ' This call is required by Windows Form Designer
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call
    End Sub
    

    Add the AssignIconsToSquares() method call so your constructor looks like the following.

    Public Sub New()
        ' This call is required by Windows Form Designer
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call
        AssignIconsToSquares()
    End Sub
    
  4. Save your program and run it. It should show a form with random icons assigned to each label.

  5. Close your program, and then run it again. Now different icons are assigned to each label, as shown in the following picture.

    Matching game with random icons

    Matching game with random icons

  6. Now stop the program and uncomment that line of code inside the For Each loop.

    iconLabel.ForeColor = iconLabel.BackColor
    
    iconLabel.ForeColor = iconLabel.BackColor;
    
  7. Click the Save All toolbar button to save your program, and then run it. The icons seem to have disappeared—only a blue background appears. However, the icons are randomly assigned and are still there. Because the icons are the same color as the background, they're invisible.

To continue or review