0

我一直在构建一个带有随机脚本遭遇的核心图形的更简单的游戏,如果这有意义的话,它开始成为视图控制器中的一个巨大方法。

-(void)spawnStuff{
CGPoint position;
CGPoint position1;

int chance = random()%10;
switch (chance) {
    case 0:
            [self spawnWall];
        Position.y = 580;
        Position.x = 160;
        wall.center = Position;

        [self spawnWall];
        Position1.y = 480;
        Position1.x = 80;
        wall.center = Position1;

}
-(void)spawnWall{
UIImage* myImage = [UIImage imageNamed:@"Wall.png"];
Wall = [[Sprite alloc] initWithImage:myImage];

CGRect rect = CGRectMake(0, 0, 90, 50);
more initilization stuff }

我可能会重复这行代码 20 - 30 不同的位置,这些墙的位置只有 10 种不同的场景,它大约是类中代码的 3rd,它开始变得有点重复我对编程还是很陌生巨大的方法有点吓到我。这是处理这个问题的正确方法吗?

4

1 回答 1

0

如果你经常做这种事情,我建议保留一系列可能的操作,然后在必要时随机选择一个。类似以下内容应该向您展示如何做到这一点。

请注意,您可以随意从数组中添加/减去,这会改变可用的块......这只是在底部显示随机选择并执行一个块 100 次。

您可以在代码中的适当位置添加/删除块以将其保留在本地。这至少应该让你开始......

// If we want to perform some action randomly, then we build an array
// of possibly actions (blocks), and then randomly pick one and execute it.
// Figure out what type of block you want...

typedef void(^ActionBlock)(void);
NSMutableArray *possibleActions = [NSMutableArray array];
[possibleActions addObject:^{
    NSLog(@"Doing Action Foo");
}];
[possibleActions addObject:^{
    NSLog(@"Doing Action Bar");
}];
[possibleActions addObject:^{
    NSLog(@"Doing Action Baz");
}];
[possibleActions addObject:^{
    NSLog(@"Doing Action FooBar");
}];
[possibleActions addObject:^{
    NSLog(@"Doing Action Blarg");
}];
[possibleActions addObject:^{
    NSLog(@"Doing Action Zip");
}];

// Now, when I want to pick an action to perform...
for (int i = 0; i < 100; ++i) {
    ActionBlock block = [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)];
    block();
}

编辑 该行

typedef void(^ActionBlock)(void);

是一个 typedef,并为特定类型的块定义类型。当然,函数和块的语法有点难读。也许我应该退后一步。我希望它不会冒犯你,如果它以任何方式光顾,请提前道歉。它类似于

typedef int IntType;
typedef void const * OpaqueType;

这更容易阅读。第一个定义了整数类型的类型 IntType,第二个定义了类型为“pointer-to-const-void”的类型 OpaqueType。然后,您可以声明变量,例如...

IntType someInteger;
OpaqueType someOpaqueValue;

现在,在基本 C 语言中,我们还可以声明函数指针。假设我们有一些功能......

int functionOne(int arg1, double arg2) {
    // do whatever...
}
int functionTwo(int arg1, double arg2) {
    // do whatever...
}

你可以很容易地调用那个函数......

int result = functionOne(42, 3.14159);

好吧,您还可以创建一个指向该函数的变量,并且可以像调用任何其他函数一样调用它。

int(*function)(int,double) = functionOne;
int result = function(42, 3.14159); // Calls functionOne
function = functionTwo;
result = function(42, 3.14159); // calls functionTwo

但是,这种语法输入起来有点乏味。因此,特别是对于函数和块,我们创建了 typedef。为函数创建 typedef 与创建函数指针变量相同,但只需将类型放在变量名的位置。所以...

typedef int(*MyFunction)(int, double);

声明一个类型,该类型表示一个指向函数的指针,该函数返回一个 int,并接受两个参数,一个 int 和一个 double。

现在,块的语法就像函数指针一样,除了用 ^ 换*。所以,输出类型...

typedef void(^ActionBlock)(void);

表示 ActionBlock 是一种表示返回 void 且不带参数的块的类型。

因此,您可以声明 ActionBlock 类型的变量,并将它们分配给具有 void 返回且没有参数的块。在示例中,这正是我所做的。

请注意,在代码中,我们创建了一堆这样的块......

[possibleActions addObject:^{
    NSLog(@"Doing Action Foo");
}];

编译器允许你省略明显的东西,所以代码真的说......创建一个不带参数的块,并且返回类型为 void,然后将其放入添加到集合中。

我们多次这样做,然后,当准备好调用函数时,我们只需遍历集合。但是,编译器想知道如何调用函数/块,它从集合中得到的只是一个 . 所以,我们想将我们得到的对象转换为一个类型,告诉编译器它是一个返回 void 的块,并且不接受任何参数。

当我们这样做时,我们就可以调用函数/块。所以,让我们再看一遍最后一段(有一些评论),稍微不那么紧凑

for (int i = 0; i < 100; ++i) {
    // We have a bunch of blocks stored in the array.
    // We want to pick one at random, so we will get a random number
    // between [0, size of our array).
    uint32_t index = arc4random_uniform(possibleActions.count);

    // Now, we have a random index into our array.  Get the object in that position.
    id randomObject = [possibleActions objectAtIndex:index];

    // We have an opaque id type, but we know it's a block.  Cast it to a block type.
    ActionBlock block = randomObject;

    // Now, we have our block, in a type that the compiler will let us invoke.
    // Call it like any other function.
    block();
}

编辑

好的,给你。创建一个 iVar,NSTimer *_timer。在 didLoad 中调度,在 didUnload 和 dealloc 中使其失效

- (void)dealloc {
    [_timer invalidate];
}

typedef void(^ActionBlock)(void);

- (void)callRandomFunction:(NSTimer*)timer {
    // Our userInfo is actually our array of blocks
    NSArray *actions = timer.userInfo;
    ActionBlock block = [actions objectAtIndex:arc4random_uniform(actions.count)];
    block();
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *possibleActions = [NSMutableArray array];

    // Create the list of possible functions that can be called...

    // Now setup a timer that performs callRandomFunction: every second
    // Pass the array of blocks as the userInfo of the timer.
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(callRandomFunction:) userInfo:possibleActions repeats:YES];

    // Whatever else you need in here...
}

- (void)viewDidUnload
{
    [_timer invalidate];

    // Any other unload stuff...

    [super viewDidUnload];
}
于 2012-07-29T22:08:45.163 回答