簡體   English   中英

在C#中表示游戲卡類的最佳方式

[英]Best way to represent game card class in C#

我使用類卡,其中包含2個枚舉屬性(套件 - 心形鑽石黑桃和俱樂部)和卡值從2到A.並覆蓋ToString()方法返回類似Ah Ad等的東西。一切正常,但枚舉值無法啟動有了數字,因此枚舉的卡片值看起來像x2,x3,x4 ......它不漂亮。

還需要簡單的方法來解析單個字符串中的幾張卡片。

誰知道設計這門課程的最佳方法?

難道你不能分別將傑克,女王,國王和王牌分別分別為11歲,12歲,13歲和14歲? 它最終看起來像:

public class Card
{
    public int Value { get; private set; }
    public enum SuitType
    {
        Clubs, Spades, Hearts, Diamonds
    }
    public SuitType Suit { get; private set; }
    public Card(int value, SuitType suit)
    {
        Suit = suit;
        Value = value;
    }
    public Card(string input)
    {
        if (input == null || input.Length < 2 || input.Length > 2)
            throw new ArgumentException();
        switch (input[0])
        {
            case 'C': case 'c':
                Suit = SuitType.Clubs;
                break;
            case 'S': case 's':
                Suit = SuitType.Spades;
                break;
            case 'H': case 'h':
                Suit = SuitType.Hearts;
                break;
            case 'D': case 'd':
                Suit = SuitType.Diamonds;
                break;
            default:
                throw new ArgumentException();
        }
        int uncheckedValue = (int)input[1];
        if (uncheckedValue > 14 || uncheckedValue < 1)
            throw new ArgumentException();
        Value = uncheckedValue;
    }
    public string encode()
    {
        string encodedCard = "";
        switch (Suit)
        {
            case SuitType.Clubs:
                encodedCard += 'c';
                break;
            case SuitType.Spades:
                encodedCard += 's';
                break;
            case SuitType.Hearts:
                encodedCard += 'h';
                break;
            case SuitType.Diamonds:
                encodedCard += 'd';
                break;
        }
        encodedCard += (char) Value;
        return encodedCard;
    }
    public override string ToString()
    {
        string output = "";
        if (Value > 10)
        {
            switch (Value)
            {
                case 11:
                    output += "Jack";
                    break;
                case 12:
                    output += "Queen";
                    break;
                case 13:
                    output += "King";
                    break;
                case 14:
                    output += "Ace";
                    break;
            }
        }
        else
        {
            output += Value;
        }
        output += " of " + System.Enum.GetName(typeof(SuitType), Suit);
        return output;
    }
}

編輯:我添加了一些字符串功能。 我從Jon Hanna的回答中獲取Card(string input)結構。

pip卡有一個明顯的數值,我們可以添加J = 11,Q = 12,K = 13。

根據正在建模的游戲,使A = 14比A = 1可能更方便(因此可以更簡單地計算手的不同相對值)。

枚舉沒有真正的優勢,特別是因為枚舉允許超出范圍的值,除非您明確檢查它們(例如,沒有什么可以阻止某人將(CardValue)54分配給卡值枚舉值)。

ToString可以使用值{null,"1","2","3","4","5","6","7","8","9","10","J","Q","K"} 同樣地, {'♥','♦','♠','♣'}可以提供更好的輸出。

解析總是比輸出一個字符串更復雜,即使你對接受的內容非常嚴格,因為你必須處理無效輸入的可能性。 一個簡單的方法是:

private Card(string input)
{
  if(input == null)
    throw new ArgumentNullException();
  if(input.length < 2 || input.length > 3)
    throw new ArgumentException();
  switch(input[input.Length - 1])
  {
    case 'H': case 'h': case '♥':
      _suit = Suit.Hearts;
      break;
    case 'D': case 'd': case '♦':
      _suit = Suit.Diamonds;
      break;
    case 'S': case 's': case '♠':
      _suit = Suit.Spades;
      break;
    case 'C': case 'c': case '♣':
      _suit = Suit.Clubs;
      break;
    default:
      throw new ArgumentException();
  }
  switch(input[0])
  {
    case "J": case "j":
      _cardValue = 11;
      break;
    case "Q": case "q":
      _cardValue = 12;
      break;
    case "K": case "k":
      _cardValue = 13;
      break;
    case "A": case "a":
      _cardValue = 1;
      break;
    default:
      if(!int.TryParse(input.substring(0, input.Length - 1), out _cardValue) || _cardValue < 2 || _cardVaue > 10)
        throw new ArgumentException;
      break;
  }
}
public static Card Parse(string cardString)
{
  return new Card(cardString);
}

