IOS: Как создать 8 уникальных случайных чисел?

Мне нужно сгенерировать 8 случайных целых чисел, но они должны быть уникальными, ака не повторяться.

Например, я хочу 8 чисел в диапазоне от 1 до 8.

Я видел arc4random, но я не уверен, как сделать их уникальными?

Решение

-(NSMutableArray *)getRandomInts:(int)amount from:(int)fromInt to:(int)toInt {

  if ((toInt - fromInt) +1 < amount) {
      return nil;    
  }

  NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
  int r;
  while ([uniqueNumbers count] < amount) {

      r = (arc4random() % toInt) + fromInt;
      if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
          [uniqueNumbers addObject:[NSNumber numberWithInt:r]];
      }
  }
  return uniqueNumbers;
}

Ответ 1

-(NSMutableArray *)getEightRandom {
  NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
  int r;
  while ([uniqueNumbers count] < 8) {
    r = arc4random();
    if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
      [uniqueNumbers addObject:[NSNumber numberWithInt:r]];
    }
  }
  return uniqueNumbers;
}

Если вы хотите ограничить числа, меньшие некоторого порога M, вы можете сделать это:

-(NSMutableArray *)getEightRandomLessThan:(int)M {
  NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
  int r;
  while ([uniqueNumbers count] < 8) {
    r = arc4random() % M; // ADD 1 TO GET NUMBERS BETWEEN 1 AND M RATHER THAN 0 and M-1
    if (![uniqueNumbers containsObject:[NSNumber numberWithInt:r]]) {
      [uniqueNumbers addObject:[NSNumber numberWithInt:r]];
    }
  }
  return uniqueNumbers;
}

Если M = 8, или даже если M близко к 8 (например, 9 или 10), то это занимает некоторое время, и вы можете быть более умным.

-(NSMutableArray *)getEightRandomLessThan:(int)M {
  NSMutableArray *listOfNumbers = [[NSMutableArray alloc] init];
  for (int i=0 ; i<M ; ++i) {
    [listOfNumbers addObject:[NSNumber numberWithInt:i]]; // ADD 1 TO GET NUMBERS BETWEEN 1 AND M RATHER THAN 0 and M-1
  }
  NSMutableArray *uniqueNumbers = [[[NSMutableArray alloc] init] autorelease];
  int r;
  while ([uniqueNumbers count] < 8) {
    r = arc4random() % [listOfNumbers count];
    if (![uniqueNumbers containsObject:[listOfNumbers objectAtIndex:r]]) {
      [uniqueNumbers addObject:[listOfNumbers objectAtIndex:r]];
    }
  }
  [listOfNumbers release];
  return uniqueNumbers;
}

Ответ 2

Уникальность - это то, что вам нужно предоставить - API-интерфейсы случайности не сделают этого для вас.

Как было предложено, вы можете сгенерировать число, а затем проверить, сталкивается ли он с чем-то, что вы уже сгенерировали, и если да, попробуйте agin. Обратите внимание, однако, что в зависимости от количества номеров и размера диапазона это становится алгоритмом, который не имеет гарантированной конечной точки.

Если вы действительно пытаетесь получить смежный набор чисел в случайном порядке, это не способ сделать это, так как это может занять непредсказуемое долгое время. В этом случае сначала создается массив всех желаемых значений, а затем "перетасовка" массива - лучший выбор. Лучшим тасованием является Fisher-Yates, но если вам не нужно, чтобы он был совершенно непредвзятым, вы также могли бы сделать то, что описано здесь.

Ответ 3

Проверка уже сгенерированных чисел является потенциально дорогостоящей (теоретически это может занять бесконечно.) Однако это проблема. Вам нужен алгоритм перетасовки, например Fisher-Yates_shuffle

В iOS возможно что-то вроде:

NSMutableArray *randSequence = [[NSMutableArray alloc] initWithCapacity:8];
for (int ii = 1; ii < 9; ++ii)
    [randSequence addObject:[NSNumber numberWithInt:ii]];

for (int ii = 8; ii > 0; --ii) {
    int r = arc4random() % (ii + 1);
    [randSequence exchangeObjectAtIndex:ii withObjectAtIndex:r];

// you can now iterate over the numbers in `randSequence` to get
// your sequence in random order

Ответ 4

Сохраняйте числа в массиве, и каждый раз, когда вы создаете следующий, проверьте, существует ли он в массиве. Если нет, добавьте его и продолжите.

Ответ 5

Здесь некоторый код psuedo

  • Для каждого номера 1-8 генерируется случайное число.
  • Добавить случайное число и целое число в словарь как пару ключевых значений
  • получить все ключи словаря в виде массива (подсказка: взглянуть на метод allKeys)
  • Сортировка этого массива (по возрастанию или по убыванию не важно)
  • Теперь для каждого из этих чисел в качестве ключа, получите соответствующее целое число из словаря

Ответ 6

Попробуйте этот код... это даст вам все возможные уникальные номера, установленные в Mutable array...

-(NSInteger) randomNumber {
NSInteger newRandomNumber = (NSInteger) arc4random() % 10;
NSInteger uniqueNumber;
if ([self.arrayContainingNumbers containsObject: [NSNumber numberWithInteger:newRandomNumber]]) {
    [self randomNumber];
    } else {
    [self.arrayContainingNumbers addObject: [NSNumber numberWithInteger:newRandomNumber]];
}
uniqueNumber = [[self.mutableArrayContainingNumbers lastObject]integerValue];
     NSLog(@"new Unique Number is %ld",(long)uniqueNumber);

return uniqueNumber;  
}

Не забудьте добавить этот метод:)

    -(NSMutableArray *) arrayContainingNumbers {
if (!_mutableArrayContainingNumbers) {
    _mutableArrayContainingNumbers = [[NSMutableArray alloc] init];
}
return _mutableArrayContainingNumbers; 
}