在开始另一个之前等待方法完成

时间:2011-03-26 13:25:46

标签: iphone objective-c ios cocos2d-iphone

假设我有两个连续的方法,methodAmethodBmethodB末尾调用methodA)我需要完成以下过程:在methodA开始之前methodB

-(void)methodA {

    //do some very heavy computation here
    [self methodB];
}

-(void)methodB {

    //this method performs some animation

}

methodA需要很多处理能力,并且在methodB有动画时需要时间才能完成。动画起初开始时滞,我猜测这与方法A的开销有关。那么我怎样才能让第二种方法在第一种方法完全完成后才开始?


这是实际代码:

代码非常杂乱无序。有很多代码已被注释掉,所以请进一步说明。我有时测试一些东西然后评论它们,以后我需要它们。

这是正在发生的事情:它以(void)checkMoves方法开头。此方法调用两个类似方法之一

-(void)getMovesForJourney:(int)journey withRolls:(NSArray *)rolls

-(void) getEntryMovesForJourney:(int)journey withRolls:(NSArray *)rolls

这些方法是长递归过程的包装器(很可能是多线程发生的地方)。

(void)checkMoves结束时调用另一个方法-(void)analyseMoves。这也是一个繁重的过程。 最后,在-(void)analyseMoves结束时调用动画方法-(void)move:。最后一种方法是以滞后开始的。

最后在-(void)move:结束时,该过程将重新开始,直到不再有“移动”可用。

以下方法不符合要求,请参阅上述说明,了解最新情况。

-(void) checkMoves {

    GameScene *game = [GameScene sharedGameScene];

    CCLOG(@"start");
    for (Stone *stone in stones) {

        if (!stone.onBoard) {

            if ([game EntryAvailable]) {
                [self getEntryMovesForJourney:stone.journey withRolls:[game rollsAsIntegers]];

                }
        }

        else {


            [self getMovesForJourney:stone.journey withRolls:[game rollsAsIntegers]];

        }
    }

    CCLOG(@"finish");

    [self analyseMoves];

}

-(NSMutableArray *) otherPlayerLocations {

    GameScene *game = [GameScene sharedGameScene];
    Board *board = [game board];
    Player *otherPlayer = [game playerOne];
    NSMutableArray *locations = [[[NSMutableArray alloc] init] autorelease];
    for (Stone *stone  in otherPlayer.stones) {

        if (stone.journey < 77) {
            int location;
            if (stone.onBoard)
                location = [[board tileForATag:[self convertJourneyToTileTag:stone.journey]] bTag];
            else
                location = 0;

            [locations addObject:[NSNumber numberWithInt:location]];
        }
    }

    return locations;
}

-(void) analyseMoves {

    if (moves.count > 0) {

        NSMutableArray *killMoves = [[[NSMutableArray alloc] init] autorelease];
        NSMutableArray *safeMoves = [[[NSMutableArray alloc] init] autorelease];

        int mostThreatened;
        float highestThreat = -1.0;
        float lowestThreat = 100.0;
        AIMove *safestMove;

        //get kill and safe moves in seperate arrays
        for (AIMove *move in moves) {

            if (move.moveType == killMoveType)
                [killMoves addObject:move];

            else if (move.moveType == safeMoveType)
                [safeMoves addObject:move];

            // get highest threatened stone

            //if (move.potThreat > highestThreat) {

             //   mostThreatened = move.journey;
             //   highestThreat = move.potThreat;

                if (move.initThreat < lowestThreat) {
                    lowestThreat = move.initThreat;
                    safestMove = [move copy];
                    CCLOG(@"safest move assigned");
                }
            //}
        }

        //MOVE SELECTION:
        //___________________________________

        //choose best kill move
        int killJourney;
        if (killMoves.count > 0) {

            //leave one move in killMoves with highest journey
            killJourney = [[killMoves objectAtIndex:0] tileTag];
            for (AIMove *killMove in killMoves) {
                if (killMove.tileTag < killJourney)
                    [killMoves removeObject:killMove];
                else
                    killJourney = killMove.tileTag;
            }
        }


        //select correct move
        if (killMoves.count > 0) {

            [self move:[killMoves objectAtIndex:0]];
            CCLOG(@"Kill move chosen");
        }

        else {
            CCLOG(@"this is called!!!!");
            CCLOG(@"safest move with initThreat: %i, potThreat: %i",safestMove.journey, safestMove.tileTag);
            [self move:safestMove];
            CCLOG(@"Success");

        }
        /*

        else if (safeMoves.count > 0) {

            [self move:[safeMoves objectAtIndex:0]];
            CCLOG(@"safe move chosen");
        }

        else {

            //temp random move generation
            randomMove = CCRANDOM_0_1()*[moves count];

            AIMove *move = [moves objectAtIndex:randomMove];
            [self move:move];
            CCLOG(@"Random move chosen");
        }
         */

    }
}


