随机发生器随机性稍差

时间:2018-09-28 20:53:59

标签: objective-c

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"category == %@", selectedCategory];
NSArray *filteredArray = [self.Quotes filteredArrayUsingPredicate:predicate];
// Get total number in filtered array
int array_tot = (int)[filteredArray count];
// As a safeguard only get quote when the array has rows in it
if (array_tot > 0) {
    // Get random index
    int index = (arc4random() % array_tot);
    // Get the quote string for the index
    NSString *quote = [[filteredArray objectAtIndex:index] valueForKey:@"quote"];
    // Display quote
    self.quote_text.text = quote;
    // Update row to indicate that it has been displayed
    int quote_array_tot = (int)[self.Quotes count];
    NSString *quote1 = [[filteredArray objectAtIndex:index] valueForKey:@"quote"];
    for (int x=0; x < quote_array_tot; x++) {
        NSString *quote2 = [[Quotes objectAtIndex:x] valueForKey:@"quote"];
        if ([quote1 isEqualToString:quote2]) {
            NSMutableDictionary *itemAtIndex = (NSMutableDictionary *)[Quotes objectAtIndex:x];
            [itemAtIndex setValue:@"DONE" forKey:@"source"];
        }
    }

上面是我在应用程序中使用的代码,用于从存储在plist中的两个类别之一(在数组中,第一行是category,第二行是quote)生成随机报价。但是,它似乎倾向于重复已经显示的内容。我希望它有一个偏好设置(但不是排他性地)显示以前没有显示的显示内容。

1 个答案:

答案 0 :(得分:1)

您的问题是算法问题。您想要的是看起来似乎随机但更统一的数字序列。

您要寻找的被称为low-discrepancy sequence。一种简单的形式是“洗牌袋”,通常在游戏开发中使用,如herehere所述。

使用洗牌袋,您基本上会生成所有索引(例如0 1 2 3 4 5),对它们进行洗牌(例如2 3 5 1 0 4),然后按此顺序显示元素。最后,您将生成另一个序列(例如4 1 0 2 3 5)。请注意,同一元素有可能在序列中出现两次,尽管这种情况很少见。例如。在这种情况下,“ 4”是重复的,因为完整序列是2 3 5 1 0 4 4 1 0 2 3 5。

arc4random()在Apple平台上是很好的PRNG,因此它不会给您“低差异序列”。但是:您可以将其用作生成“低差异序列”的原语,也可以将其用作创建随机播放袋实现的原语。