从数组中读取随机值

时间:2011-08-12 22:43:13

标签: objective-c random

我有一个包含14个字符串的数组。我想向用户显示这14个字符串中的每一个而不重复。我得到的最接近的是创建一个整数数组并对它们的值进行混洗,然后使用int数组中的一个数字作为索引从字符串数组中读取:

    //appDelegate.randomRiddles is an array of integers that has integer values randomly
     appDelegate.randomRiddlesCounter++;
     NSNumber *index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
     int i = [index intValue];
     while(i>[appDelegate.currentRiddlesContent count]){
        appDelegate.randomRiddlesCounter++;
        index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
        i = [index intValue];
                    }
hintText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:@"hint"];
questionText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:@"question"];

但我的方式导致崩溃和重复。哦,每次我从字符串数组中读取一个值时,该字符串将从数组中删除,使其计数减少1.这样会使这一点复杂化。

5 个答案:

答案 0 :(得分:7)

获取数组中的元素:

int position = arc4random() % ([myArray count]);

这样即使count减1,也没关系,因为你仍然会得到一个有效的下一个位置值,直到没有更多的可能值。

答案 1 :(得分:4)

通过“没有重复”我假设你的意思是你想在再次使用相同的字符串之前使用数组中的每个字符串,而不是你想要过滤数组,因此它不包含重复的字符串。

这是一个使用Fisher-Yates shuffle的函数:

/** @brief Takes an array and produces a shuffled array.
 *
 *  The new array will contain retained references to 
 *  the objects in the original array
 *
 *  @param original The array containing the objects to shuffle.
 *  @return A new, autoreleased array with all of the objects of 
 *          the original array but in a random order.
 */
NSArray *shuffledArrayFromArray(NSArray *original) {
    NSMutableArray *shuffled = [NSMutableArray array];
    NSUInteger count = [original count];
    if (count > 0) {
        [shuffled addObject:[original objectAtIndex:0]];

        NSUInteger j;
        for (NSUInteger i = 1; i < count; ++i) {
            j = arc4random() % i; // simple but may have a modulo bias
            [shuffled addObject:[shuffled objectAtIndex:j]];
            [shuffled replaceObjectAtIndex:j 
                                withObject:[original objectAtIndex:i]];
        }
    }

    return shuffled; // still autoreleased
}

如果你想保持谜语,提示和问题之间的关系,那么我建议使用NSDictionary来存储每组相关字符串,而不是将它们存储在单独的数组中。

答案 2 :(得分:2)

使用NSMutableArray可以轻松完成此任务。为此,只需从数组中删除一个随机元素,将其显示给用户。

将可变数组声明为实例变量

NSMutableArray * questions;

当应用启动时,使用myArray

中的值填充
questions = [[NSMutableArray alloc] initWithArray:myArray]];

然后,要从数组中获取随机元素并将其删除,请执行以下操作:

int randomIndex = (arc4random() % [questions count]);
NSDictionary * anObj = [[[questions objectAtIndex:randomIndex] retain] autorelease];
[questions removeObjectAtIndex:randomIndex];
// do something with element
hintText.text = [anObj objectForKey:@"hint"];
questionText.text = [anObj objectForKey:@"question"];

答案 3 :(得分:2)

无需打字那么多。要对数组进行洗牌,只需使用随机比较器对其进行排序:

#include <stdlib.h>

NSInteger shuffleCmp(id a, id b, void* c)
{
    return (arc4random() & 1) ? NSOrderedAscending : NSOrderedDescending;
}

NSArray* shuffled = [original sortedArrayUsingFunction:shuffleCmp context:0];

答案 4 :(得分:1)

您可以将数组复制到NSMutableArray中并随机播放。一个简单的演示如何改组数组:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Original array, here initialised with 1..9
    NSArray *arr = [NSArray arrayWithObjects: 
                    [NSNumber numberWithInt: 1],
                    [NSNumber numberWithInt: 2],
                    [NSNumber numberWithInt: 3],
                    [NSNumber numberWithInt: 4],
                    [NSNumber numberWithInt: 5],
                    [NSNumber numberWithInt: 6],
                    [NSNumber numberWithInt: 7],
                    [NSNumber numberWithInt: 8],
                    [NSNumber numberWithInt: 9],
                    nil];

    // Array that will be shuffled
    NSMutableArray *shuffled = [NSMutableArray arrayWithArray: arr];

    // Shuffle array
    for (NSUInteger i = shuffled.count - 1; i > 0; i--) 
    {
        NSUInteger index = rand() % i;
        NSNumber *temp = [shuffled objectAtIndex: index];
        [shuffled removeObjectAtIndex: index];
        NSNumber *top = [shuffled lastObject];
        [shuffled removeLastObject];
        [shuffled insertObject: top atIndex: index];
        [shuffled addObject: temp];
    }

    // Display shuffled array
    for (NSNumber *num in shuffled)
    {
        NSLog(@"%@", num);
    }

    [pool drain];
    return 0;
}

请注意,此处的所有数组和数字都是自动释放的,但在您的代码中,您可能需要处理内存管理。

如果您不必将元素保留在数组中,您可以简化它(请参阅Oscar Gomez的回答):

        NSUInteger index = rand() % shuffled.count;
        NSLog(@"%@", [shuffled objectAtIndex: index]);
        [shuffled removeObjectAtIndex: index];

最后,洗牌将是空的。您还必须更改循环条件:

    for (NSUInteger i = 0; i < shuffled.count; i++)