假设我有两个连续的方法,methodA
和methodB
(methodB
末尾调用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];
//----------------------------------
}
}
}
}
}
答案 0 :(得分:0)
从技术上讲,在methodB
完成后调用methodA
。在methodA
中,您显然正在执行后台操作,这意味着该方法完成,而某些任务在另一个线程上执行(或在runloop上调度)。除非你分享methodA
的内部运作方式,否则我们无法对此说些什么。