【问题标题】:Mutable Arrays in Objective-C. How to change/manipulate array elements?Objective-C 中的可变数组。如何更改/操作数组元素?
【发布时间】:2012-09-25 14:29:55
【问题描述】:

我正在尝试构建一个包含 400 个整数的数组(在 20 x 20 矩阵的上下文中处理)。所有元素都初始化为 0,然后随机选择 40 个点为整数 9(在扫雷上下文中指定为地雷)。由于某种原因,我的程序挂了:

[map replaceObjectAtIndex: mine_placement withObject:[NSNumber numberWithInt:9]];

在此之后,我有一个例程来累积每个元素的地雷接近度,最后的位创建字符串对象以发送到控制台(日志)。我很想听 Objective-C 专业人士说我做错了什么,以及为什么输出不正确。它构建得很好,只是没有输出。我收到一些关于线程正在启​​动的消息。我是 Obj-C 的新手,所以对此事的任何想法都会很棒。

这是 main 里面的内容:

@autoreleasepool
{

    int number_of_mines = 40;
    int mine_placement;

    // create map of 400 char elements
    NSMutableArray* map = [[NSMutableArray alloc] init];

    // char map[400];
    // build array with zeros everywhere
    for(int i = 0; i < 400; i++)
        [map addObject:[NSNumber numberWithInt:0]];

    // add randomly placed mines

    for(int i = 0; i < number_of_mines; i++) // loop for 40 mines
    {
        mine_placement = arc4random() % 400;
        while([map objectAtIndex: mine_placement] == [NSNumber numberWithInt:9]) // if we are already on a mine, repeat
            {
                mine_placement = arc4random() % 400;
            }
        [map replaceObjectAtIndex: mine_placement withObject:[NSNumber numberWithInt:9]];
    }

    // proximity accumulator (an iterative approach)
    for(int i = 0; i < 400; i++)
    {
        if([map objectAtIndex: i] != [NSNumber numberWithInt:9])
        {
            int accumulator = 0;

            // check top three neighbors
            if(i >= 20) // past first row
            {
                if(i % 20 != 0) // past first column
                    if([map objectAtIndex: (i-21)] == [NSNumber numberWithInt:9]) // top-left
                        accumulator++;

                if((i+1) % 20 != 0) // before last column
                    if([map objectAtIndex: (i-19)] == [NSNumber numberWithInt:9]) //top-right
                            accumulator++;

                if([map objectAtIndex: (i-20)] == [NSNumber numberWithInt:9]) // top
                    accumulator++;
            }

            // check bottom three neighbors
            if(i < 380) // before last row
            {
                if(i % 20 != 0) // past first column
                    if([map objectAtIndex: (i+19)] == [NSNumber numberWithInt:9]) // bottom-left
                        accumulator++;

                if((i+1) % 20 != 0) // before last column
                    if([map objectAtIndex: (i+21)] == [NSNumber numberWithInt:9]) // bottom-right
                            accumulator++;

                if([map objectAtIndex: (i+20)] == [NSNumber numberWithInt:9]) // bottom
                    accumulator++;
            }

            // left neighbor
            if(i % 20 != 0) // past first column
                if([map objectAtIndex: (i-1)] == [NSNumber numberWithInt:9]) // left
                    accumulator++;

            // right neighbor
            if((i+1) % 20 != 0) // before last column
                if([map objectAtIndex: (i+1)] == [NSNumber numberWithInt:9]) // right
                    accumulator++;

            if(accumulator > 0)
                [[map objectAtIndex: i] replaceObjectAtIndex: i withObject:[NSNumber numberWithInt:accumulator]];
        }
    }


    // output map of 400 char elements
    // build string rows

    NSMutableString* string_row = [[NSMutableString alloc] init];
    for(int row = 0; row < 20; row++)
    {
        for(int s = 0; s < 20; s++)
        {
            [string_row insertString:[map objectAtIndex: s] atIndex:s];
        }
        NSLog(@"%@", string_row);
        [string_row setString:@""]; // clear string_row for next row pass
    }
}

【问题讨论】:

    标签: objective-c arrays minesweeper


    【解决方案1】:

    您的程序可能会挂起

    while([map objectAtIndex: mine_placement] == [NSNumber numberWithInt:9])
    

    您在此处比较指针(地址),但您想比较值。试试这个:

    while ([[map objectAtIndex:mine_placement] isEqualTo:[NSNumber numberWithInt:9]])
    

    顺便说一句,如果您使用的是 Xcode 4.5,现在您可以使用 @9 而不是 [NSNumber numberWithInt:9]。如果您使用 iOS 6 SDK 进行编译,您也可以使用 map[mine_placement],因此它应该会缩短您的代码。

    【讨论】:

    • 和地图[i] = @9;而不是 [map replaceObjectAtIndex:] :) --- 我不认为 == [NSNumber numberWithInt:9] 是问题所在,因为直到 13(?)左右的所有 NSNumbers 都返回相同的指针(缓存的单例)。
    • 我不知道这些缓存单例,但安全总比抱歉...[map[i] isEqualTo:@9] 足够短。
    • 我同意你的观点,指望缓存行为不仅仅是糟糕的编码。
    【解决方案2】:

    你的程序也挂了:

    [[map objectAtIndex: i] replaceObjectAtIndex: i withObject:[NSNumber numberWithInt:accumulator]];
    

    因为[map objectAtIndex: i]是NSNumber,它没有replaceObjectAtIndex方法。您可能应该检查阵列的逻辑。这就是问题所在。

    【讨论】:

      【解决方案3】:

      我将您的代码放入了测试应用程序的 applicationDidFinishLaunching 方法中,但在您所说的地方我没有遇到任何问题——我不知道为什么它在那里的行为与在 main 中的行为不同。我确实在这一行遇到了错误:

      [[map objectAtIndex: i] replaceObjectAtIndex: i withObject:[NSNumber numberWithInt:accumulator]];
      

      我想你希望这样:

      [map replaceObjectAtIndex: i withObject:[NSNumber numberWithInt:accumulator]];
      

      您创建可变字符串的代码的最后一部分也不起作用,因为您试图将 NSNumber 插入字符串。可以这样解决:

      [string_row insertString:[NSString stringWithFormat:@"%@",[map objectAtIndex: s]] atIndex:s];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多