/// The image with number 0 is the
/// back pattern of the card
/// </summary>
static private Image[] cardImages = new Bitmap[53];
/// <summary>
/// The attribute to be used when drawing the card
/// to implement transpancy
/// </summary>
static public System.Drawing.Imaging.ImageAttributes
cardAttributes;
/// <summary>
/// Used when loading card images prior to drawing
/// </summary>
static private System.Reflection.Assembly execAssem;
/// <summary>
/// Sets up the color and attribute values.
/// </summary>
static Card()
{
cardAttributes =
new System.Drawing.Imaging.ImageAttributes();
cardAttributes.SetColorKey(Color.Green, Color.Green);
execAssem =
System.Reflection.Assembly.GetExecutingAssembly();
}
/// <summary>
/// Scores for each of the cards in a suit
/// </summary>
static private byte[] scores =
new byte[] { 11, //ace
2,3,4,5,6,7,8,9,10, //spot cards
10,10,10}; //jack, queen, king
/// <summary>
/// Picture information for each card in a suit
/// </summary>
static private bool[] isPicture =
new bool[] { false, //ace
false,false,false,false,false,false,
false,false,false, //spot cards
true,true,true}; //jack, queen, king
/// <summary>
/// Names of the suits, in the order that of the suits
/// in the number sequence
/// </summary>
static private string[] suitNames =
new string[] { "club", "diamond", "heart", "spade" };
/// <summary>
/// Names of individual cards, in the order of the cards
/// in a suit
/// </summary>
static private string[] valueNames =
new string[] {"Ace", "Deuce","Three","Four","Five","Six",
"Seven","Eight","Nine","Ten", "Jack","Queen","King" };
/// <summary>
/// Returns the value in points of a given card,
/// according to BlackJack rules
/// </summary>
public int BlackJackScore
{
get
{
return scores[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns true if the card is a picture
/// (i.e. jack, queen or king)
/// </summary>
public bool IsPicture
{
get
{
return isPicture[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns text of the suit of this card
/// </summary>
public string Suit
{
get
{
return suitNames[(CardNo – 1) / 13];
}
}
/// <summary>
/// Returns the text of the value of this card
/// </summary>
public string ValueName
{
get
{
return valueNames[(CardNo – 1) % 13];
}
}
/// <summary>
/// Returns true if this is a red card
/// </summary>
public bool Red
{
get
{
int suit = (CardNo – 1) / 13;
return ((suit == 1) || (suit == 2));
}
}
/// <summary>
/// Returns true if this is a black card
/// </summary>
public bool Black
{
get
{
return !Red;
}
}
/// <summary>
/// Returns an image which can be used to draw this card
/// </summary>
public Image CardImage
{
get
{
int dispNo = CardNo;
if (!FaceUp)
{
dispNo = 0;
}
if (cardImages[dispNo] == null)
{
cardImages[dispNo] = new Bitmap(
execAssem.GetManifestResourceStream(
@"PocketJack.images." + dispNo + @".gif"));
}
return cardImages[dispNo];
}
}
/// <summary>
/// Constructs a card with a partiuclar number
/// </summary>
/// <param name="cardNo">number of the card
/// in the range 1 to 52</param>
/// <param name="faceUp">true if the card
/// is to be drawn face up</param>
public Card(byte cardNo, bool faceUp)
{
CardNo = cardNo;
FaceUp = faceUp;
}
/// <summary>
/// Constructs a face up card with that number
/// </summary>
/// <param name="cardNo"></param>
public Card(byte cardNo)
: this(cardNo, true)
{
}
/// <summary>
/// String description of the card
/// </summary>
/// <returns>the name and suit of the card</returns>
public override string ToString()
{
return ValueName + " of " + Suit;
}
}
/// <summary>
/// Provides a container for a number of cards.
/// May be used to draw the cards and compute their score.
/// </summary>
public class CardHand : ArrayList
{
/// <summary>
/// Used as a destination of teh draw action
/// </summary>
private static Rectangle drawRect;
/// <summary>
/// Draws the hand on the graphics.
/// </summary>
/// <param name="g">graphics to draw with</param>
/// <param name="startx">left edge of first card</param>
/// <param name="starty">top of first card</param>
/// <param name="gapx">x gap between each card</param>
/// <param name="gapy">y gap between each card</param>
public void DrawHand(Graphics g, int startx, int starty,
int gapx, int gapy)
{
drawRect.X = startx;
drawRect.Y = starty;
foreach (Card card in this)
{
drawRect.Width = card.CardImage.Width;
drawRect.Height = card.CardImage.Height;
g.DrawImage(
card.CardImage, // Image
drawRect, // destination rectange
0, // srcX
0, // srcY
card.CardImage.Width, // srcWidth
card.CardImage.Height, // srcHeight
GraphicsUnit.Pixel, // srcUnit
Card.cardAttributes); // ImageAttributes
drawRect.X += gapx;
drawRect.Y += gapy;
}
}
/// <summary>
/// Computes the score of the hand
/// </summary>
/// <returns>the value of the score</returns>
public int BlackJackScoreHand()
{
int score = 0;
int aces = 0;
foreach (Card card in this)
{
score += card.BlackJackScore;
if (card.BlackJackScore == 11)
{
aces++;
}
}
while ((score > 21) && (aces > 0))
{
score -= 10;
aces–;
}
return score;
}
}
/// <summary>
/// Contains a number of card decks
/// which can be dealt one at a time.
/// </summary>
public class CardShoe
{
private int noOfDecks = 1;
private byte[] decks;
private int nextCard;
private bool testShoe = false;
/// <summary>
/// True if the deck is "stacked",
/// i.e. was created from a byte array
/// </summary>
public bool TestShoe
{
get
{
return testShoe;
}
}
private void makeShoe()
{
decks = new byte[noOfDecks * 52];
int cardPos = 0;
for (int i = 0; i < noOfDecks; i++)
{
for (byte j = 1; j < 53; j++)
{
decks[cardPos] = j;
cardPos++;
}
}