1

This is a 2 part question, I am making a blackjack game and I am trying to randomly generate a key and value (KEY = string(card value e.g. Hearts2), And VALUE = int (Score for that specific card value)), and I would like to try and return the key and value.

I have a deck, dealer and player class. My Deck class has 2 methods, Deck() and Shuffel(), deck() is used to create the deck and shuffle90 well shuffles the deck(). I would like to send the random card to the dealer class to deal the cards. I am not sure if it is possible to return the key and value so the dealer class method (dealCards()) can receive a string and int as parameters.

Also I found a way to randomize my dictionary but it is returning the entire dictionary randomized, but I only need one card to be returned.

This is what I have so far for the Deck class...

This is my

public static Dictionary<string, int> deck()
{
    string[] Suite = new string[4] { "Spades", "Clubs", "Hearts", "Diamonds" };
    string[] FaceValue = new string[13] { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
    int score;

    Dictionary<string, int> deckOfCards = new Dictionary<string, int>();

    for (int s = 0; s < 4; s++)
    {
        string sute = Suite[s];

        for (int f = 0; f < 13; f++)
        {
           string fV = FaceValue[f];

            if (f == 0)
            {
                score = 0;
            }
            else if (f >= 9)
            {
                score = 10;
            }
            else
            {
                score = (f + 1);
            }

            string card = (sute + fV);

            deckOfCards.Add(card, score);
        }
    }


    Dictionary<string, int> ranCard = deckOfCards.Shuffle();

    return ranCard;
}

As you can see I created 2 simple arrays and used for loops to iterate through them and add them to the dictionary.

The last two lines, the first is declaring a new dictionary to hold the random card and reciving its value from the Shuffle() method,(is posted bellow) and I would like to know if there is a way to return ranCard.Key, ranCard.Value ? so I can have my Dealer class method like this (dealCard(string card, int score))?

This is my Shuffle() method for my Deck class...

public static Dictionary<TKey, TValue> Shuffle<TKey, TValue>(this Dictionary<TKey, TValue> Cards)
{
    Random r = new Random();
    Cards = Cards.OrderBy(x => r.Next(0, Cards.Count)).ToDictionary(item => item.Key, item => item.Value);
    return Cards;
}

Now with this method The entire dictionary is randomized and I would like to just return one randome value if possible. I tried to remove the parameters in the r.Next(**) but still the same.

I am using vs2012.

Jody Stocks
  • 93
  • 1
  • 2
  • 15

2 Answers2

1

There are several issues here:

  • Dictionaries aren't ordered - so the order in which the cards come out of OrderBy may not be reflected when you iterate over the dictionary later. I believe in the current implementation it may happen to do that, but fundamentally you shouldn't rely on it.
  • Your way of shuffling isn't good anyway - it's likely to make early items stay early, as if there are two items which get the same random "key", the earlier one will be emitted first. Consider using a variant of a Fisher-Yates shuffle - there are several examples on SO, such as this one.
  • Your approach to keeping the card and score together as a dictionary key/value pair feels awkward to me... if you avoid that, you'll find a lot of other things drop out.

Basically, a deck of cards isn't a dictionary - it's a sequence of cards. So you should be modelling a card:

public sealed class Card
{
    // Fields for face value and suit, and a property to compute the score
}

How you choose to represent the face value and suit are up to you, but you should consider using enums given that there are natural sets of valid values here.

Once you've got a deck as a List<Card> (or a Queue<Card>), you can easily shuffle that, and then just deal Card values to players.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Hi there Jon, where would be the best place to have the calculate score ? in the Card class, After the random card has been chosen from the list<>, Then calculate its score and return the random card and its score to dealer ? – Jody Stocks Aug 27 '14 at 09:48
  • 1
    @JodyStocks: If it's a natural part of a single card (based only on the attributes of the card), then the card itself could do it. – Jon Skeet Aug 27 '14 at 11:11
1

First things first.

The game rules require that you have state. What I mean is that you don't have a stateless random return value, but you MUST retain the state across the generation of random values, as the probabilities change. In layman's terms: you can't draw the same card more than n times because the game rules specify how the deck is composed.

That said, it is clear that one way or another you have to keep track of the cards in the deck. In your code you shuffle the whole deck and return that. All you need now is an object that wraps it and keeps internally its state, like so:

class Dealer
{
    private List<Card> shuffledCards; // keep state of the current shuffle

    public Dealer(...)
    {
        shuffledCards = Shuffle(...); // use your method to get the shuffled cards
    }

    public Card Deal() // remove the first card from the deck and hand it out
    {
        Card c;

        c = shuffledCards[0];
        shuffledCards.RemoveAt(0);

        return c;
    }
}

There are many more ways to implement this, at least another 2 come to my mind, but the result is just the same.

pid
  • 11,472
  • 6
  • 34
  • 63
  • This is a realy good example thanks, but should I keep the dictionary in my deck class, Which I am changing to a card class, or also keep it as a list? – Jody Stocks Aug 27 '14 at 09:50
  • If you need the list inside the class keep also the list, but you'll have to manage it accordingly. If you can do without you might be better off not having the list. Remember that you should keep it next to the dictionary and "under wraps" because it is an implementation detail and should not be exposed to the rest of the application. This way you are free to later change the implementation without compromising other classes. – pid Aug 27 '14 at 12:02