Click here to Skip to main content
15,899,825 members
Please Sign up or sign in to vote.
2.00/5 (3 votes)
See more:
I am making a blackjack game using console application and I started to make my card class but I am not sure on how to validate if the value set to the card is in my array

Any help would be appreciated

Here is the table I need to use
C#
String[] values = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};


Here is my card class so far

C#
class Card
    {

        public enum SUIT { HEARTS, SPADES, DIAMONDS, CLUBS };

        private SUIT _suit;
        private String _value;

        public Card(SUIT suit, String value)
        {

            _suit = suit;
            _value = value;
        }
        String[] values = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
        public SUIT Suit
        {
            get
            {
                //Return member variable value
                return _suit;
            }
            set
            {
                _suit = value;
            }
        }
       
        public String Value 
        {
            get
            {
                //Return member variable value
                return _value;
            }
            set
            {
                int index = Array.IndexOf(values, Convert.ToInt32(_value));
                if (index > 1)
                    _value = value;
            }
        }
    }
Posted
Updated 22-Nov-14 18:27pm
v2
Comments
BillWoodruff 23-Nov-14 4:14am    
Hi Josh, I wonder how far along with this you are: do you want to consider a very different way of modeling a deck of cards, using Classes and inheritance ?

I don't see why you should ever need to check for an incorrect value for a Card because I think all the cards should be created when the Deck is initialized, and at that point you have complete control over what values are set.

I have used modeling a deck of cards in .NET as a student assignment in the past because it involves mastery of manipulating different Types (suits, values).

If you want some different ideas, and some code outlines, let me know, and I will post.

Note the code shown here uses "automatic" Property backing-field creation as implemented beginning in C# 3.0 (2007).

By defining a Deck as inheriting from a List<Card> we (essentially) create a custom List of Cards, and we can extend the functionality of that "custom List" with whatever we require: in this case, all we do is add a 'Shuffle method.

By use of 'Enums you can make your code express your intent to model a Deck of Cards.

By use of Properties with a private 'setter, you can ensure that only the constructor of an instance of a Card can set the property, but the public 'getter allows access to the Value from anywhere in your code that has a reference to the instance of the Deck.
C#
public enum SuitType
{
    Hearts, Diamonds, Clubs, Spades, Jokers
}

// note the Enum value 'Joker here: this is not used in this example
// but is there to enable another type of Deck definition
// ... the "US deck," with Jokers, for example

public enum CardValueType
{
    Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Joker
}

public class Card
{
    // note the private 'set
    public SuitType Suit { private set; get; }
    public CardValueType Value { private set; get; }

    public Card(SuitType suit, CardValueType value)
    {
        Suit = suit;
        Value = value;
    }
}

// note inheritance from List<Card>
public class Deck : List<Card>
{
    public void ShuffleDeck()
    {
        var rnd = new Random(DateTime.Now.Millisecond);
        
        this.OrderBy(order => rnd.Next());
    }
}

// "Classic" or "French" Deck
// four Suits of 13 cards each.

// because we inherit from 'Deck:
// this class also will behave as a List<Card>
public class ClassicDeck : Deck
{
    public ClassicDeck()
    {
        for (int i = 0; i < 4; i++)
        {
            var suit = (SuitType) i;

            for (int j = 0; j < 13; j++)
            {
               this.Add(new Card(suit, (CardValueType)j));
            }
        }
    }
}

// test: put these in a Form's code

// requires Two TextBoxes on the Form, 'textBox1, 'textBox2
// requires a Button on the Form, 'btnTestDeck with its 'Click EventHandler
// connected to the EventHandler shown here

private ClassicDeck TheCurrentDeck;

private void TestDeck(Deck theDeck)
{
    foreach (Card card in theDeck)
    {
        textBox1.AppendText(string.Format("{0}\t{1}\n", card.Value, card.Suit));
    }

    TheCurrentDeck.ShuffleDeck();

    foreach (Card card in theDeck)
    {
        textBox2.AppendText(string.Format("{0}\t{1}\n", card.Value, card.Suit));
    }
}

// run the app, click the button
private void btnTestDeck_Click(object sender, EventArgs e)
{
    textBox1.Clear();
    textBox2.Clear();
    
    TheCurrentDeck = new ClassicDeck();
    
    TestDeck(TheCurrentDeck);
}
 
Share this answer
 
v5
Comments
Maciej Los 23-Nov-14 14:42pm    
Very interesting implementation, Bill!
+5!
BillWoodruff 23-Nov-14 15:04pm    
Thanks, Maciej, I will always appreciate any input you care to share on how I might have done it better, or in more of an "OO" fashion.
Sergey Alexandrovich Kryukov 23-Nov-14 18:10pm    
Bill,

You mixed everything up!
Properties was in .NET from the very beginning, and from the very beginning, they could be backed (how else could they work). What was introduced in 3.0, was auto-implemented properties, where they was no explicitly backed fields. Even then, the backed property was some named property which can conflict with the member declaration if you, by some reason, try to use the same name for some other member. Later, on this apparent design problem was fixed by Microsoft, by using names which are not valid identifier names; but that potential naming conflict remains for properties.

So, you really need to fix your knowledge on these historical .NET and C# version, to avoid confusing our readers. You can easily check up MSDN on this matter and see that I'm right here.

—SA
BillWoodruff 24-Nov-14 0:38am    
Nonsense, Sergey, you are the one who has misunderstood here. My comments explicitly refer to automatic creation of Property backing-fields which arrived in .NET in version 3.0. Of course Properties have been part of .NET from the beginning, and your assumption that my statement implied otherwise is just a mis-interpretation.

You are also confused about .NET 3.0's creation of private backing-fields for automatic property syntax: the name created is a "synthesized" name, and is only accessible to view by using ildasm.exe: there can never be a name clash. If you examine one for a Property named 'Name, you might see something like:

<name>k__BackingField;

A "convention" prior to .NET 3.0 was to have Property private backing fields starting with an underscore and a lower-case letter. To use that convention today is NOT an error, it just means you do more typing, the compiler less work.

I suggest you read The C# Programming Language 4th.edition, by Hejlsberg, Torgersen, Wiltamuth, Golde with annotations by Skeet, Albihari, Liberty, Abrams, Lippers, Sells, and others, and refresh your knowledge of .NET.
Sergey Alexandrovich Kryukov 24-Nov-14 1:59am    
I'm sorry, but didn't you add the word "automatic" after I posted my comment? It's easy to check up. If it was there in first place, my comment would be a mistake.
—SA
Wrong question, no need to answer it the way you expect. Not only such search of the index would compromise performance, but it's also absolutely not needed.

Your mistake is having the field String _value; you never need it. Besides, related problem is: it's bad to have the field Values as the instance field; it should really be static read-only field. Indeed, you don't want to carry this array object with all of your instances, because it is the object to be shared by all your instances.

To fix the design of you class, declare value as byte. First of all, this type, as an integer type, is convenient for all calculations. Second of all, it will save you from the pointless search. Your only problem is finding the string value of the card (let me call it "Name", or you could have "Name" and "ShortName", and this is a simple as the index in the array Values. So, it should be something like that:
C#
class Card {

    public string Name { get { return names[cardValue]; } }

    // ...

    static readonly string[] names = new string[] {
        "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", };
    byte cardValue;

    // ...

}

And I believe you will never need a constructor which accepts name (short or full) of the card, you will just need its numeric value. Those strings values are only needed to show the game on screen, so the are needed only on output of your calculation.

I must note that you show a very common but sorrowful fallacy of many beginners these days: attempt to work with strings representing data instead of actual data. I would advise you to get rid of this habit. :-)

—SA
 
Share this answer
 
v2
Comments
BillWoodruff 23-Nov-14 2:14am    
"Your mistake is having the field String _value" If the OP is working with an older version of C#, i.e., prior to 3.0 (2007), then it is required to define a "backing field." We would hope, however, the OP is working with a later version !

I see no reason to insist on using 'byte here, rather than 'int.

If the Card class is an "atomic" element here, then, yes, it's not a good idea to have an instance of 'Values created with every Card: even worse is the repeat definition of the 'Enum in the class. imho, the current structure leads to question the overall design.

And, the overall design here is clearly not optimal for modeling a card deck (here a "French" deck, 52 cards, no Jokers): a given card definition is fixed: it has-a value from Ace to King, it has-a a Suit property.
Sergey Alexandrovich Kryukov 23-Nov-14 3:02am    
First of all, all I wrote here is applicable to any .NET version.
Oh, I don't insist on byte vs int, I insist on not using a string. I mentioned by as the minimal integer type good to cover all the card values.
Well, yes, variable card definition of quite possible...
—SA
Sergey Alexandrovich Kryukov 23-Nov-14 18:13pm    
Ah, now, after you answer post, I can see where your mistake was.
Please fix it.
—SA
Maciej Los 23-Nov-14 14:42pm    
Good general advice, +5!
Sergey Alexandrovich Kryukov 23-Nov-14 18:03pm    
Thank you, Maciej.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900