1

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

例如,单词 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];

我在这里做错了什么?我希望乱码中的字母有意义。

请帮忙,我卡在这个上!

谢谢!

4

3 回答 3

2

只要您的字符串长度适合 32 位,这应该没问题。如果没有,我将用arc4random_uniformC++ 中的统一随机数生成器替换并将其编译为 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++ 感到满意,请转换为 a std::wstring,调用std::random_shuffle,然后将其转换为 a NSString。使用经过验证的、经过良好测试的代码时,错误会减少很多。

于 2014-03-11T21:28:42.480 回答
0

当你得到一个随机字母时,你需要做一些事情来从你的 NSMutableArray 中删除那个字母(即按顺序排列的单词的字母)。因此,当您遍历单词时,每次剩余的字符都会减少。现在,从您有限的代码块(第一个)来看,您可能没有这样做。您需要类似 "[_words removeObjectAtIndex:letterIndex]" 的内容,并且您还希望在从数组中删除项目时从字母数迭代到零:for (int i=[_words count]; i > [_words count ]; i--) 因为你需要从 4 个字母减少到 0 个字母。

于 2014-03-11T17:55:14.267 回答
-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;
}
于 2014-03-11T18:06:02.063 回答