[英]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.