-(void) assignThreatLevel:(AIMove *)move {

    NSArray *otherPlayerStones = [self otherPlayerLocations];
    NSMutableArray *initThreats = [[NSMutableArray alloc] init];
    NSMutableArray *potThreats = [[NSMutableArray alloc] initWithCapacity:4];



    for (NSNumber *location in otherPlayerStones) {

        //get threat levels for potential moves
        if (move.tileTag > [location intValue]) {

            int dif = move.tileTag - [location intValue];
            CCLOG(@"dif: %i",dif);
            //threat level conditions:
            // 1 >> 5 =   70% of journey
            // 6 >> 9 =   40% of journey
            // 10 & 11 =  50% of journey
            // 12 >> 24 = 20% of journey
            // 25 && 26 = 50% of journey
            // 27+ =      20% of journey

            if (move.tileTag < 9) {
                [initThreats addObject:[NSNumber numberWithFloat:0.0f]];
            }

            else if (dif >= 1 && dif <= 5) {
                [initThreats addObject:[NSNumber numberWithFloat:k1to5]];


            }

            else if (dif >= 6 && dif <= 9) {
                [initThreats addObject:[NSNumber numberWithFloat:k6to9]];



            }

            else if (dif == 10 || dif == 11) {
                [initThreats addObject:[NSNumber numberWithFloat:k10to11]];



            }

            else if (dif >= 12  && dif <= 24) {
                [initThreats addObject:[NSNumber numberWithFloat:k12to24]];



            }

            else if (dif == 25 || dif == 26) {
                [initThreats addObject:[NSNumber numberWithFloat:k25to26]];



            }

            else if (dif > 26) {
                [initThreats addObject:[NSNumber numberWithFloat:k27plus]];


            }

            //-------------------------------------
        }

        //get Threat levels for current positions
        if (move.tileTag > [location intValue]) {

            int dif = move.tileTag - [location intValue];

            //threat level conditions:
            // 1 >> 5 =   70% of journey
            // 6 >> 9 =   40% of journey
            // 10 & 11 =  50% of journey
            // 12 >> 24 = 20% of journey
            // 25 && 26 = 50% of journey
            // 27+ =      20% of journey

            if (move.journey < 8 || move.journey > 75)
                [potThreats addObject:[NSNumber numberWithFloat:0.0f]];

            else if (dif >= 1 && dif <= 5)
                [potThreats addObject:[NSNumber numberWithFloat:k1to5]];

            else if (dif >= 6 && dif <= 9)
                [potThreats addObject:[NSNumber numberWithFloat:k6to9]];

            else if (dif == 10 || dif == 11)
                [potThreats addObject:[NSNumber numberWithFloat:k10to11]];

            else if (dif >= 12  && dif <= 24)
                [potThreats addObject:[NSNumber numberWithFloat:k12to24]];

            else if (dif == 25 || dif == 26)
                [potThreats addObject:[NSNumber numberWithFloat:k25to26]];

            else if (dif > 26)
                [potThreats addObject:[NSNumber numberWithFloat:k27plus]];

            //-------------------------------------
        }


    }

    float initThreat = 0.0f;
    float potThreat = 0.0f;
    for (NSNumber *number in initThreats) {

        if ([number floatValue] > initThreat) 
            initThreat = [number floatValue];
    }


    for (NSNumber *number in potThreats) {

        if ([number floatValue] > potThreat)
            potThreat = [number floatValue];
    }

    move.initThreat = initThreat;
    move.potThreat = potThreat;
    [initThreats release];

}




