CardPacket.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. //-----------------------------------------------------------------------------
  2. // CardsCollection.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. namespace CardsFramework
  11. {
  12. /// <summary>
  13. /// Card related <see cref="EventArgs"/> holding event information of a <see cref="TraditionalCard"/>
  14. /// </summary>
  15. public class CardEventArgs : EventArgs
  16. {
  17. public TraditionalCard Card { get; set; }
  18. }
  19. /// <summary>
  20. /// A packet of cards
  21. /// </summary>
  22. /// <remarks>
  23. /// A card packet may be initialized with a collection of cards.
  24. /// It may lose cards or deal them to <see cref="Hand"/>, but may
  25. /// not receive new cards unless derived and overridden.
  26. /// </remarks>
  27. public class CardPacket
  28. {
  29. protected List<TraditionalCard> cards { get; set; }
  30. /// <summary>
  31. /// An event which triggers when a card is removed from the collection.
  32. /// </summary>
  33. public event EventHandler<CardEventArgs> LostCard;
  34. public int Count { get { return cards.Count; } }
  35. /// <summary>
  36. /// Tracks whether this card packet has been shuffled at least once.
  37. /// </summary>
  38. public bool HasBeenShuffled { get; private set; } = false;
  39. /// <summary>
  40. /// Initializes a card collection by simply allocating a new card list.
  41. /// </summary>
  42. protected CardPacket()
  43. {
  44. cards = new List<TraditionalCard>();
  45. }
  46. /// <summary>
  47. /// Returns a card at a specified index in the collection.
  48. /// </summary>
  49. /// <param name="index">The card's index.</param>
  50. /// <returns>The card at the specified index.</returns>
  51. public TraditionalCard this[int index]
  52. {
  53. get
  54. {
  55. return cards[index];
  56. }
  57. }
  58. /// <summary>
  59. /// Initializes a new instance of the <see cref="CardPacket"/> class.
  60. /// </summary>
  61. /// <param name="numberOfDecks">The number of decks to add to
  62. /// the collection.</param>
  63. /// <param name="jokersInDeck">The amount of jokers in each deck.</param>
  64. /// <param name="suits">The suits to add to each decks. Suits are specified
  65. /// as flags and several can be added.</param>
  66. /// <param name="cardValues">The card values which will appear in each deck.
  67. /// values are specified as flags and several can be added.</param>
  68. public CardPacket(int numberOfDecks, int jokersInDeck,
  69. CardSuit suits, CardValue cardValues)
  70. {
  71. cards = new List<TraditionalCard>();
  72. for (int deckIndex = 0; deckIndex < numberOfDecks; deckIndex++)
  73. {
  74. AddSuit(suits, cardValues);
  75. for (int j = 0; j < jokersInDeck / 2; j++)
  76. {
  77. cards.Add(new TraditionalCard(CardSuit.Club,
  78. CardValue.FirstJoker, this));
  79. cards.Add(new TraditionalCard(CardSuit.Club,
  80. CardValue.SecondJoker, this));
  81. }
  82. if (jokersInDeck % 2 == 1)
  83. {
  84. cards.Add(new TraditionalCard(CardSuit.Club,
  85. CardValue.FirstJoker, this));
  86. }
  87. }
  88. }
  89. /// <summary>
  90. /// Adds suits of cards to the collection.
  91. /// </summary>
  92. /// <param name="suits">The suits to add to each decks. Suits are specified
  93. /// as flags and several can be added.</param>
  94. /// <param name="cardValues">The card values which will appear in each deck.
  95. /// values are specified as flags and several can be added.</param>
  96. private void AddSuit(CardSuit suits, CardValue cardValues)
  97. {
  98. if ((suits & CardSuit.Club) == CardSuit.Club)
  99. {
  100. AddCards(CardSuit.Club, cardValues);
  101. }
  102. if ((suits & CardSuit.Diamond) == CardSuit.Diamond)
  103. {
  104. AddCards(CardSuit.Diamond, cardValues);
  105. }
  106. if ((suits & CardSuit.Heart) == CardSuit.Heart)
  107. {
  108. AddCards(CardSuit.Heart, cardValues);
  109. }
  110. if ((suits & CardSuit.Spade) == CardSuit.Spade)
  111. {
  112. AddCards(CardSuit.Spade, cardValues);
  113. }
  114. }
  115. /// <summary>
  116. /// Adds cards to the collection.
  117. /// </summary>
  118. /// <param name="suit">The suit of the added cards.</param>
  119. /// <param name="cardValues">The card values which will appear in each deck.
  120. /// values are specified as flags and several can be added.</param>
  121. private void AddCards(CardSuit suit,
  122. CardValue cardValues)
  123. {
  124. if ((cardValues & CardValue.Ace) == CardValue.Ace)
  125. {
  126. cards.Add(new TraditionalCard(suit, CardValue.Ace, this));
  127. }
  128. if ((cardValues & CardValue.Two) == CardValue.Two)
  129. {
  130. cards.Add(new TraditionalCard(suit, CardValue.Two, this));
  131. }
  132. if ((cardValues & CardValue.Three) == CardValue.Three)
  133. {
  134. cards.Add(new TraditionalCard(suit, CardValue.Three, this));
  135. }
  136. if ((cardValues & CardValue.Four) == CardValue.Four)
  137. {
  138. cards.Add(new TraditionalCard(suit, CardValue.Four, this));
  139. }
  140. if ((cardValues & CardValue.Five) == CardValue.Five)
  141. {
  142. cards.Add(new TraditionalCard(suit, CardValue.Five, this));
  143. }
  144. if ((cardValues & CardValue.Six) == CardValue.Six)
  145. {
  146. cards.Add(new TraditionalCard(suit, CardValue.Six, this));
  147. }
  148. if ((cardValues & CardValue.Seven) == CardValue.Seven)
  149. {
  150. cards.Add(new TraditionalCard(suit, CardValue.Seven, this));
  151. }
  152. if ((cardValues & CardValue.Eight) == CardValue.Eight)
  153. {
  154. cards.Add(new TraditionalCard(suit, CardValue.Eight, this));
  155. }
  156. if ((cardValues & CardValue.Nine) == CardValue.Nine)
  157. {
  158. cards.Add(new TraditionalCard(suit, CardValue.Nine, this));
  159. }
  160. if ((cardValues & CardValue.Ten) == CardValue.Ten)
  161. {
  162. cards.Add(new TraditionalCard(suit, CardValue.Ten, this));
  163. }
  164. if ((cardValues & CardValue.Jack) == CardValue.Jack)
  165. {
  166. cards.Add(new TraditionalCard(suit, CardValue.Jack, this));
  167. }
  168. if ((cardValues & CardValue.Queen) == CardValue.Queen)
  169. {
  170. cards.Add(new TraditionalCard(suit, CardValue.Queen, this));
  171. }
  172. if ((cardValues & CardValue.King) == CardValue.King)
  173. {
  174. cards.Add(new TraditionalCard(suit, CardValue.King, this));
  175. }
  176. }
  177. /// <summary>
  178. /// Shuffles the cards in the packet by randomly changing card placement.
  179. /// </summary>
  180. public void Shuffle()
  181. {
  182. Random random = new Random();
  183. List<TraditionalCard> shuffledDeck = new List<TraditionalCard>();
  184. while (cards.Count > 0)
  185. {
  186. TraditionalCard card = cards[random.Next(0, cards.Count)];
  187. cards.Remove(card);
  188. shuffledDeck.Add(card);
  189. }
  190. cards = shuffledDeck;
  191. HasBeenShuffled = true;
  192. }
  193. /// <summary>
  194. /// Shuffles the cards in the packet using a specified seed for deterministic shuffling.
  195. /// </summary>
  196. /// <param name="seed">The seed for the random number generator.</param>
  197. public void Shuffle(int seed)
  198. {
  199. Random random = new Random(seed);
  200. List<TraditionalCard> shuffledDeck = new List<TraditionalCard>();
  201. while (cards.Count > 0)
  202. {
  203. TraditionalCard card = cards[random.Next(0, cards.Count)];
  204. cards.Remove(card);
  205. shuffledDeck.Add(card);
  206. }
  207. cards = shuffledDeck;
  208. HasBeenShuffled = true;
  209. }
  210. /// <summary>
  211. /// Removes the specified card from the packet. The first matching card
  212. /// will be removed.
  213. /// </summary>
  214. /// <param name="card">The card to remove.</param>
  215. /// <returns>The card that was removed from the collection.</returns>
  216. /// <remarks>
  217. /// Please note that removing a card from a packet may only be performed internally by
  218. /// other card-framework classes to maintain the principle that a card may only be held
  219. /// by one <see cref="CardPacket"/> only at any given time.
  220. /// </remarks>
  221. internal TraditionalCard Remove(TraditionalCard card)
  222. {
  223. if (cards.Contains(card))
  224. {
  225. cards.Remove(card);
  226. if (LostCard != null)
  227. {
  228. LostCard(this, new CardEventArgs() { Card = card });
  229. }
  230. return card;
  231. }
  232. return null;
  233. }
  234. /// <summary>
  235. /// Removes all the cards from the collection.
  236. /// </summary>
  237. /// <returns>A list of all the cards that were removed.</returns>
  238. internal List<TraditionalCard> Remove()
  239. {
  240. List<TraditionalCard> cards = this.cards;
  241. this.cards = new List<TraditionalCard>();
  242. return cards;
  243. }
  244. /// <summary>
  245. /// Deals the first card from the collection to a specified hand.
  246. /// </summary>
  247. /// <param name="destinationHand">The destination hand.</param>
  248. /// <returns>The card that was moved to the hand.</returns>
  249. public TraditionalCard DealCardToHand(Hand destinationHand)
  250. {
  251. TraditionalCard firstCard = cards[0];
  252. firstCard.MoveToHand(destinationHand);
  253. return firstCard;
  254. }
  255. /// <summary>
  256. /// Deals several cards to a specified hand.
  257. /// </summary>
  258. /// <param name="destinationHand">The destination hand.</param>
  259. /// <param name="count">The amount of cards to deal.</param>
  260. /// <returns>A list of the cards that were moved to the hand.</returns>
  261. public List<TraditionalCard> DealCardsToHand(Hand destinationHand, int count)
  262. {
  263. List<TraditionalCard> dealtCards = new List<TraditionalCard>();
  264. for (int cardIndex = 0; cardIndex < count; cardIndex++)
  265. {
  266. dealtCards.Add(DealCardToHand(destinationHand));
  267. }
  268. return dealtCards;
  269. }
  270. }
  271. }