C#:撲克牌遊戲(2):給CardLib新增Cards集合
(一):背景
在上一篇文章中,我們簡單建立了幾個可能在後面會用到的類並且放到了一個類庫中,接下來需要對這幾個類進行進一步的思考。首先一個問題是,我們原先在Deck類中,使用了一個數組來代表一副牌,但是我們知道,在一個撲克牌遊戲中,(例如鬥地主),會存在著抽牌,出牌的動作,當發生這種動作時,物件的個數就發生變化了。這種情況下,我們使用一個固定個數的陣列就不是那麼合適了。因此在這篇文章中,會使用集合的技術來代替原先的陣列。
因為有抽牌出牌的動作,所以我們還需要一個Cards類來代表“一手牌”這個概念
(二):建立新工程
按照書上的做法,建立新類庫工程命名為Ch11CardLib
(三):建立原先的列舉
列舉Rank和Suit和上一篇文章一致
(四):建立代表一手牌的新類Cards
建立新類,命名為Cards,這是一個繼承CollectionBase類的集合。首先考慮到抽牌的動作,一個集合內物件減少而另一個集合內物件增加,因此建立增加物件和減少物件的方法。
public void Add(Card newCard) { List.Add(newCard); }
public void Remove(Card oldCard)
{
List.Remove(oldCard);
}
然後我們考慮實現“判斷某張牌是否在集合內”的功能
public bool Contains(Card card) => InnerList.Contains(card);
接下來是將一個集合內物件複製到另一個集合內
public void CopyTo(Cards targetCards) { for(int index=0;index<this.Count;index++) { targetCards[index] = this[index]; } }
(五):修改Deck類
修改完的Deck類見下面程式碼
(六):建立客戶端工程進行驗證
和上一篇文章中的做法一樣,程式碼不變
(七):輸出結果
(八):原始碼
Ch11CardLib類庫中
Suit.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch11CardLib
{
public enum Suit
{
Club,
Diamond,
Heart,
Spade
}
}
Rank.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch11CardLib
{
public enum Rank
{
Ace = 1,
Deuce,
Three,
Four,
Five,
Six,
Seven,
Eight,
Ten,
Jack,
Queen,
King
}
}
Card.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch11CardLib
{
public class Card
{
public Rank rank;
public Suit suit;
public Card()
{
}
public Card(Suit newSuit, Rank newRank)
{
suit = newSuit;
rank = newRank;
}
public override string ToString()
{
return "The " + rank + "of " + suit + "s";
}
}
}
修改過的Deck.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch11CardLib
{
public class Deck
{
private Cards cards = new Cards();
public Deck()
{
for(int suitVal=0;suitVal<4;suitVal++)
{
for (int rankVal=1;rankVal<14;rankVal++)
{
cards.Add(new Card((Suit)suitVal, (Rank)rankVal));
}
}
}
public Card GetCard(int cardNum)
{
if (cardNum >= 0 && cardNum <= 51)
return cards[cardNum];
throw new System.ArgumentOutOfRangeException("cardNum", cardNum, "Value must between 0 and 51");
}
public void Shuffle()
{
Cards newDeck = new Cards();
bool[] assigned = new bool[52];
Random sourceGen = new Random();
for(int i=0;i<52;i++)
{
int sourceCard = 0;
bool foundCard = false;
while(foundCard==false)
{
sourceCard = sourceGen.Next(52);
if (assigned[sourceCard] == false)
foundCard = true;
}
assigned[sourceCard] = true;
newDeck.Add(cards[sourceCard]);
}
newDeck.CopyTo(cards);
}
}
}
新建的Cards.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Ch11CardLib
{
public class Cards:CollectionBase
{
public void Add(Card newCard)
{
List.Add(newCard);
}
public void Remove(Card oldCard)
{
List.Remove(oldCard);
}
public Card this[int cardIndex]
{
get { return (Card)List[cardIndex]; }
set { List[cardIndex] = value; }
}
public void CopyTo(Cards targetCards)
{
for(int index=0;index<this.Count;index++)
{
targetCards[index] = this[index];
}
}
public bool Contains(Card card) => InnerList.Contains(card);
}
}
Ch11CardClient工程
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ch11CardLib;
using static System.Console;
namespace Ch11CardClient
{
class Program
{
static void Main(string[] args)
{
Deck myDeck = new Deck();
myDeck.Shuffle();
for(int i=0;i<52;i++)
{
Card tempCard = myDeck.GetCard(i);
WriteLine(tempCard.ToString());
}
ReadKey();
}
}
}