计算每个可能的数字组合

时间:2013-04-13 17:24:09

标签: objective-c

我有9个标有1-9的图块,带有相应的值。图块1 = 1,图块6 = 6等。用户可以按下等于骰子总和的图块。当他们按下确认移动时,这些故事就不能再使用了。

我需要计算每种可能的数字组合,以检查用户是否可以再次使用。目前我正在计算它,但我确信必须有更好的方法。 allTiles包含仍可用于计算的切片。

检查所有组合的最佳方法是什么?

- (void) getCombinations {

NSMutableArray *combinations = [[NSMutableArray alloc] init];

for (int i = 0; i < [allTiles count]; i++) {
    for (int j = i + 1; j < [allTiles count]; j++) {
        for (int k = i+2; k < [allTiles count]; k++) {
            TileView *first = [allTiles objectAtIndex:i];
            TileView *second = [allTiles objectAtIndex:j];
            TileView *third = [allTiles objectAtIndex:k];
            NSNumber *total = [NSNumber numberWithInt:first.getTileValue + second.getTileValue];
            NSNumber *total2 = [NSNumber numberWithInt:
                                first.getTileValue +
                                second.getTileValue +
                                third.getTileValue];
            [combinations addObject:[NSNumber numberWithInt:first.getTileValue]];
            [combinations addObject:[NSNumber numberWithInt:second.getTileValue]];
            [combinations addObject:[NSNumber numberWithInt:third.getTileValue]];
            [combinations addObject:total];
            [combinations addObject:total2];
        }
    }
}
if ([combinations containsObject:[NSNumber numberWithInt:[self diceTotal]]]) {
    NSLog(@"STILL COMBINATION AVAILABLE");
}
else {
    NSString *message = [NSString stringWithFormat:@"Your score: %i", player1Score];
    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@"No more combinations left."
                          message: message
                          delegate:self
                          cancelButtonTitle:@"Go to player2"
                          otherButtonTitles: nil];
    [alert show];
    [alert release];
}
} 

以下是我的方法不起作用的方案之一的屏幕截图。 enter image description here

1 个答案:

答案 0 :(得分:4)

在您的示例中,播放器有四个可用的磁贴。是否包括瓦片是二元选择(是或否),并且在该示例中有4个这样的选择,因此存在2×2×2×2 = 2 4 可能的组合瓷砖。一般来说,有2个 n 组合,其中有 n 个瓷砖。

检查与目标相加的组合的最简单方法是枚举0到2 n 中的整数。对于每个整数 i ,用二进制写 i 并将与二进制表示的1对应的图块的图块值相加。

我们会将切片值缓存在本地数组中,以避免反复发送tileValue消息。

static int selectedNumbersSum(unsigned int selector, int const *numbers) {
    int sum = 0;
    for (int i = 0; selector != 0; i += 1, selector >>= 1) {
        if (selector & 1) {
            sum += numbers[i];
        }
    }
    return sum;
}

static BOOL tilesCanMakeTarget(NSArray *tiles, int target) {
    NSUInteger count = tiles.count;
    int numbers[count];
    for (int i = 0; i < count; ++i) {
        numbers[i] = [tiles[i] tileValue];
    }

    for (unsigned int step = 0, maxStep = 1 << count; step < maxStep; ++step) {
        if (selectedNumbersSum(step, numbers) == target)
            return YES;
    }
    return NO;
}

- (void)checkForEndOfPlayer1Turn {
    if (tilesCanMakeTarget(allTiles, self.diceTotal)) {
        NSLog(@"STILL COMBINATION AVAILABLE");
    } else {
        NSString *message = [NSString stringWithFormat:@"Your score: %i",
            player1Score];
        UIAlertView *alert = [[UIAlertView alloc]
            initWithTitle:@"No more combinations left."
            message:message delegate:self cancelButtonTitle:@"Go to player 2"
            otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

顺便说一下,我们通常不会使用get启动我们的getter方法名称。您的getCombinations方法应该被称为checkCombinations(或类似的东西),因为它甚至不是一个吸气剂。您的getTileValue方法应该被称为tileValue