Objective c 从牌堆中抽出一张牌,进行扑克的蒙特卡罗模拟
目前,我正在开发一个iOS应用程序,在这个应用程序中,我需要从卡片组中随机抽取卡片。目前,我的代码如下所示:Objective c 从牌堆中抽出一张牌,进行扑克的蒙特卡罗模拟,objective-c,random,montecarlo,poker,Objective C,Random,Montecarlo,Poker,目前,我正在开发一个iOS应用程序,在这个应用程序中,我需要从卡片组中随机抽取卡片。目前,我的代码如下所示: - (PlayingCard*) drawRandomCard { PlayingCard * randomCard = nil; NSUInteger index = arc4random_uniform(self.cards.count); randomCard = self.cards[index]; //self.cards is an NSArray
- (PlayingCard*) drawRandomCard
{
PlayingCard * randomCard = nil;
NSUInteger index = arc4random_uniform(self.cards.count);
randomCard = self.cards[index]; //self.cards is an NSArray of PlayingCard's
while (randomCard.isUsed) {
index = arc4random_uniform(self.cards.count);
randomCard = self.cards[index];
}
randomCard.used = YES;
return randomCard;
}
这种方法被调用了很多次(一次蒙特卡罗模拟调用了50'000-1'000'000次)目前,整个事情是缓慢的,我真的需要优化它。 我有一些想法:
- 快速随机数发生器
- 将牌组(Objective-C类,包括一系列玩牌)和牌(Objective-C类)的整个高级表示形式更改为普通C数组和结构中的表示形式
- 将牌组和牌的整个表示更改为按位级别,然后在下面执行所有操作
你还有其他想法吗?
你知道更适合(更快)的随机数发生器吗
提前谢谢 我假设您多次调用此方法从牌组中抽牌,将抽牌的
used
属性设置为YES
,以便不再抽牌
您不必设置属性,只需将卡从卡组中取出,并将其放入usedCards
数组中,就可以在循环时为您保存可能永不结束的
另一种方法是先洗牌,然后从数组的开头或结尾抽牌。保持一个指向最后抽牌的静态索引(最初设置为-1)。每次调用该方法时,将索引模向前推进self.cards.count
,如果结果为零,则洗牌组。然后在索引处返回卡片。因为像Fisher Yates/Knuth这样一个像样的洗牌是θ(self.cards.count
),但是在self.cards.count
)中只调用一次,所以每次平局的结果是摊销固定时间。这应该避免由于识别已绘制的值和拒绝而产生的任何开销。如果您想避免在重新洗牌之前处理整个牌组,可以添加重置方法。通过随机查看循环中的整个牌组
while(randomCard.isUsed){
不仅是那些还在使用中的牌,当你到达牌组末端时,你会得到很多重试次数。最后一张牌(数字52)在average上的未命中次数超过25次。t将一张全牌组转换平均总共会有超过600次未命中
除此之外,您还需要在再次使用牌组之前重置牌组。我猜您有一种方法可以通过循环所有牌来重置牌组,并执行used=NO
。这将在牌组上执行52次操作,即使您只需要处理一张牌
通过这个简单的解决方案,您可以避免这两个问题
将你所有的牌储存在一个阵列中。然后将一端用于尚未发放的牌,另一端用于已发放的牌:
<---------------------- not yet dealt ---------------------->
[ ah 2h 3h 4h 5h 6h 7h 8h 9h 10h jh qh kh ad 2d ..... jk qk kk ]
^
dealt
cards
将其与最后一张尚未发牌的牌切换,并将发牌指针移到左侧
<-------------------- not yet dealt --------------------->
[ ah 2h 3h 4h 5h 6h kk 8h 9h 10h jh qh kh ad 2d ..... jk qk 7h ]
^
dealt
cards
[ah 2h 3h 4h 5h 6h kk 8h 9h 10h jh qh kh ad 2d…..jk qk 7h]
^
处理
卡
根据需要重复以下步骤:
<------------------ not yet dealt ----------------->
[ ah 2h qk 4h 5h 6h kk 8h 9h 10h jh jk kh ad 2d ..... qh 3h 7h ]
^
dealt
cards
[ah 2h qk 4h 5h 6h kk 8h 9h 10h jh jk kh ad 2d…..qh 3h 7h]
^
处理
卡
当你需要新牌组时,只需将已发牌指针移回末端,牌组即可开始新的使用
<----------------------- not yet dealt ---------------------->
[ ah 2h qk 4h 5h 6h kk 8h 9h 10h jh jk kh ad 2d ..... qh 3h 7h ]
^
dealt
cards
[ah 2h qk 4h 5h 6h kk 8h 9h 10h jh jk kh ad 2d…..qh 3h 7h]
^
处理
卡
牌组的新顺序只是增加了随机性…执行此操作的原因是,我必须从牌组中抽出一些(2-23)张牌,进行一些计算,然后重置牌组,并一次又一次地执行所有这些操作(50'000-1'000'000次)…所以我真的不知道你的建议是否会加快速度。因为我认为创建NSArray、处理某些元素、复制元素(重置)的开销比仅仅设置一些布尔值更大,然后将布尔值设置回重置…你能解释一下为什么你认为这会有帮助吗?似乎你的while循环并不像我想象的那样是一个瓶颈(除非抽到的牌的数量非常接近牌组的大小).我将我的实现更改为此,效果很好!谢谢!你有其他提高速度的想法吗?那么现在有多快?什么部分需要花费时间?因此,如果你使用解决方案,也许你可以接受答案?
<----------------------- not yet dealt ---------------------->
[ ah 2h qk 4h 5h 6h kk 8h 9h 10h jh jk kh ad 2d ..... qh 3h 7h ]
^
dealt
cards