1. 程式人生 > >C#:撲克牌遊戲(2):給CardLib新增Cards集合

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();
        }
    }
}