0

抱歉,标题有点笼统,如果有人有更好的建议,请告诉我。

基本上我正在编写一个自定义排行榜视图,我只想显示 3 个分数。如果可能,它将在中间显示当前用户的分数,但如果用户位于列表的顶部或底部,它仍应显示 3 个分数,但它会在列表上方或下方显示其他用户。

例如

  1. 我(如果我名列前茅,请在下面显示 2)
  2. 用户 1
  3. 用户 2

或者

  1. 用户 1
  2. 我(通常情况下我处于两个分数的中间)
  3. 用户 2

或者

  1. 用户 1
  2. 用户 2
  3. 我(如果我垫底,显示比我高两个分数)

我编写了一个函数来完成第一部分,但没有考虑到我正在努力解决的边缘情况。有人可以请教吗?

-(void)getNearbyScores:(int)score{
    GCLeaderboardScore *closestScoreAbove = nil; //Custom container for GC properties
    GCLeaderboardScore *closestScoreBelow = nil; //Contains playerID, score, alias etc

    if ([playerScores count] == 0){ //playerScores is an NSMutableDictionary
        return;
    }

    for (NSString* key in playerScores) {

        GCLeaderboardScore *playerScore = (GCLeaderboardScore *)[playerScores objectForKey:key];
        if ((closestScoreAbove == nil || closestScoreAbove->score > playerScore->score)  && playerScore->score > score){
            closestScoreAbove = playerScore;
        }
        else if ((closestScoreBelow == nil || closestScoreAbove->score < playerScore->score) && playerScore->score < score){
            closestScoreBelow = playerScore;
        }
    }

    me->score = score;
    me->rank = 1;
    if (closestScoreAbove != nil) {
        me->rank = closestScoreAbove->rank + 1;
        nearbyScores = [NSMutableArray arrayWithObjects: closestScoreAbove, me, closestScoreBelow, nil];
    }
    else {
        nearbyScores = [NSMutableArray arrayWithObjects: me, closestScoreBelow, nil];
    }
}
4

2 回答 2

1

假设有一个me GCLeaderboardScore对象,下面的方法应该返回一个包含所需GCLeaderboardScore对象的数组(未经测试):

-(NSArray *)getNearbyScores {

    if(playerScores.count==0) return nil;

    // Create an array sorted by score
    NSArray *sortedByScore=[playerScores sortedArrayUsingComparator: ^(id object1, id object2) {
        GCLeaderboardScore  *score1=object1;
        GCLeaderboardScore  *score2=object2;

        if(score1->score < score2->score) return NSOrderedAscending;
        if(score1->score > score2->score) return NSOrderedDescending;

        return NSOrderedSame;
    }];

    // Find index of me
    NSUInteger  idx=[sortedByScore indexOfObject:me];

    // If me not found, return nil
    if(idx==NSNotFound) return nil;

    // Ideally we want to show the player before and behind
    idx=MAX(0,(NSInteger)idx-1);

    // maxIdx will be idx+2 or index of last object if lower
    NSUInteger  maxIdx=MIN(sortedByScore.count-1,idx+2);

    // In case we are last, show two previous results (if array large enough)
    if (maxIdx > 3)
                idx=MAX(0,maxIdx-3);

    // And return the objects, may be 1..3 objects
    return [sortedByScore subarrayWithRange:NSMakeRange(idx,maxIdx-idx+1)];
}
于 2013-10-13T17:01:37.287 回答
0

我假设你有一系列分数。(实际实现可以适应你的代码)

Initialize:  
firstScoreAbove = VERY_LARGE_SCORE; secondScoreAbove = VERY_LARGE_SCORE + 1;
firstScoreBelow = -1; secondScoreBelow = -2;

Scan the array elements.
if ( newScore > myScore ) {
  if ( newScore < firstScoreAbove ) {
     secondScoreAbove = firstScoreAbove;
     firstScoreAbove = newScore;
  } else if ( newScore < secondScoreAbove ) {
     secondScoreAbove = newScore;
  }
} else {
  // similarly for below.
}

扫描后,
如果 firstScoreAbove 没有变化,则 myScore 为 top 并输出以下两个分数。
如果 firstScoreBelow 没有变化,则 myScore 最低,输出以上两个分数。
否则输出 firstScoreAbove、myScore、firstScoreBelow。

于 2013-10-13T17:02:58.173 回答