-(void) move:(AIMove *)move {

    CCLOG(@"Moves count: %i",[moves count]);
    if ([moves count] > 0) {

        BOOL isOtherStoneOnPreviousTile = NO;

        int total;
        if (move.tileTag > 8)
            total = move.tileTag - move.journey;
        else if (move.tileTag < 9 && move.journey > 8)
            total = ((9-move.tileTag)+75) - move.journey;
        else if (move.tileTag < 9)
            total = move.tileTag - move.journey;
        CCLOG(@"Total: %i",total);

        GameScene *game = [GameScene sharedGameScene];
        Board *board = [game board];
        BoardTile *tile = [[game board] tileForBTag:move.tileTag];
        CCSequence *sequence;
        NSMutableArray *actions = [[[NSMutableArray alloc] init] autorelease];
        id delay = [CCDelayTime actionWithDuration:0.5];
        [actions addObject:delay];

        if (move.journey > 0) {

            for (int i = 1; i < total+1; i++) {
                if (move.journey+i < 76)
                    tile = [board tileForBTag:move.journey+i];
                else 
                    tile = [board tileForBTag:9-((move.journey+i)-75)];
                id moveAction = [CCMoveTo actionWithDuration:0.2 position:tile.position];
                [actions addObject:moveAction];
            }
        }

        else {
            id moveAction = [CCMoveTo actionWithDuration:0.2 position:tile.position];
            [actions addObject:moveAction];
        }


       // id moveFunc = [CCCallFunc actionWithTarget:self selector:@selector(moveMotion)]; 

        //id moveAction = [CCMoveTo actionWithDuration:0.3 position:tile.position];
        id killFunc = [CCCallFuncND actionWithTarget:self selector:@selector(killStonesForTile:data:) data:tile];
        //id callfunc = [CCCallFunc actionWithTarget:self selector:@selector(move)];
        [actions addObject:killFunc];
        //[actions addObject:callfunc];
        sequence = [CCSequence actionMutableArray:actions];
        [actions removeAllObjects];

        CGPoint exitPos = ccp(exitPosition.x-(completeStones*30),exitPosition.y-(completeStones*30));

        id move2 = [CCMoveTo actionWithDuration:0.2f position:exitPos];
        id sequence2 = [CCSequence actions:move2, nil];

        Stone *stone = [self getStoneForJourney:move.journey];

        //-

        //------------------------------------------
        //clean tracks

        for (Stone *stone in stones) {

            if (stone.journey == (move.tileTag - move.journey))
                isOtherStoneOnPreviousTile = YES;
        }

        if (!isOtherStoneOnPreviousTile) {

            BoardTile *prevTile = [board tileForBTag:[self convertJourneyToTileTag:move.journey]];
            prevTile.occupiedBy = 0;
        }

        //===========================================

        //-------------------------------------------
        //set stone status

        if (move.tileTag < 9 && stone.crossedEntry)
            stone.journey = (9 - move.tileTag) + 75;
        else 
            stone.journey = move.tileTag;
        stone.onBoard = YES;
        tile.occupiedBy = player2;

        if (stone.journey > 8 && !stone.crossedEntry)
            stone.crossedEntry = YES;

        //============================================


        if (stone.journey < 84)
            [stone runAction:sequence];

        else {

            [stone runAction:sequence2];
            completeStones++;
            stone.isJourneyComplete = YES;
        }

        CCLOG(@"Stone Journey:%i",stone.journey);
        NSArray *rollTypesArray = [move rollTypes];
        [self removeRollTypes:rollTypesArray];

        [moves removeAllObjects];
        [game updateRollResults];
        [self updateMoveAvailability];

    }

    else {
        GameScene *game = [GameScene sharedGameScene];
        [moves removeAllObjects];
        [game nextTurn];
        [game updateRollResults];

    }




}


-(Stone *)getStoneForJourney:(int)journey {

    Stone *theStone;
    for (Stone *stone in stones) {

        if (stone.journey == journey) 
            theStone = stone;
    }

    return theStone;
}

-(void)dealloc {

    [moves release];
    [rollTypes release];
    [results release];
    [super dealloc];

}


-(void)killStonesForTile:(id)sender data:(BoardTile *)tile {

    GameScene *game = [GameScene sharedGameScene];

    int tileTag;
    Player *otherPlayer;

    if (playerNumber == player1) {
        tileTag = tile.aTag;
        otherPlayer = [game playerTwo];
    }
    else {
        tileTag = tile.bTag;
        otherPlayer = [game playerOne];
    }

    CCArray *currentStones = [otherPlayer stones];

    for (Stone *stone in currentStones) {

        if (!stone.isJourneyComplete) {

            int journey = stone.journey;

            if (tileTag == tile.aTag) {

                if (journey > 0 && [self convertJourneyToTileTag:journey] == tile.bTag) {

                    CCLOG(@"blue stone killed");

                    [self returnStoneToOrigin:stone];

                }

            }

            if (tileTag == tile.bTag) {

                if (journey > 0 && [self convertJourneyToTileTag:journey] == tile.aTag) {

                    CCLOG(@"gold stone killed");

                    [self returnStoneToOrigin:stone];

                }           
            }
        }
    }
}

