AceInfinity
Emeritus, Contributor
Here's a bunch of code I just started working on...
So far, I've got the main structure down, I haven't tested hardly any of it other than the Deck and the Card class. The Hand class I'm just going to say it works, and if someone finds a bug in it, while be my guest to take this even further lol.
I ended up getting pretty far, I could do the rest and create the images for the suits to draw on the face of the cards, but I kinda got too tired before I decided to go at it. It is 3:20AM here (as usual, I stay up pretty late), and I am supposed to go to the gym tomorrow, but I think I'm going to have to cancel on that one.
Here's a preview of what I had for the GDI portion (not too much, but decent enough for use if someone wanted simplicity):
... Comes with no warranty, so it's staying as is for now until I decide that there's a good reason why I should continue killing more time on this :)
:thumbsup2:
Code:
// Name: Card Utilities
// Copyright: (c) AceInfinity - 2013
// Description: Full code for graphics display of a card from a standard 52 card deck.
// Includes methods and collections of Card's in various classes.
//
// IDEAS:
// - I was thinking on creating a "Flip" state for a specific card so that you would
// see a back view of what a card looks like from the deck. Could be handy for games...
//
// - I didn't feel like putting the image in the middle of the card being drawn out.
// But if I took this seriously, then that would be my next real update.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
#region CardDisplay
/// <summary>
/// Custom PictureBox control to display the card
/// </summary>
public class CardDisplay : PictureBox
{
/// <summary>
/// Fixed card dimensions.
/// </summary>
private const int _fixedHeight = 200;
private const int _fixedWidth = 150;
/// <summary>
/// All the face values for a standard 52 card deck.
/// (No jokers.)
/// </summary>
private string[] _faceValues = new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };
/// <summary>
/// Card to be displayed in the PictureBox.
/// </summary>
private Card _displayCard;
public Card DisplayCard
{
get
{
return _displayCard;
}
set
{
_displayCard = value;
Invalidate();
}
}
/// <summary>
/// Need the default constructor for designer.
/// </summary>
public CardDisplay() : this(new Card(SUIT.Spades, VALUE.Ace)) { }
/// <summary>
/// For dynamic instances...
/// </summary>
/// <param name="card"></param>
public CardDisplay(Card card)
{
_displayCard = card;
}
/// <summary>
/// Paint event method for the PictureBox.
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.Clear(Color.White);
g.DrawRectangle(Pens.DarkGray, Rectangle.FromLTRB(0, 0, this.Width - 1, this.Height - 1));
PaintFace(ref g);
}
/// <summary>
/// Method to paint the Suit and ID for the card.
/// </summary>
/// <param name="g"></param>
private void PaintFace(ref Graphics g)
{
Brush color = (_displayCard.Suit == SUIT.Hearts || _displayCard.Suit == SUIT.Diamonds) ? Brushes.Red : Brushes.Black;
string name = _faceValues[(int)_displayCard.Value];
using (Font font = new Font(FontFamily.GenericSansSerif, 12f))
{
string strObj = name;
SizeF strSize = g.MeasureString(strObj, font);
int quad = this.Width / 4;
g.DrawString(strObj, font, color, new PointF(quad / 2 - strSize.Width / 2, 10));
g.DrawString(strObj, font, color, new PointF(this.Width - quad / 2 - strSize.Width / 2, this.Height - 30));
strObj = Enum.GetName(typeof(SUIT), _displayCard.Suit);
strSize = g.MeasureString(strObj, font);
g.DrawString(strObj, font, color, new PointF(this.Width / 2 - strSize.Width / 2, this.Height / 2 - strSize.Height / 2));
}
}
/// <summary>
/// Keep the size consistent.
/// I could add in resizing stuff, but the main graphics aren't even done yet, so i've decided to work with a fixed size.
/// </summary>
public override Size MinimumSize { get { return new Size(_fixedWidth, _fixedHeight); } }
public override Size MaximumSize { get { return new Size(_fixedWidth, _fixedHeight); } }
}
#endregion
#region Other
#region Deck
/// <summary>
/// Class object that represents the full 52 card deck.
/// </summary>
public class Deck
{
/// <summary>
/// Card array property.
/// No need for the user to modify this, unless I decide at a later date to
/// allow cards to be withdrawn from the deck and excluded from the pack.
/// </summary>
private Card[] _cards = new Card[52];
public Card[] Cards
{
get { return _cards; }
}
/// <summary>
/// Instantiates the full deck of cards, in an ordered state.
/// </summary>
public Deck()
{
int index = 0;
foreach (SUIT suit in Enum.GetValues(typeof(SUIT)))
{
foreach (VALUE value in Enum.GetValues(typeof(VALUE)))
{
_cards[index++] = new Card(suit, value);
}
}
}
/// <summary>
/// Method to shuffle the deck of cards.
/// </summary>
public void Shuffle()
{
_cards = _cards.OrderBy(card => Guid.NewGuid()).ToArray();
}
}
#endregion
#region Hand
/// <summary>
/// Represents a hand of cards.
/// </summary>
public class Hand :
IEnumerable<Card>, IList<Card>
{
/// <summary>
/// Set a maximum amount of cards that can be held in a users Hand at a time.
/// </summary>
public ushort MaxHandSize { get; set; }
/// <summary>
/// Check if we have reached the max.
/// </summary>
public bool HasMaxCards
{
get
{
return cards.Count == MaxHandSize;
}
}
/// <summary>
/// Container for the cards this hand is holding.
/// </summary>
private List<Card> cards = new List<Card>();
#region IEnumerable<Card> Implementation
public IEnumerator<Card> GetEnumerator()
{
return cards.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return cards.GetEnumerator();
}
#endregion
#region IList<Card> Implementation
public int IndexOf(Card item)
{
return cards.IndexOf(item);
}
public void Insert(int index, Card item)
{
if (HasMaxCards)
{
throw new ArgumentException("Hand already has maximum number of cards.");
}
cards.Insert(index, item);
}
public void RemoveAt(int index)
{
cards.RemoveAt(index);
}
public Card this[int index]
{
get
{
return cards[index];
}
set
{
cards[index] = value;
}
}
public void Add(Card item)
{
if (HasMaxCards)
{
throw new ArgumentException("Hand already has maximum number of cards.");
}
cards.Add(item);
}
public void Clear()
{
cards.Clear();
}
public bool Contains(Card item)
{
return cards.Contains(item);
}
public void CopyTo(Card[] array, int arrayIndex)
{
cards.CopyTo(array, arrayIndex);
}
public int Count
{
get { return cards.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(Card item)
{
return cards.Remove(item);
}
#endregion
public override string ToString()
{
return "{ " + string.Join(", ", cards) + " }";
}
}
#endregion
#region Card
public class Card
{
/// <summary>
/// After a card has been instantiated, there's no reason to change the value or suit.
/// (We are not magicians here.)
/// </summary>
private readonly SUIT _suit;
private readonly VALUE _value;
/// <summary>
/// Constructor that instantiates the properties of this specific card.
/// </summary>
/// <param name="suit"></param>
/// <param name="value"></param>
public Card(SUIT suit, VALUE value)
{
this._suit = suit;
this._value = value;
}
/// <summary>
/// Get the suit of this card.
/// </summary>
public SUIT Suit
{
get
{
return this._suit;
}
}
/// <summary>
/// Get the face value of this card.
/// </summary>
public VALUE Value
{
get
{
return this._value;
}
}
public override string ToString()
{
return string.Format("{0} Of {1}", this._value, this._suit);
}
}
#endregion
/// <summary>
/// Various enumerations that define the possible face values and suits that a card can use.
/// </summary>
public enum SUIT { Hearts, Diamonds, Spades, Clubs }
public enum VALUE { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace }
#endregion
So far, I've got the main structure down, I haven't tested hardly any of it other than the Deck and the Card class. The Hand class I'm just going to say it works, and if someone finds a bug in it, while be my guest to take this even further lol.
I ended up getting pretty far, I could do the rest and create the images for the suits to draw on the face of the cards, but I kinda got too tired before I decided to go at it. It is 3:20AM here (as usual, I stay up pretty late), and I am supposed to go to the gym tomorrow, but I think I'm going to have to cancel on that one.
Here's a preview of what I had for the GDI portion (not too much, but decent enough for use if someone wanted simplicity):
... Comes with no warranty, so it's staying as is for now until I decide that there's a good reason why I should continue killing more time on this :)
:thumbsup2:
Last edited: