我有一个'Hand'课程,由两张扑克牌组成,如下所示:
public class Card
{
public char r, s;
public Card(char rank, char suit)
{
r = rank;
s = suit;
}
}
public class Hand
{
public Card c1, c2;
public Hand(Card one, Card two)
{
c1 = one;
c2 = two;
}
}
在52张牌中,我们不能有两张相同的牌。我怎么应该处理一个错误,我不小心用两张相同的牌来实例,例如(啊,啊)?
谢谢,Ash
答案 0 :(得分:4)
甲板不应该处理吗?例如,你可以有一个pinochle牌组和一个常规牌组来强制执行卡片实例限制。
答案 1 :(得分:3)
抛出ArgumentException将是一个可接受的解决方案。来自MSDN:
当调用方法并且至少有一个传递的参数不符合被调用方法的参数规范时,抛出ArgumentException。
当然,您必须在代码中更高的位置捕获异常并适当地处理它。
答案 2 :(得分:2)
当您创建卡片组时,确保没有重复的应由甲板负责。甲板创建可以有不同游戏的多个构造函数。
答案 3 :(得分:2)
如果这是例外的典型情况,并且不应该发生,那么他们抛出异常可能是正确的做法。我会尽一切努力阻止这种情况发生。
答案 4 :(得分:2)
我想我明白你要做什么。
您可以考虑的一件事是防止情况发生。我会HandFactory
我可以致电createHand(2)
,其中2
是要处理的卡数。
在createHand
内,你自己处理一张卡片,从52张卡片中取出该卡片,然后随机选择另一张卡片。通过这种方式,您可以拥有Ah Ad,Ah Ac,Ah As等。下次拨打createHand()
在这个例子中,有一些明显的事情我会忽略,如果我处理53张牌会发生什么?我会留下那个让你弄明白的。这不是线程安全的。 Shuffle()也没有真正洗牌。你可以在Shuffle
中做的一件事就是随机化卡片并改变DealCard()来取代列表顶部的卡片。
示例强>
namespace StackOverflow_4599533
{
public class Deck
{
private static Random sRand = new Random();
private List<Card> mCards = new List<Card>();
public Deck()
{
Shuffle();
}
public void Shuffle()
{
mCards.Clear();
foreach (char suit in "DSCH") // Diamond, Spade, Clover, Heart
{
foreach (char rank in "1234567890JQK")
{
mCards.Add(new Card(rank, suit));
}
}
}
public Card DealCard()
{
int cardIndex = sRand.Next(mCards.Count);
Card card = mCards[cardIndex];
mCards.Remove(card);
return card;
}
}
public class Card
{
public char r, s;
public Card(char rank, char suit)
{
r = rank;
s = suit;
}
public override string ToString()
{
return "" + s + r;
}
}
public class Hand
{
public Card c1, c2;
public Hand(Card one, Card two)
{
c1 = one;
c2 = two;
}
public override string ToString()
{
return "C1: " + c1 + " C2: " + c2;
}
}
public class Dealer
{
private Deck mDeck;
public Dealer(Deck deck)
{
mDeck = deck;
}
public Hand DealHand()
{
return new Hand(mDeck.DealCard(), mDeck.DealCard());
}
}
class Program
{
static void Main(string[] args)
{
Deck deck = new Deck();
Dealer dealer = new Dealer(deck);
Hand hand1 = dealer.DealHand();
Hand hand2 = dealer.DealHand();
Console.WriteLine(hand1);
Console.WriteLine(hand2);
deck.Shuffle();
hand1 = dealer.DealHand();
hand2 = dealer.DealHand();
Console.WriteLine(hand1);
Console.WriteLine(hand2);
}
}
}
<强>策略强>
如果您想真正深入了解设计方法,可以开始使用策略来处理卡片,专用卡片等。
要真正防止有人创建无效的手,请考虑此代码正在执行的操作
public interface Hand
{
Card C1
{
get;
}
Card C2
{
get;
}
}
public interface Dealer
{
Hand DealHand();
}
public class SpecialDealer : Dealer
{
private Deck mDeck;
private class HandImpl : Hand
{
private Card mC1;
private Card mC2;
public Card C1
{
get
{
return mC1;
}
}
public Card C2
{
get
{
return mC2;
}
}
public HandImpl(Card c1, Card c2)
{
mC1 = c1;
mC2 = c2;
}
public override string ToString()
{
return C1 + " " + C2;
}
}
public SpecialDealer(Deck deck)
{
mDeck = deck;
}
public Hand DealHand()
{
return new HandImpl(mDeck.DealCard(), mDeck.DealCard());
}
}
答案 5 :(得分:2)
我的建议是创建一个Exception结构,您可以用更清晰的方式识别错误,以便能够处理错误。
例如,如果您要创建可能具有不同业务规则的游戏,则大多数业务规则异常应从基础GameRuleException继承。在这种情况下,在您的场景中,我将创建一个特定的异常,如HandCardException,它继承GameRuleException。
拥有此层次结构的重要性在于,当您捕获异常时,您可以确定错误来自游戏规则,而不是例如连接问题。
请参阅下面的示例 - 请注意我没有测试代码,只是为了说明
public class GameRuleException : Exception
{
public GameException(string message) : base(message)
{
}
}
public class HandCardException : GameRuleException
{
public HandCardException(string message) : base(message)
{
}
}
public class Card
{
public int r;
public char s;
public Card(int rank, char suit)
{
r = rank;
s = suit;
if (rank > 13 || rank < 1) {
throw new GameRuleException("The card rank must be between 1 and 13");
}
}
}
public class Hand
{
public Card c1;
public Card c2;
public Hand(Card one, Card two)
{
//Basic validation
if (one == null || two == null) {
throw new HandCardException("Each hand needs at least two cards");
}
if (one == two) {
throw new HandCardException("Repeated cards are found.");
}
//Allows creating the instance
c1 = one;
c2 = two;
}
}
然后正在使用这些类的应用程序何时可以正确处理这些异常...例如:
try {
Hand hand = new Hand(card1, card2);
} catch (GameRuleException ex) {
//Handle the error by showing the error in a label ...
ErrorLabel.Text = ex.message;
} catch (Exception ex) {
//Any other exception will log
//Trace.Error(ex)
//And maybe throw back the exception... ?
//Throw
}
这只是一个如何使用自定义异常来更恰当地处理它们的示例。
答案 6 :(得分:-1)
如果“Deck”对象将相同的卡传递给单个“Hand”对象,则表示该进程的状态无效。 Hand对象应使用键控集合来存储卡片,如果将复制键添加到集合中,则集合本身将为您抛出异常。所以要回答这个问题,不要处理Hand类中的错误。允许它在层次结构中冒泡。