-(void)removeRollTypes:(NSArray *)theRollTypes {

    GameScene *game = [GameScene sharedGameScene];
    NSMutableArray *rolls = [game rolls];

        for (NSNumber *roll in theRollTypes) {

            NSUInteger index = [rolls indexOfObject:[game convertIntToRoll:roll]];
            CCLOG(@"rolltypes count: %i",[theRollTypes count]);
            CCLOG(@"roll integer: %i",[roll intValue]);
            [rolls removeObjectAtIndex:index];
        }
}

#pragma mark -
#pragma mark enumerations

- (NSArray*)getSums:(NSArray*)numbers {

    NSMutableArray *result = [self getSumsHelper:numbers startingFrom:0];
    [result removeObjectAtIndex:0];
    return result;
}

- (NSMutableArray*)getSumsHelper:(NSArray*)numbers startingFrom:(NSUInteger)index {
    /* (1) */
    if (index >= [numbers count])
        return [NSMutableArray arrayWithObject:[NSNumber numberWithFloat:0]];

    /* (2) Generate all the subsets where the `index`th element is not included */
    NSMutableArray* result = [self getSumsHelper:numbers startingFrom:index+1];

    //  NSSortDescriptor *mySorter = [[NSSortDescriptor alloc] initWithKey:@"floatValue" ascending:YES];
    //  [result sortUsingDescriptors:[NSArray arrayWithObject:mySorter]];
    /* (3) Add all the cases where the `index`th element is included */

    NSUInteger i, n = [result count];

    float element = [[numbers objectAtIndex:index] floatValue];
    for (i = 0; i < n; i++) {
        float element2 = [[result objectAtIndex:i] floatValue];
        float sum = element+element2;
        BOOL numberPresent = NO;
        for (NSNumber *number in result) {
            if ([number floatValue] == sum)
                numberPresent = YES;
        }
        if (!numberPresent)
            [result addObject:[NSNumber numberWithFloat:sum]];

    }
    return result;
}

-(NSArray *) getCombsforNumbers:(NSArray *)numbers withTarget:(int)target{

    NSMutableArray *partial = [[NSMutableArray alloc] init];
    [partial addObject:[NSNumber numberWithInt:0]];
    [results removeAllObjects];
    NSArray *result = [self getCombsHelper:numbers target:target partial:partial];

    NSUInteger minCount = [[result objectAtIndex:0] count];
    NSUInteger index = 0;
    NSMutableArray *combArray = [result objectAtIndex:0];
    for (NSMutableArray *array in result) {

        if ([array count] < minCount) {
            minCount = [array count];
            index = [result indexOfObject:array];
            combArray = array;
        }
    }

    //remove number 0 from array
    [combArray removeObject:[NSNumber numberWithInt:0]];
    return combArray;
}

-(NSMutableArray *) getCombsHelper:(NSArray *)numbers target:(int)target partial:(NSMutableArray *)partial {

    int s = 0;
    for (NSNumber *number in partial) {
        s += [number intValue];
    }

    if (s == target) {

        [results addObject:partial];


    }

    if (s >= target) {

        return results;
    }

    for (int i = 0; i < [numbers count]; i++) {

        NSMutableArray *remaining = [[[NSMutableArray alloc] init] autorelease];
        int n = [[numbers objectAtIndex:i] intValue];
        for (int j = i+1; j<[numbers count]; j++) {
            [remaining addObject:[numbers objectAtIndex:j]];
        }

        NSMutableArray *partialRec = [[[NSMutableArray alloc] init] autorelease];
        [partialRec addObjectsFromArray:partial];

        [partialRec addObject:[NSNumber numberWithInt:n]];

        [self getCombsHelper:remaining target:target partial:partialRec];
    }

    return results;

}


