如何生成非重复随机数

时间:2012-11-30 06:37:13

标签: objective-c cocoa arc4random

我想在数组中随机化数字。我可以使用arc4random() % [indexes count]

来做到这一点

我的问题是 - 如果一个数组由20个项组成,每次数组洗牌时,在5个批次中,应该出现不同的数字。示例:

第一次洗牌:1,4,2,5,6。

第二次洗牌:7,12,9,15,3

-(IBAction)randomNumbers:(UIButton *)sender
{
    int length = 10; // int length = [yourArray count];

    NSMutableArray *indexes = [[NSMutableArray alloc] initWithCapacity:length];
    for (int i=0; i<5; i++)
        [indexes addObject:[NSNumber numberWithInt:i]];

    NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:length];

    while ([indexes count])
    {
        int index = arc4random() % [indexes count];
        [shuffle addObject:[indexes objectAtIndex:index]];
        [indexes removeObjectAtIndex:index];
    }

    //    for (int i=0; i<[shuffle count]; i++)
    NSLog(@"%@", [shuffle description]);
}

4 个答案:

答案 0 :(得分:2)

根据您的要求....请查看此代码

将此作为属性

@synthesize alreadyGeneratedNumbers;

在.m

中添加这些方法
-(int)generateRandomNumber{

    int TOTAL_NUMBER=20;

    int low_bound = 0;
    int high_bound = TOTAL_NUMBER;
    int width = high_bound - low_bound;
    int randomNumber = low_bound + arc4random() % width;

    return randomNumber;
}


-(IBAction)randomNumbers:(UIButton *)sender
{

    NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:5];

    BOOL contains=YES;
    while ([shuffle count]<5) {
        NSNumber *generatedNumber=[NSNumber numberWithInt:[self generateRandomNumber]];
        //NSLog(@"->%@",generatedNumber);

        if (![alreadyGeneratedNumbers containsObject:generatedNumber]) {
            [shuffle addObject:generatedNumber];
            contains=NO;
            [alreadyGeneratedNumbers addObject:generatedNumber];
        }
    }

    NSLog(@"shuffle %@",shuffle);
    NSLog(@"Next Batch");


    if ([alreadyGeneratedNumbers count] >= TOTAL_NUMBER) {
        NSLog(@"\nGame over, Want to play once again?");//or similar kind of thing.
        [alreadyGeneratedNumbers removeAllObjects];
    }


}

我还是觉得你需要做一些改变,比如

它会给你正确的价值,但是如果用户第五次按下该怎么办?

在20个数字中你已经选择了4组5个数字,在第6次它将循环搜索下一组数字并且将变为无限。

所以你可以做的是,保持随机播放的轨道,一旦达到极限,即20/5 = 4禁用随机按钮。

答案 1 :(得分:1)

声明包含已在扩展名或头文件中生成的数字的数组

@property (strong, nonatomic)NSMutableArray *existingNums;
@property (assign, nonatomic)NSInteger maxLimit;
@property (assign, nonatomic)NSInteger minLimit;

然后在实现文件中实现给定的代码

@synthesize existingNums;
@synthesize maxLimit;
@synthesize minLimit;

- (NSInteger)randomNumber {

    if(!existingNums)
        existingNums = [NSMutableArray array];

    while (YES) {

        NSNumber *randonNum = [NSNumber numberWithInteger:minLimit+arc4random()%maxLimit];

        if([existingNums containsObject:randonNum]) {

            if([existingNums count] == (maxLimit - minLimit))
                return -1; // All possible numbers generated in the given range

            continue;
        }

        [existingNums addObject:randonNum];

        return [randonNum integerValue];
    }

    return -1;   // return error
}

希望这会对你有所帮助:)。

答案 2 :(得分:1)

这个适用于我:

    NSMutableArray *numbers = [NSMutableArray new];
    BOOL addElement = YES;
    int limit = 100; // Range from 0 to 36
    int numElem = 10; // Number of elements
    do
    {
        int ranNum = (arc4random() % limit) +1;
        if ([numbers count] < numElem) {
            for (NSNumber *oneNumber in numbers) {
                addElement =([oneNumber intValue] != ranNum) ? YES:NO;
                if (!addElement) break;
            }
            if (addElement) [numbers addObject:[NSNumber numberWithInt:ranNum]];
        } else {
            break;
        }
    } while (1);
    NSLog(@"%@",numbers);

答案 3 :(得分:0)

所有这些答案的问题在于,您需要查看以前生成的随机数,如果需要大量随机整数,则需要额外的时间。

另一种解决方案是使用加密技术:

  1. 生成随机密钥
  2. 在0..n
  3. 之间迭代
  4. 加密每个整数,并将模块的数量应用于函数的输出。
  5. 有一些额外的细节需要考虑,这与您的情况无关。