我使用类卡,其中包含2个枚举属性(套件 - 心形钻石黑桃和俱乐部)和卡值从2到A.并覆盖ToString()方法返回类似Ah Ad等的东西。一切正常,但枚举值可以从数字开始,因此枚举的卡片值看起来像x2,x3,x4 ......它不漂亮。
还需要简单的方法来解析单个字符串中的几张卡片。
谁知道设计这门课程的最佳方法?
答案 0 :(得分:4)
难道你不能将Jack,Queen,King和Ace分别分别为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's answer获取Card(string input)
的结构。
答案 1 :(得分:2)
pip卡有一个明显的数值,我们可以加J = 11,Q = 12,K = 13.
根据正在建模的游戏,A = 14比A = 1可能更方便(因此可以更简单地计算不同的手的相对值)。
枚举没有真正的优势,特别是因为枚举允许超出范围的值,除非您明确检查它们(例如,没有什么可以阻止某人将(CardValue)54
分配给卡值枚举值。
可以使用值{null,"1","2","3","4","5","6","7","8","9","10","J","Q","K"}
的数组辅助ToString。同样地,{'♥','♦','♠','♣'}
可以提供更好的输出。
解析总是比输出字符串更复杂,即使你对接受的内容非常严格,因为你必须处理无效输入的可能性。一个简单的方法是:
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
卡,以便更容易编码多张卡。
答案 2 :(得分:1)
当我第一次开始使用card.dll时,我使用的是套装和卡片排名,但后来我不想处理相同的问题并编写额外的代码来补偿字符串,那里为我写了一个只有两个变量的抽象类Info (Flag(byte))和(Name(string))由Rank类和Suit类实现,它们将是Card类的成员。我发现这对命名约定和过滤目的更有效。我喜欢使用枚举但是必须解决变量命名问题可能很麻烦,所以有时最好不要将变量名称作为字符串。
因此,当卡构造函数被调用时,输入卡ID,然后它进入Rank和Suit,然后将ID分隔代码中的含义(101 = 100(套装标志)+ 1(等级标志))。受保护的抽象SetName(int cardID)和SetFlag(int cardID),同时通过Rank和Suit处理info的构造函数中的其余部分。没有更多的枚举问题,它仍然可以通过数字按数字过滤。
答案 3 :(得分:1)
此卡命名系统使用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获取您的信息。实际上你只是在为图像文件提供名称的代码(数字)。
答案 4 :(得分:0)
我可能会从2个枚举开始,1代表Suits,1代表Faces。然后根据这些枚举声明公共属性“Suit”和公共属性“Face”。您可能还需要一个具有卡可以具有的不同唯一值的数组(即1到13)。
答案 5 :(得分:0)
您可以使用数字启动枚举(尽管最好从零开始)
public enum Card
{
Two = 2,
Three,
Four,
...
}
答案 6 :(得分:0)
抓一下我之前写的,这样更好。
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);
}
}