Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

(Beginner) Form label variable help 4

Status
Not open for further replies.

JohnnyT

Programmer
Jul 18, 2001
167
GB
Hi all,

I'm new to C# but I'm really enjoying learning it. I've just started a little exercise to try and make a BlackJack simulator. Using 'Lists' to hold the cards etc.

My form shows the possible 5 cards that the Player can hold as Labels (PlayerCard1, PlayerCard2, PlayerCard3 etc).

I want to do something like this:
for(i = 0; i < player1.PlayerCards.Count; i++) {
PlayerCard.Text = player1.PlayerCards.ShowCard();
}

Notice the "PlayerCard" bit in the for loop.
How can I add a variable to a name so that it will loop through all my labels ?

Is it even possible??

Many thanks for any light you can shed on this.

John ;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
Hi Kss444

Thanks for the links.

I don't need to loop through every control on my form, just the labels.

Basically I want to set the labels .text property to show the card that the player holds.

If I have 4 labels called PlayerCard1, PlayerCard2 etc.

I would like something like:
for(i=0; i < 4; i++) {
PlayerCard(i).Text = "My Label Text";
}

I hope this example is clearer. I'm not sure if your links answered this they kind of delved a little deeper into the murky waters of C# then I've dared to venture yet, but they seemed like they were using a sledgehammer to crack a walnut.

Is there no 'easy' way to achieve something like this?

Thanks again for all your help.

John ;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
place the cards in a list when the form is initialized and then loop through the list when necessary. personally, I don't see any value in this, but you want it...
Code:
class MyForm : Form
{
   private readonly List<Label> labels;

   public MyForm()
   {
      labels = new List<Labels>
                 {
                    PlayerCard1,
                    PlayerCard2,
                    PlayerCard3,
                    PlayerCard4,
                 };
   }


   public void DoSomething()
   {
       foreach(var label in labels)
       {
            label.Text = ...;
       }
   }
}

Jason Meckley
Programmer
Specialty Bakers, Inc.

faq855-7190
faq732-7259
 
I think you are looking for something like this:

Code:
for(i = 0; i < player1.PlayerCards.Count; i++) {
    this.Controls["PlayerCard" + i.ToString()].Text = "value or whatever";
}

=======================================
People think it must be fun to be a super genius, but they don't realize how hard it is to put up with all the idiots in the world. (Calvin from Calvin And Hobbs)

Robert L. Johnson III
CCNA, CCDA, MCSA, CNA, Net+, A+, CHDP
VB.NET Programmer
 
mstrmage1768,

That is exactly what I was after! Thank you so much for that.

jmeckley, thanks for you answer. I've just been learning about lists but didn't think of using one for this. Many thanks.

Thanks for everyones help

;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
You could create your own Card and Deck user controls and use them together. I got a bit carried away so sorry if it is too complex but here is an example:
Code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;

public enum CardSuit
{
    Hearts, Diamonds, Clubs, Spades
}

public enum CardFace
{
    Ace, Two, Three, Four, Fiv, Six, Seven, Eight, Nine, Ten, Jack, Queen, King
}

public class Card : Control
{
    // Constructors not public as we only want creation through a Deck.
    protected internal Card(int value) : this(value, (CardSuit)(value % 4), (CardFace)(value / 4)) { }
    protected internal Card(CardSuit suit, CardFace face) : this((int)suit * (int)face, suit, face) { }

    // Both of the above constructors call this one.
    private Card(int value, CardSuit suit, CardFace face)
    {
        if (value < 0 || value > 51)
            throw new ArgumentException("The card's value must be between 0 and 51 inclusive.");

        this.Value = value;
        this.Suit = suit;
        this.Face = face;

        SetDisplayProperties();
    }

    protected virtual void SetDisplayProperties()
    {
        this.BackColor = Color.White;
        this.Text = this.ToString();
        this.Size = new Size(110, 20);
    }

    // Read only properties as we do not want the card's value to change once it's been created.
    public CardSuit Suit { get; private set; }
    public CardFace Face { get; private set; }
    public int Value { get; private set; }

    // Return a friendly card name, i.e. "Ace of Spades".
    public override string ToString()
    {
        return Enum.GetName(typeof(CardFace), Face) + " of " + Enum.GetName(typeof(CardSuit), Suit);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawString(this.ToString(), this.Font, new SolidBrush(this.ForeColor), 3, 3);
    }
}

public static class Deck
{
    private static List<Card> cards = new List<Card>() {
        new Card(0), new Card(1), new Card(2), new Card(3), new Card(4), new Card(5), 
        new Card(6), new Card(7), new Card(8), new Card(9), new Card(10), new Card(11), 
        new Card(12), new Card(13), new Card(14), new Card(15), new Card(16), new Card(17), 
        new Card(18), new Card(19), new Card(20), new Card(21), new Card(22), new Card(23), 
        new Card(24), new Card(25), new Card(26), new Card(27), new Card(28), new Card(29), 
        new Card(30), new Card(31), new Card(32), new Card(33), new Card(34), new Card(35), 
        new Card(36), new Card(37), new Card(38), new Card(39), new Card(40), new Card(41), 
        new Card(42), new Card(43), new Card(44), new Card(45), new Card(46), new Card(47), 
        new Card(48), new Card(49), new Card(50), new Card(51)};


