C# 确定一张扑克牌与手齐平
在卡片应用程序中,我使用0-51表示5张卡片的手 这套衣服是C# 确定一张扑克牌与手齐平,c#,.net,optimization,C#,.net,Optimization,在卡片应用程序中,我使用0-51表示5张卡片的手 这套衣服是card/13 排名为card% 只有4种可能的套装(黑桃、红桃、梅花钻石) 如果五套衣服都一样,那就是同花顺。所有冲洗都具有相同的价值。黑桃和钻石一样 我知道你会说预优化是邪恶的,但我正在进行一些模拟,做了数百万次,这是最昂贵的一步。卡可以是字节,但int的计算速度似乎更快。我没有真正检查范围,但我把它放进去了,这样你就会知道有一个范围 有没有更有效的方法 public bool IsFlush(int[] quick) {
card/13
排名为
card%
只有4种可能的套装(黑桃、红桃、梅花钻石) 如果五套衣服都一样,那就是同花顺。所有冲洗都具有相同的价值。黑桃和钻石一样 我知道你会说预优化是邪恶的,但我正在进行一些模拟,做了数百万次,这是最昂贵的一步。卡可以是字节,但int的计算速度似乎更快。我没有真正检查范围,但我把它放进去了,这样你就会知道有一个范围 有没有更有效的方法
public bool IsFlush(int[] quick)
{
HashSet<int> suit = new HashSet<int>();
suit.Add(quick[0] / 13);
int thisQuick;
for (int i = 1; i < quick.Length; i ++)
{
thisQuick = quick[i];
if (thisQuick < 0 || thisQuick > 51)
throw new IndexOutOfRangeException();
if (suit.Add(thisQuick / 13))
return false;
}
return true;
}
public bool IsFlush(int[]快速)
{
HashSet suit=新的HashSet();
suit.Add(快速[0]/13);
int thisQuick;
for(int i=1;i51)
抛出新的IndexOutOfRangeException();
如果(诉讼补充(thisQuick/13))
返回false;
}
返回true;
}
我会使用位域来存储有关卡的信息,它可能会更快,这样可以避免整数除法和模运算的开销
const Int32 SuitMask = 0x001100000;
const Int32 Spade = 0x000000000;
const Int32 Heart = 0x000100000;
const Int32 Diamond = 0x001000000;
const Int32 Club = 0x001100000;
public static Boolean AllCardsInHandOfSameSuit(Int32[] hand) {
Int32 countSpades = 0;
Int32 countHeart = 0;
Int32 countDiamonds = 0;
Int32 countClubs = 0;
foreach( Int32 card in hand ) {
Int32 suit = card & SuitMask;
switch( suit ) {
case Spade:
countSpades++;
break;
case Heart:
countHearts++;
break;
case Diamond:
countDiamonds++;
break;
case Club:
countClubs++;
break;
}
}
// Your question is not worded clearly about whether or not you care about unique ranks, only unique suits:
// I'm also unsure of your flush/hand rules, but just compare the counts as-required:
Boolean allSameSuit =
( countSpades == 0 || countSpades == hand.Length ) &&
( countHearts == 0 || countHearts == hand.Length ) &&
( countDiamonds == 0 || countDiamonds == hand.Length ) &&
( countClubs == 0 || countClubs == hand.Length );
Boolean allDifferentSuit =
countSpades <= 1 &&
countHearts <= 1 &&
countDiamonds <= 1 &&
countClubs <= 1;
}
例如:
Int32[] deck = new Int32[52];
for( Int32 i = 0; i < deck.Length; i++ ) {
Int32 suit =
i / 13 == 0 ? Spade :
i / 13 == 1 ? Heart :
i / 13 == 2 ? Diamond : Club;
deck[i] = CreateCard( suit, i % 13 );
}
Int32[] hand = new Int32[4];
for( Int32 i = 0; i < hand.Length; i++ ) {
hand[i] = deck[ GetRandomIndexPreviouslyUnused() ];
}
Int32[]deck=newint32[52];
对于(Int32 i=0;i
消除哈希集
应该会加快速度:
public static bool IsFlush(int[] hand)
{
int firstSuit = hand[0] / 13;
for (int i = 1; i < hand.Length; i++)
{
int card = hand[i];
if (card < 0 || card > 51)
throw new IndexOutOfRangeException();
if (firstSuit != (card / 13))
return false;
}
return true;
}
公共静态bool IsFlush(int[]hand)
{
int firstSuit=hand[0]/13;
for(int i=1;i51)
抛出新的IndexOutOfRangeException();
如果(第一套!=(卡片/13))
返回false;
}
返回true;
}
我的测试(承认很差)显示性能提高了约20%。本机“字”大小的整数总是比较小的单位(如
字节)快,因为处理器就是围绕这个单位大小构建的。对于x86,它是Int32
对于x64,它是Int64
。不幸的是,C不具有与C++不同的“<代码> FastInt <代码> >别名,因此如果你真的关心这个特定的微优化,那么你需要一个单独的X64代码路径。整数除法非常昂贵-我敢打赌这将比Byte
vsInt32
vsInt64
消耗更多的挂钟时间。请注意,从本质上讲,哈希表并不完全便宜-因为它们必须分配足够大的bucket表并执行键哈希和相等检查。如果一副牌只有52张牌,我想你最好用一个简单的本机数组。@Dai我不明白你说的本机数组是什么意思?@Paparazzi,例如int[]
你可以更疯狂地进行微优化,改为使用字节(8位给你的比你需要的更多)。您可以将i/13
放入一个变量中,以便每次迭代只计算一次(内存更多,但计算速度更快)。但是,请确保在循环外部创建此变量,并在循环中重新赋值,以便只使用内存中的一个点。然后,对于齐平检查,迭代该手,当下一套西装与上一套西装不匹配时,返回false。最坏的情况是,你迭代了整手牌,最好的情况是,你只迭代了手中的两张牌。我会检查这个。规定了关于同花顺的规则。“如果五套衣服都是一样的,那就是同花顺。”如果是同花顺,那么所有的牌都必须有不同的等级。没错,你还必须进行等级检查。。。最好的情况仍然是只迭代两张牌(如果他们的套装不匹配,你甚至不需要检查等级)。@StephenPorter不,你不需要等级检查。在5张牌中,如果它们都是同一套牌,则表示同花顺(或同花顺)。不需要额外检查。如果你有一个同花顺,它不可能是一条船或四边形。我知道这是怎么回事,但现在重构卡将是一项工作。我只是想到这一点自己+1我得到了超过20%的分数。如果你假设你的牌组是完美的(例如,你不可能有相同等级的同一套牌(根据我们在另一个答案中的对话)),那么为什么不假设你的牌不可能少于0或超过51张呢?然后,您可以通过不检查IndexOutOfRange标准来节省CPU时间。我在我的基准测试中尝试了这一点,结果证明它对代码的运行时几乎没有影响。
public static bool IsFlush(int[] hand)
{
int firstSuit = hand[0] / 13;
for (int i = 1; i < hand.Length; i++)
{
int card = hand[i];
if (card < 0 || card > 51)
throw new IndexOutOfRangeException();
if (firstSuit != (card / 13))
return false;
}
return true;
}