2013-02-21 48 views
1

我在使用Xcode中的arc4random生成隨機值時遇到了問題。我想從隨機生成中排除那些已經被選中的數字。這是我wr algorithm的算法Array對於Xcode中的隨機數在非重複算法中爲空arc4random

int randomValue = (arc4random() % numberofquest)+ 1; 
int kk=1; 

if (kk==1) { 

//first time add the first random value 
[oldquest addObject: randomValue]; 
    } 
else { 
     //control if the number is already in the vector 
     for (int j=1; j<[oldquest count]; j++) 
     { 

      if (randomValue==oldquest[j]) 
      { 

       randomValue = (arc4random() % numerodomande)+ 1; 
      } 
      else 
      { 
       [oldquest addObject: randomValue]; 
      } 
     } 

} 
kk=kk+1 

但它不起作用。我想也許是因爲randomvalue和數組中的第j個對象沒有可比性(int爲第一個,第二個爲字符串?)。任何人都可以幫助我嗎?

+1

有關一般解決方案,請參閱http://crypto.stackexchange.com/questions/1379/how-to-generate-a-list-of-unique-random-numbers。 – rossum 2013-02-21 12:56:57

+0

謝謝!我會明白的。 :) – TheInterestedOne 2013-02-21 18:39:35

+0

請注意,你不應該%arc4random()'的結果。它注入了模數偏差。如果你想要一個範圍內的隨機數,使用'arc4random_uniform()'。 – 2013-02-22 18:56:03

回答

2

對不起,戰神的回答幾乎是對的。您可以比較兩個不同的NSNumber對象。

這裏是我的解決方案:

- (int) generateRandomNumber { 
    int number = arc4random() % 100; 

    if ([chosen_numbers indexOfObject:[NSNumber numberWithInt:number]]!=NSNotFound) 
     number = [self generateRandomNumber]; 

    [chosen_numbers addObject:[NSNumber numberWithInt:number]]; 
    return number; 
} 

由於亞歷山德羅有一些麻煩繼承人實現它一個UIViewController類中的例子。本工程爲100個號碼:

#import "ViewController.h" 

@implementation ViewController { 
    NSMutableArray * chosen_numbers;  
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    chosen_numbers = [[NSMutableArray alloc] init]; 

    for(int i = 0; i<90; i++) { 
     NSLog(@"number: %d",[self generateRandomNumber]); 
    } 
} 

- (int) generateRandomNumber { 
    int number = arc4random() % 100; 

    if ([chosen_numbers indexOfObject:[NSNumber numberWithInt:number]]!=NSNotFound) 
     number = [self generateRandomNumber]; 

    [chosen_numbers addObject:[NSNumber numberWithInt:number]]; 
    return number; 
} 

@end 
+0

我該如何調用這個函數並將值號傳遞給randomValue? TY – TheInterestedOne 2013-02-22 19:39:18

+0

randomValue = [self generateRandomNumber]; – Odrakir 2013-02-22 19:47:38

+0

selected_numbers應該是之前初始化的NSMutableArray。 – Odrakir 2013-02-22 19:47:59

1

如何:

