给 CardLib 添加 Cards 集合

  第 10 章创建了一个类库项目 Ch10CardLib,它包含一个表示扑克牌的 Card 类和一个表示一副扑克牌的 Deck 类,这个 Deck 类是 Card 类的集合,且实现为一个简单数组。

  本章给这个库添加一个新类,并将类库重命名为 Ch11CardLib。这个新类 CardsCard 对象的一个定制集合,并拥有本章前面介绍的各种功能。在 C:\BegVCSharp\Chapter11 目录中创建于给新类库 Ch11CardLib。然后删除自动生成的 Class1.cs 文件,再使用 Project | Add Existing Item 选择 C:\BegVCSharp\Chapter10\Ch10CardLib\Ch10CardLib 目录中的 Card.csDeck.csSuit.csRank.cs 文件,把它们添加到项目中。与第 10 章介绍的这个项目的上一个版本相同,这里也不使用标准的 “试一试” 格式介绍这些变化。

  如果要自己创建这个项目,就应该添加一个新类 Cards,修改 Cards.cs 中的代码,如下所示:

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace Ch11CardLib
  8. {
  9. public class Cards : CollectionBase
  10. {
  11. public void Add(Card newCard)
  12. {
  13. List.Add(newCard);
  14. }
  15. public void Remove(Card oldCard)
  16. {
  17. List.Remove(oldCard);
  18. }
  19. public Card this[int cardIndex]
  20. {
  21. get {
  22. return (Card)List[cardIndex];
  23. }
  24. set {
  25. List[cardIndex] = value;
  26. }
  27. }
  28. public void CopyTo(Cards targetCards)
  29. {
  30. for (int index = 0; index < this.Count; index++)
  31. {
  32. targetCards[index] = this[index];
  33. }
  34. }
  35. public bool Contains(Card card)
  36. {
  37. return InnerList.Contains(card);
  38. }
  39. }
  40. }

  然后需要修改 Deck.cs,以利用这个新集合,而不是数组:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace Ch11CardLib
  6. {
  7. public class Deck
  8. {
  9. private Cards cards = new Cards();
  10. public Deck()
  11. {
  12. for (int suitVal = 0; suitVal < 4; suitVal++)
  13. {
  14. for (int rankVal = 1; rankVal < 14; rankVal++)
  15. {
  16. cards.Add(new Card((Suit)suitVal, (Rank)rankVal));
  17. }
  18. }
  19. }
  20. public Card GetCard(int cardNum)
  21. {
  22. if (cardNum >=0 && cardnum <= 51)
  23. return cards[cardNum];
  24. else
  25. throw (new System.ArgumentOutOfRangeException("cardNum", cardNum, "Value must be between 0 and 51."));
  26. }
  27. public void Shuffle()
  28. {
  29. Cards newDeck = new Cards();
  30. bool[] assigned = new bool[52];
  31. Random sourceGen = new Random();
  32. for (int i = 0; i < 52; i++)
  33. {
  34. int sourceCard = 0;
  35. bool foundCard = false;
  36. while (foundCard == false)
  37. {
  38. sourceCard = sourceGen.Next(52);
  39. if (assigned[sourceCard] == false)
  40. foundCard = true;
  41. }
  42. assigned[sourceCard] = true;
  43. newDeck.Add(cards[sourceCard]);
  44. }
  45. newDeck.CopyTo(cards);
  46. }
  47. }
  48. }

  在此不需要做很多修改。其中大多数修改都涉及改变洗牌逻辑,才能把 cards 中随机的一张牌添加到新 Cards 集合 newDeck 的开头,而不是把 cards 集合中顺序位置的一张牌添加 newDeck 集合的随机位置上。

  Ch10CardLib 解决方案的客户控制台应用程序 Ch10CardClient 可以使用这个新库得到与以前相同的结果,因为 Deck 的方法签名没有改变。这个类库的客户程序现在可以使用 Cards 集合类,而不是依赖 Card 对象数组,例如,在扑克牌游戏应用程序中定义一手牌。