Objective c obj-c:在不包括变量2的范围内生成随机数

Objective c obj-c:在不包括变量2的范围内生成随机数,objective-c,cocos2d-iphone,Objective C,Cocos2d Iphone,我正在生成一个介于0和topOfRange之间的随机数。我可以使用以下代码排除firstNumberToExclude: NSInteger aRandom; while ((aRandom = arc4random()%topOfRange) == firstNumberToExclude); 如果我要排除两个数字:firstNumberToExclude和secondNumberToExclude,怎么样?这是我的计划,但似乎不合适: NSInteger aRandom = arc4ran

我正在生成一个介于0和topOfRange之间的随机数。我可以使用以下代码排除firstNumberToExclude:

NSInteger aRandom;
while ((aRandom = arc4random()%topOfRange) == firstNumberToExclude);
如果我要排除两个数字:firstNumberToExclude和secondNumberToExclude,怎么样?这是我的计划,但似乎不合适:

NSInteger aRandom = arc4random()%topOfRange;
while (aRandom == firstNumberToExclude || aRandom == secondNumberToExclude)
    {
    aRandom = arc4random()%topOfRange;
    }
试试这个:

NSInteger aRandom = arc4random()%topOfRange;
NSMutableArray *exludedNumbers = [NSMutableArray arrayWithObjects:
    [NSNumber numberWithInt: firstNumberToExclude],
    [NSNumber numberWithInt: secondNumberToExclude],
    nil];
BOOL flag = YES;
while (flag)
{
    flag = NO;
    for (NSNumber *numberToExclude in excludedNumbers)
    {
        if (numberToExclude.intValue == aRandom)
        {
            flag = YES;
            aRandom = arc4random()%topOfRange;
            break;
        }
    }
}

因此,您可以动态添加和删除要从数组中排除的数字

如果您将其重构为实用方法,我认为您的代码将更干净,更易于维护:

+ (NSInteger)generateRandomExcluding:(NSArray *)exclude topOfRange:(NSInteger)topOfRange {
    NSInteger aRandom = arc4random_uniform(topOfRange);
    while ([exclude containsObject:[NSNumber numberWithInteger:aRandom]]) {
        aRandom = arc4random_uniform(topOfRange);
    }
    return aRandom;
}
然后你可以这样称呼它:

NSNumber *excludeOne = [NSNumber numberWithInt:5];
NSNumber *excludeTwo = [NSNumber numberWithInt:13];

NSInteger random = [MyClass generateRandomExcluding:[NSArray arrayWithObjects:excludeOne, excludeTwo, nil] topOfRange:100];

最近在寻找相同的解决方案时遇到了这个问题。我认为while循环是一个非常糟糕的主意,对于随机数,你无法真正知道需要多长时间。因此,我又尝试了一次,并采用了其他解决方案

生成随机数时考虑排除的数字池,然后检查该数字是否大于任何排除的数字,并为每个数字增加1

- (NSInteger) randomNumberExcluding:(NSArray <NSNumber *> *) excludedNumbers range:(NSRange) range
{
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"integerValue >= %d AND integerValue =< %d", range.location, NSMaxRange(range)];
    NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:@"integerValue" ascending:YES];
    excludedNumbers = [[excludedNumbers filteredArrayUsingPredicate:pred] sortedArrayUsingDescriptors:@[sorter]];
    NSInteger base = arc4random_uniform((uint32_t)(range.length - excludedNumbers.count + 1)) + (NSInteger)range.location;
    for (NSNumber *excludedNumber in excludedNumbers) {
        if (base >= excludedNumber.integerValue) {
            base++;
        }
    }
    return base;
}
-(NSInteger)随机数包括:(NSArray*)不包括数字范围:(NSRange)范围
{
NSPredicate*pred=[NSPredicate predicateWithFormat:@“integerValue>=%d和integerValue=<%d”,range.location,NSMaxRange(range)];
NSSortDescriptor*分类器=[NSSortDescriptor SortDescriptor With Key:@“integerValue”升序:是];
excludedNumbers=[[excludedNumbers FilteredArraying谓词:pred]SortedArraying描述符:@[sorter]];
NSInteger base=arc4random_uniform((uint32_t)(range.length-excludedNumbers.count+1))+(NSInteger)range.location;
用于(NSNumber*excludedNumber中的excludedNumber){
if(base>=excludedNumber.integerValue){
base++;
}
}
返回基地;
}

只要循环中的条件为真,您就可以分配aRandom。。。似乎是错的,你的意思是这样吗?@driis它没有错,如果
aRandom
等于要排除的数字之一,那么你需要生成一个新的随机数,并将其重新分配给
aRandom
@driis:在第二个示例中,你的意思是?是的,我只想在条件为真的情况下重新分配aRandom,然后当它重新分配到某个对象时,重新检查代码是否正常。有什么问题吗?我会使用do/while循环来代替它——它更干净一些。你如何传递要排除的数字?是这些变量的数量以及它们的值吗?这个解决方案很简单。您可以像craig使用-containsObject方法那样改进它,但意义是一样的。您还应该使用arc4random_uniform(上界)来避免模偏差。我的代码确实有效,错误在其他地方,但这也有效,而且干净有用。谢谢@craig。