您可能希望添加一個讀取較大字符串的靜態方法,在解析時生成yield return卡片,以便更容易編碼多個卡片。

當我第一次開始使用card.dll時,我使用了套裝和卡片排名,但后來我不想處理同樣的問題並編寫額外的代碼來補償字符串,因為我寫了一個摘要class Info只有兩個變量(Flag(byte))和(Name(string))由Rank類和Suit類實現,它們是Card類的成員。 我發現這對命名約定和過濾目的更有效。 我喜歡使用枚舉但是必須解決變量命名問題可能很麻煩,所以有時最好不要將變量名稱作為字符串。

因此,當卡構造函數被調用時,輸入卡ID,然后它進入Rank和Suit,然后將ID分離代碼中的含義(101 = 100(套裝標志)+ 1(等級標志))。 受保護的抽象SetName(int cardID)和SetFlag(int cardID),同時通過Rank和Suit處理info的構造函數中的其余部分。 枚舉沒有更多問題,它仍然可以通過Flag按數字過濾。

該卡命名系統使用1到4 * 100(告訴套裝標志)+ 1到13(用於卡等級)。 500 + 14到16分別是Little Joker,Big Joker和Wild。

public class Card
{
    short id;

    public Card(string zFile)
    {
        this.id = Convert.ToInt16(zFile.Split('.')[0].Trim());
        this.Rank = new Rank(id);
        this.Suit = new Suit(id);
    }

    public override string ToString()
    {
        if (Suit.Flag == 5)
            return Suit.Name;
        return string.Concat(Rank.Name, " of ", Suit.Name);
    }
    public override int GetHashCode()
    {
        return id;
    }

    public Rank Rank { get; private set; }
    public Suit Suit { get; private set; }

    public static Card GetGreaterRank(Card value1, Card value2)
    {               
        return  (value1.Rank >= value2.Rank) ? value1 : value2;                        
    }

    public static bool CompareRank(Card value1, Card value2)
    {
        return (value1.Rank.Flag == value2.Rank.Flag);
    }
    public static bool CompareSuit(Card value1, Card value2)
    {
        return (value1.Suit.Flag == value2.Suit.Flag);
    }
};    
public abstract class Info
{
    protected Info(short cardID)
    {
        Flag = SetFlag(cardID);            
    }

    protected string SetName(short cardID, params string[] names)
    {
        for (int i = 0; i < names.Length; i++)
        {
           if (Flag == (i + 1))
              return names[i];
        }
        return "Unknown";
    }

    protected abstract byte SetFlag(short cardID);

    public static implicit operator byte(Info info)
    {
        return info.Flag;
    }

    public byte Flag { get; protected set; }
    public string Name { get; protected set; }
};

public class Rank : Info
{
    internal Rank(short cardID) : base(cardID) 
    { 
        string name = SetName(cardID, "A","2","3","4","5","6","7",
               "8","9","10","J","Q","K","Little Joker","Big Joker","Wild");
        Name = (name == "Unknown") ? string.Concat(name, " Rank") : name;
    }

    protected override byte SetFlag(short cardID)
    {
        return Convert.ToByte(cardID.ToString().Remove(0, 1));
    }        
};

public class Suit : Info
{
    internal Suit(short cardID) : base(cardID) 
    { 
        string name = SetName(cardID,"Clubs","Diamonds","Hearts","Spades");
        Name = (name == "Unknown") ? string.Concat(name, " Suit") ? name;
    }

    protected override byte SetFlag(short cardID)
    {
        return Convert.ToByte(cardID.ToString().Remove(1));
    }
};

所以現在,如果您的卡片圖像文件名為101.png並將其傳遞給Card ctor,它將傳遞給Rank和Suit獲取您的信息。 實際上你只是在為圖像文件提供名稱的代碼(數字)。

我可能會從2個枚舉開始,1代表Suits,1代表Faces。 然后根據這些枚舉聲明公共屬性“Suit”和公共屬性“Face”。 您可能還需要一個具有卡可以具有的不同唯一值的數組(即1到13)。

您可以使用數字啟動枚舉(盡管首選從零開始)

public enum Card
{
   Two = 2,
   Three,
   Four,
   ...
}

抓我之前寫的,這更好。

using System;

enum Suit
{
    Clubs,
    Hearts,
    Diamonds,
    Spades
}

class Card
{
    Suit Suit
    {
        get;
        private set;
    }

    int Value
    {
        get;
        private set;
    }

    Card(Suit suit, int value)
    {
        Suit = suit;
        Value = value;
    }

    private const string[] valsToString = new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };

    bool IsValid()
    {
        return Value >= 2 && Value <= 14;
    }

    override string ToString()
    {
        return string.Format("{0} of {1}", valsToString[Value - 2], Suit);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM