2011-08-12 125 views
7

我有一個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。

回答

7

讓您的數組中的元素是這樣的:

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

即使計數就會減少這種方式,這是確定,因爲你仍然會得到一個有效的下一個位置值,直到沒有任何更多可取值。

+0

但是會不會導致重複? – Snowman

+1

@Mohabitar,如果每次獲得一個,都不會將該對象從數組中移除。 –

+0

不應該是'arc4random()%[myArray count]'給出的數字從0到count-1?否則,最後一個元素將保持最後一個元素,如果count = 1,則會執行'arc4random()%0',這不正確。如果你想從數組中刪除項目,你可以這樣說或發佈代碼。 –

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; 
} 

注意的是,這裏所有的數組和數字自動釋放,但在你的代碼,你可能要小心內存管理。

如果你沒有保持數組中的元素,你可以簡化(見奧斯卡戈麥斯的回答太):

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

最後,洗牌將是空的。你將不得不改變循環條件太:

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

通過「不重複」我想你的意思是你要使用的陣列中的每個字符串,當您再次使用相同字符串之前,不是說你想過濾數組,使其不包含重複的字符串。

下面是一個使用費雪耶茨洗牌功能:

/** @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存儲每組而不是將它們存儲在單獨的數組中。

+0

不知道它被稱爲「Fisher-Yates shuffle」。我一直把它稱爲「隨機排列」。這是一個很好的半隨機算法,可以輕鬆確保您只通過每個項目一次。 – Oli

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"]; 
2

沒有必要鍵入那麼多。要隨機比較數組,你只需要用隨機比較器對其進行排序:

#include <stdlib.h> 

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

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

抱歉疏浚過去,但這是一個壞主意:http://www.cocoawithlove.com/2010/06/sorting-nsmutablearray-with-random.html – warrenm