下面是NSMutableArray的一个类别,用于将数组随机移动。它在小阵列上做的不错,但请注意,使用的随机数函数mrand48()
没有足够的随机性来产生一副牌的所有可能的混洗,所以在产生的混洗中存在一些偏差。如果你的游戏纯粹是为了娱乐,这可能就足够了。如果没有,您可以用更好的发生器替换mrand48()
。
不要忘记在srand48()
启动时播种随机数发生器。
// --- NSMutableArray+Random.h ---
#import <Foundation/Foundation.h>
@interface NSMutableArray (Random)
/// Shuffle a mutable array in place. Uses a Fisher-Yates shuffle as described
/// in http://en.wikipedia.org/wiki/Fisher-Yates_shuffle .
- (void)shuffle;
@end
// --- NSMutableArray+Random.m
#import "NSMutableArray+Random.h"
/// Return a pseudo-random unsigned integer in the range
/// [0, exclusiveUpperBound) using the mrand48() function.
/// Seed the random number state by calling srand48().
/// See http://developer.apple.com/iphone/library/documentation/System/Conceptual/ManPages_iPhoneOS/man3/rand48.3.html
static NSUInteger randomUIntegerFromZeroUpTo(NSUInteger exclusiveUpperBound) {
NSUInteger const maxUInteger = 0xffffffff;
NSUInteger largestMultipleOfMaxUInteger
= maxUInteger - (maxUInteger % exclusiveUpperBound);
// discard random integers outside the range [0, largestMultipleOfMaxUnsignedInteger)
// to eliminate modulo bias
NSUInteger randomUInteger;
do {
randomUInteger = (NSUInteger) mrand48();
} while (randomUInteger >= largestMultipleOfMaxUInteger);
return randomUInteger % exclusiveUpperBound;
}
@implementation NSMutableArray (Random)
- (void)shuffle {
for (NSUInteger unshuffled = self.count; unshuffled > 1; --unshuffled) {
NSUInteger index1 = unshuffled - 1;
NSUInteger index2 = randomUIntegerFromZeroUpTo(unshuffled);
[self exchangeObjectAtIndex:index1 withObjectAtIndex:index2];
}
}
@end