如何从NSString中正确随机化字母

时间:2014-03-11 17:38:54

标签: ios objective-c random nsstring scramble

我正在创建一个单词扰码器,我有问题随机化字母。当这些字母随机化时,它没有意义。

例如,PARK这个词显示为AAPA。所以,正如你可以告诉它的那样,当用户解读时,它对用户没有意义。

您知道,我正在使用.plist文件来保存这些文字。

这是我用来随机化字母的代码:

    _words = [NSMutableArray arrayWithCapacity:scramblelength];

    for (int i=0;i<scramblelength;i++) { 

    NSString *letter = [scramble substringWithRange:[scramble rangeOfComposedCharacterSequenceAtIndex:arc4random()%[scramble length]]];

然后,我正在创建UIImageViews来显示乱码:

    if (![letter isEqualToString:@""]) {
        GameView *boxes = [[GameView alloc] initWithLetter:letter andSideLength:boxSide];
        boxes.center = CGPointMake(xOffset + i*(boxSide + kTileMargin), kScreenHeight/4*3);

        [self.scrambleView addSubview:boxes];
        [_words addObject:boxes];

我在这里做错了什么?我希望拼写单词中的字母有意义。

请帮助,我被困在这个!

谢谢!

3 个答案:

答案 0 :(得分:2)

只要您的字符串长度适合32位,这应该没问题。如果没有,我会用C ++中的统一随机数生成器替换arc4random_uniform,并将其编译为Objective-C ++模块。

代码只是遍历字符串,并使用来自同一字符串的一些随机组合字符序列交换每个组合字符序列。

很抱歉,当你傲慢并只输入代码时会发生这种情况。如果你对这个问题有疑问,请告诉我......

对于更大的字符串,有一种更有效的方法,但这似乎可以解决问题。

NSMutableString类别......

@interface NSMutableString (Scramble)
- (void)scramble;
@end

@implementation NSMutableString (Scramble)
static void
swapRanges(NSMutableString *string, NSRange iRange, NSRange jRange)
{
    // Need to replace the "trailing" component first
    if (NSEqualRanges(iRange, jRange)) return;
    if (iRange.location > jRange.location) {
        NSRange tmpRange = iRange;
        iRange = jRange;
        jRange = tmpRange;
    }
    NSString *iString = [self substringWithRange:iRange];
    NSString *jString = [self substringWithRange:jRange];
    [string replaceCharactersInRange:jRange withString:iString];
    [string replaceCharactersInRange:iRange withString:jString];
}

- (void)scramble
{
    for (NSUInteger i = 0; i < self.length; ++i) {
        NSRange iRange = [self rangeOfComposedCharacterSequenceAtIndex:i];
        NSUInteger j = arc4random_uniform(self.length);
        NSRange jRange = [self rangeOfComposedCharacterSequenceAtIndex:j];
        swapRanges(self, iRange, jRange);
    }
}
@end

NSString类别......

@interface NSString (Scramble)
- (NSString*)scrambledString;
@end
@implementation NSString (Scramble)
- (NSString *)scrambledString
{
    NSMutableString *result = [self mutableCopy];
    [result scramble];
    return [result copy];
}
@end

样品使用......

[someMutableString scramble];

NSString *mixedUp = [someString scrambledString];

或者,如果您对C ++感到满意,请转换为std::wstring,请致电std::random_shuffle,然后将其转换为NSString。使用久经考验的经过验证的代码可以减少错误。

答案 1 :(得分:0)

当你收到一封随机字母时,你需要做一些事情从你的NSMutableArray中删除那个字母(即按顺序时单词的字母)。因此,当您遍历单词时,每次剩余的字符较少。现在,从您有限的代码块(第一个)开始,您可能不会这样做。你想要像“[_words removeObjectAtIndex:letterIndex]”这样的东西,你也想要从数字中删除数字,同时从数组中删除项目:for(int i = [_ words count]; i&gt; [_words计数]; i--)因为你需要从4个字母到0个字母。

答案 2 :(得分:-1)

所以,我确信有更有效的方法可以做到这一点,但我会遵循不优化的规则,直到你需要为止。考虑到这一点,此代码似乎正常工作:

- (NSString *)scrambleWord:(NSString *)word {
    NSMutableArray *letterArray     = [self letterArrayFromWord:word];
    NSMutableString *returnValue    = [[NSMutableString alloc] init];
    do {
        int randomIndex = arc4random() % letterArray.count;
        [returnValue appendString:letterArray[randomIndex]];
        [letterArray removeObjectAtIndex:randomIndex];
        if (letterArray.count == 1) {
            [returnValue appendString:letterArray[0]];
            break;
        }
    } while (YES);
    if ([[returnValue copy] isEqualToString:word]) {
        return [self scrambleWord:word];

    } else {
        return [returnValue copy];

    }
}
- (NSMutableArray *)letterArrayFromWord:(NSString *)word {
    NSMutableArray *array = [NSMutableArray array];
    for (int i = 0; i < word.length; i = i + 1) {
        [array addObject:[NSString stringWithFormat:@"%C", [word characterAtIndex:i]]];
    }
    return array;
}