    private static int cardsDealt;

    public static void Reset()
    {
        Shuffle();
        cardsDealt = 0;
    }

    private static Card CardFromPosition(int position)
    {
        return cards[position];
    }

    public static Card GetNextCard()
    {
        cardsDealt++;
        return CardFromPosition(cardsDealt - 1);
    }

    public static void Shuffle()
    {
        Shuffle(500);
    }

    public static void Shuffle(int iterations)
    {
        Card cardPlaceHolder;
        Random random = new Random();

        for (int i = 0; i < iterations; i++)
        {
            int position1 = random.Next(0, 51);
            int position2 = random.Next(0, 51);

            // Make sure the positions are different
            while (position1.Equals(position2))
            {
                position2 = random.Next(0, 51);
            }

            cardPlaceHolder = cards[position1];
            cards[position1] = cards[position2];
            cards[position2] = cardPlaceHolder;
        }
    }

    public static int CardsRemaining()
    {
        return cards.Count - cardsDealt;
    }

    public static Card Peek()
    {
        return Peek(1);
    }

    public static Card Peek(int depth)
    {
        if (depth < 1 || depth > CardsRemaining())
            throw new ArgumentException(string.Format("There are {0} cards remaining.  You cannot peek to a depth of {1}.", CardsRemaining().ToString(), depth.ToString()), "depth");

        return CardFromPosition(cardsDealt + (depth-1));
    }
}

You would then use them like this:
Code:
// Shuffles the deck (can pass in number of iterations if needed).
Deck.Shuffle();
Code:
// Retrieves a card from the deck.
Card card = Deck.GetNextCard();
Code:
// Gets the next card, but does not remove it from the deck.
Card card = Deck.Peek(); // Can pass in an integer here for depth.
 
PGO01,

Wow! I've been trying to get my head around your code but it is still a bit above me.

Could you briefly explain the Card constructors to me.

Code:
 // Constructors not public as we only want creation through a Deck.
    protected internal Card(int value) : this(value, (CardSuit)(value % 4), (CardFace)(value / 4)) { }
    protected internal Card(CardSuit suit, CardFace face) : this((int)suit * (int)face, suit, face) { }

    // Both of the above constructors call this one.
    private Card(int value, CardSuit suit, CardFace face)
    {
 // rest of code
}

I'm not sure how you can then instantiate a new card in your list (in the Deck class) with just new Card(0).

The constructor seems to want an int,CardSuit,CardFace.

I presume the "protected internal" constructors of the same name are doing something but I'm not sure what...?

Thanks for your code. It is great to see how things 'should be done'.

;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
Yes you are right, I've overloaded the constructor, which means the Card can be created by calling any of the 2 constructors:
Code:
new Card(0);

new Card(CardSuit.Hearts, CardFace.King);
Both of these call the private constructor that takes the 3 arguments. The 3 arguments are worked out from the 1 or 2 arguments that have been given:
Code:
new Card(25);
The above would create Six of Diamonds like this:

25 is passed in to the constructor:
Code:
protected internal Card(int value) : this(value, (CardSuit)(value % 4), (CardFace)(value / 4))
{
}
From the 1 argument (value: 25) the suit and face are worked out like this:
Code:
(CardSuit)(value % 4) // 25 mod 4 = 1 (Diamonds)
(CardFace)(value / 4) // 25 / 4 = 6 (Six)
And so, these together with the value are passed to the private constructor, and you have a new Card().
Code:
private Card(int value, CardSuit suit, CardFace face)
{
    // In this example, this constructor would eventually be called with the arguments:
    // 25
    // CardSuit.Diamonds
    // CardFace.Six
}
 
PGO01,

Ahhh... I think I need to do some reading on protected internal constructors.

Why does your Card class also have : Control ?

I can't see a Control class that it inherits from and I can't see a Control interface that it could implement? Is Control a class or interface that is embedded in .NET or something?

Sorry for all these questions but your example has really intrigued (and puzzled) me.

;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
No problem - glad to help.
Code:
public Class Dog : Animal
{
}
In the above example, Dog inherits from Animal.

Yes, Control is a class in the System.Windows.Forms namespace.

In Visual Studio, click View > Object Browser. You'll see a list of namespaces down the left pane, and if you expand System.Windows.Forms you should see a list of classes that are in that namespace, including the Control class.

A great tool for checking out what goes on behind the scenes in these classes is .Net Reflector. It can get quite complex though.

 
Found it, thanks.

No idea what it does yet.. but found it! ;-)

Will continue to delve and see what else I can find out.

Your example is a LOT more elegant than my effort and it has given me a lot of food for thought.

Thanks for all your work.

;-)

Spend a few minutes remembering your loved ones,
Create a permanent memorial to commemorate their life,

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top