-(void) generateRandomNumber { 

     int randomValue = arc4random_uniform(numberofquest) + 1; 

     if([oldQuest indexOfObject:[NSNumber numberWithInt:randomValue] == NSNotFound) { 
      //Unique value 
      [oldQuest addObject:[NSNumber numberWithInt:randomValue]]; 
     } 
     else { 
      //Value already exists. Look for another one 
      return [self generateRandomNumber]; 

     } 
    } 

顯然oldQuest是以前初始化的NSMutableArray實例。

+0

我想你並沒有把新的數字放到數組中。 – Odrakir 2013-02-22 18:54:39

+0

他沒有要求將新數字放入數組中,我假設他想要一個函數返回一個唯一的隨機數。 – Ares 2013-02-22 18:56:22

+0

如果你不把數字放到oldQuest數組中,你怎麼知道新數組是獨一無二的? 無論如何,我不認爲你的解決方案有效,請參閱我的答案。 – Odrakir 2013-02-22 19:00:04

1

你是對的 - 這是行不通的,因爲在這裏:

  if (randomValue==oldquest[j]) 

您要的int與對象進行比較...... NSArrays只能存儲對象。其實這條線應該不是這個原因的工作:

[oldquest addObject: randomValue]; 

您需要框中INT作爲一個NSNumber和存儲陣列中:

NSNumber* boxedRandomValue = [NSNumber numberWithInt:randomValue]; 
[oldquest addObject: boxedRandomValue]; 

然後使用NSNumber的實例方法-(int)intValue拆箱它之前比較值:

if (randomValue==[oldquest[j] intValue]) 

更新

有你將不得不出席一些其他問題:KK的

  • 值是在測試的每個迭代重置爲1,所以kk == 1總是真,else子句永遠不會調用。你只需要在這段代碼之外設置一次(例如你可以將它設置爲一個屬性,在初始化時將它設置爲1,然後在這裏訪問並遞增)。更好的是,只需使用[oldquest count]:if ([oldquest count]==0) {} else {}。然後你可以完全免除你的kk計數器。

  • 你的for循環以j = 1開始。這應該是j = 0來解決數組中的第一個項目(項目0)。

更新2

這條線:randomValue = (arc4random() % numerodomande)+ 1將會導致所有種類的其他問題,是由於它在檢查環的位置。嘗試以下建議之一:

  • 只是return當你遇到一個笨蛋。沒有號碼被添加到陣列...

  • 設置BOOL測試循環內,外對付它:

    BOOL repeatedValue = NO; 
    for (int j=0; j<[self.oldquest count]; j++){ 
        if (randomValue==[self.oldquest[j] intValue]) { 
         repeatedValue = YES; 
         break; 
        } 
    } 
    if (repeatedValue){ 
        NSLog (@"value repeated"); 
        [self addRandom]; 
        //recursive call to this code block, 
        //assuming it is a method called `addRandom` 
    } 
    
  • 嘗試最後建議的壓縮版本(類似Odrakir的解決方案) - 我已將它包含在addRandom方法中,以便您可以看到如何遞歸調用它。

    - (void) addRandom { 
        int numberofquest = 5; 
        int randomValue = (arc4random() % numberofquest)+ 1; 
        NSNumber* boxedValue = [NSNumber numberWithInt:randomValue]; 
        if ([self.oldquest indexOfObject:boxedValue]==NSNotFound) { 
         [self.oldquest addObject: boxedValue]; 
        } else { 
         [self addRandom]; 
        } 
    } 
    

    (如果你這樣做循環,直到你找到了唯一的編號,你將不得不小心,因爲你的號碼的總集是有限限於numberofquest,所以當你有一個完整的一套,你最終可能會與。無限循環)

  • 而不是使用NSMutableArray裏,你可以使用MutableOrderedSet代替 - 這是獨特對象的有序集合,因此不會添加對象的兩倍。

在@interface

@property (nonatomic, strong) NSMutableOrderedSet setOfRandoms; 

在@implementation

int randomValue = (arc4random() % numberofquest)+ 1; 
NSNumber randomValueBoxed = [NSNumber numberWithInt:randomValue]; 
[setOfRandoms addObject:randomValueBoxed]; 

更新3

先前的提示假定它是您感興趣的randoms的列表。下面是一個完整的解決方案,用於在自包含方法中返回一個新的唯一隨機int。

您需要在@interface 設立2個屬性和地方初始化它們:

@property (nonatomic, assign) int maxRand; 
    //stores the highest allowed random number 

@property (nonatomic, strong) NSMutableArray* oldRands; 
    //stores the previously generated numbers 

uniqueRandom返回1和self.maxRand每次之間的唯一的隨機數。如果已經歸還所有允許的數字則返回0

- (int) uniqueRandom { 
    int result = 0; 
    if ([self.oldRands count] != self.maxRand) { 
     int randomValue = (arc4random() % self.maxRand)+ 1; 
     NSNumber* boxedValue = [NSNumber numberWithInt:randomValue]; 
     if ([self.oldRands indexOfObject:boxedValue]==NSNotFound) { 
      [self.oldRands addObject: boxedValue]; 
      result = randomValue; 
     } else { 
      result = [self uniqueRandom]; 
     } 
    } 
    return result; 
} 

您應該考慮,這是沒有意義的改變self.maxRand一旦被初始化,除非你也重self.oldRands。因此,您可能需要使用const#define,並/或將其連接到self.oldRands初始化程序。

+0

我已經嘗試過但它不起作用!問題仍然在重複:( – TheInterestedOne 2013-02-22 19:32:55

+0

@AlessandroBava,你有幾個其他問題,請參閱我的更新回答 – foundry 2013-02-22 20:45:46

+0

謝謝你的幫助!你對kk正確,我已經做了一個屬性。我對第一個索引是1的其他代碼感到困惑。謝謝您注意到這一點。我已經理解了您在第3點中所說的內容,但我不知道如何實現新的隨機值,然後如何檢查它 – TheInterestedOne 2013-02-22 21:19:38