-(void) getMovesForJourney:(int)journey withRolls:(NSArray *)rolls {

    GameScene *game = [GameScene sharedGameScene];
    Board *board = [game board];

    NSArray *sums = [self getSums:rolls];
    for (NSNumber *number in sums) {

        if ([number intValue]+journey <= 84) {

            BoardTile *tile = [board tileForBTag:[self convertJourneyToTileTag:journey+[number intValue]]];
            if (tile.isSafeTile) {
                if (tile.occupiedBy != player1) {
                    AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
                    NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];

                    //Checking rolltypes, remove later
                    NSLog(@"%i = ",[number intValue]);
                    for (NSNumber *comb in theRollTypes) {
                        NSLog(@"%i",[comb intValue]);
                    }
                    NSLog(@"-----------");
                    //----------------------------------
                    move.moveType = safeMoveType;
                    move.initThreat = 0.0;

                    CCLOG(@"move initThreat: %f",move.initThreat);


                    [move setRollTypes:theRollTypes];
                    [moves addObject:move];

                }
            }
            else {
                AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
                NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];

                //Checking rolltypes, remove later
                NSLog(@"%i = ",[number intValue]);
                for (NSNumber *comb in theRollTypes) {
                    NSLog(@"%i",[comb intValue]);
                }
                NSLog(@"-----------");
                //-----------------------------------

                [move setRollTypes:theRollTypes];


                //assing threat level
                [self assignThreatLevel:move];

                CCLOG(@"move initThreat: %f",move.initThreat);



                //check for kill move
                NSArray *otherPlayerPositions = (NSArray *)[self otherPlayerLocations];
                for (NSNumber *location in otherPlayerPositions) {

                    if (move.tileTag == [location intValue])
                        move.moveType = killMoveType;

                }

                [moves addObject:move];
            }
        }
        //int i = [number intValue];
        //NSArray *combs = [self getCombsforNumbers:numbers withTarget:i];

    }
}


-(void) getEntryMovesForJourney:(int)journey withRolls:(NSArray *)rolls {

    GameScene *game = [GameScene sharedGameScene];
    Board *board = [game board];

    NSArray *sums = [self getSums:rolls];
    for (NSNumber *number in sums) {

        if ([number intValue]+journey <= 84) {

            BoardTile *tile = [board tileForBTag:[self convertJourneyToTileTag:journey+[number intValue]]];
            if (tile.isSafeTile) {
                if (tile.occupiedBy != player1) {
                    NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];


                    BOOL containsEntry = NO;
                    for (NSNumber *rollType in theRollTypes) {
                        if ([rollType intValue] == 1) {
                            containsEntry = YES;
                        }
                    }

                    if (containsEntry) {

                        AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];

                        //Checking rolltypes, remove later
                        NSLog(@"%i = ",[number intValue]);
                        for (NSNumber *comb in theRollTypes) {
                            NSLog(@"%i",[comb intValue]);
                        }
                        NSLog(@"-----------");

                        move.moveType = safeMoveType;

                        move.initThreat = 0.0;

                        CCLOG(@"move initThreat: %f",move.initThreat);


                        [move setRollTypes:theRollTypes];
                        [moves addObject:move];
                        //----------------------------------
                    }
                }
            }
            else {
                NSArray *theRollTypes = [[self getCombsforNumbers:rolls withTarget:[number intValue]] copy];
                BOOL containsEntry = NO;
                for (NSNumber *rollType in theRollTypes) {
                    if ([rollType intValue] == 1) {
                        containsEntry = YES;
                    }
                }

                if (containsEntry) {

                    AIMove *move = [AIMove moveWithJourney:journey tileTag:tile.bTag];
                    [move setRollTypes:theRollTypes];

                    //check for kill move
                    NSArray *otherPlayerPositions = (NSArray *)[self otherPlayerLocations];
                    for (NSNumber *location in otherPlayerPositions) {

                        if (move.tileTag == [location intValue])
                            move.moveType = killMoveType;

                    }

                    //assing threat level
                    [self assignThreatLevel:move];

                    [moves addObject:move];


                    //Checking rolltypes, remove later
                    NSLog(@"%i = ",[number intValue]);
                    for (NSNumber *comb in theRollTypes) {
                        NSLog(@"%i",[comb intValue]);
                    }
                    NSLog(@"-----------");

                    CCLOG(@"move initThreat: %f",move.initThreat);

                    [move setRollTypes:theRollTypes];
                    [moves addObject:move];
                    //----------------------------------
                }
            }
        }

    }
}

1 个答案:

答案 0 :(得分:0)

从技术上讲,在methodB完成后调用methodA。在methodA中,您显然正在执行后台操作,这意味着该方法完成,而某些任务在另一个线程上执行(或在runloop上调度)。除非你分享methodA的内部运作方式,否则我们无法对此说些什么。