参与者池大小调整:poolNum与standing同步修正技术求助
池玩家重排逻辑修正方案
我来帮你梳理下问题并修正代码——你的核心需求是根据目标池大小调整玩家的池编号(lp_pool_order)和池内排名(lp_standing),目前缩容(下推玩家)逻辑基本正常,但扩容(上拉玩家)时存在两个关键问题:被抽取玩家的原池剩余玩家排名未更新、后续池的池编号未整体递减。下面是具体的分析和修正方案:
原代码问题分析
你的ReorderParticipants方法存在以下几个问题:
- 扩容时仅修改了被移动玩家的
lp_pool_order,但所有后续池的玩家的池编号都需要递减1(因为目标池扩容占用了后续池的位置); - 被抽取玩家的原池,剩余玩家的排名没有重新从1开始排序,导致排名断层;
- 循环中
i <= playersToMoveDown.Count会触发索引越界(列表索引从0开始,最大索引为Count-1); - 扩容时给移动玩家设置的
lp_standing逻辑错误,应该是目标池原有玩家数+递增序号,而非直接加上playersInPool。
修正后的代码
public void ReorderParticipants(int poolOrder, int poolSize, List<ClubLeagueParticipant> allPlayersFromClubLeague) { // 获取目标池当前的玩家数量 int playersInPool = allPlayersFromClubLeague .Count(x => x.lp_pool_order == poolOrder); int movingPlayers = poolSize - playersInPool; // 缩容处理:将目标池内排名超过poolSize的玩家下推 if (movingPlayers < 0) { int playersToMoveDownCount = Math.Abs(movingPlayers); // 选出需要下推的玩家(目标池内排名超出poolSize的) var playersToMoveDown = allPlayersFromClubLeague .Where(x => x.lp_pool_order == poolOrder && x.lp_standing > poolSize) .OrderBy(x => x.lp_standing) .ToList(); if (playersToMoveDown.Any()) { // 将下推玩家的池编号+1 foreach (var player in playersToMoveDown) { player.lp_pool_order += 1; // 下推玩家进入新池后,排名放在新池末尾 int newPoolPlayerCount = allPlayersFromClubLeague.Count(x => x.lp_pool_order == player.lp_pool_order); player.lp_standing = newPoolPlayerCount; } // 目标池剩余玩家重新排序排名(从1开始递增) var remainingPoolPlayers = allPlayersFromClubLeague .Where(x => x.lp_pool_order == poolOrder) .OrderBy(x => x.lp_standing) .ToList(); for (int i = 0; i < remainingPoolPlayers.Count; i++) { remainingPoolPlayers[i].lp_standing = i + 1; } // 后续第一个池的玩家排名加上下推的数量,确保排名连续 var nextPoolPlayers = allPlayersFromClubLeague .Where(x => x.lp_pool_order == poolOrder + 1) .OrderBy(x => x.lp_standing) .ToList(); foreach (var player in nextPoolPlayers) { player.lp_standing += playersToMoveDownCount; } } } // 扩容处理:从后续池抽取玩家进入目标池 else if (movingPlayers > 0) { // 按池编号从小到大、池内排名从小到大,选出需要上拉的玩家 var playersToMoveUp = allPlayersFromClubLeague .Where(x => x.lp_pool_order > poolOrder) .OrderBy(x => x.lp_pool_order) .ThenBy(x => x.lp_standing) .Take(movingPlayers) .ToList(); if (playersToMoveUp.Any()) { // 记录每个被抽取玩家的原池编号,用于后续处理原池排名重排 var originalPoolNumbers = playersToMoveUp.Select(x => x.lp_pool_order).Distinct().ToList(); // 设置上拉玩家的池编号和排名:排名从目标池原有数量+1开始递增 for (int i = 0; i < playersToMoveUp.Count; i++) { playersToMoveUp[i].lp_pool_order = poolOrder; playersToMoveUp[i].lp_standing = playersInPool + i + 1; } // 所有池编号大于目标池的玩家,池编号统一递减1(后续池整体前移) var playersAfterTargetPool = allPlayersFromClubLeague .Where(x => x.lp_pool_order > poolOrder) .ToList(); foreach (var player in playersAfterTargetPool) { player.lp_pool_order -= 1; } // 对每个被抽取过的原池,剩余玩家重新排序排名(从1开始递增) foreach (int originalPool in originalPoolNumbers) { var remainingPlayers = allPlayersFromClubLeague .Where(x => x.lp_pool_order == originalPool) .OrderBy(x => x.lp_standing) .ToList(); for (int i = 0; i < remainingPlayers.Count; i++) { remainingPlayers[i].lp_standing = i + 1; } } } } // 池大小不变,无需处理 else { return; } }
代码关键修改说明
缩容逻辑优化
- 修复了循环索引越界问题,改用
foreach遍历下推玩家更安全; - 目标池剩余玩家按原排名排序后,重新分配从1开始的连续排名;
- 下推玩家进入新池后,直接设置为新池的末尾排名(新池当前玩家数);
- 后续第一个池的玩家排名加上下推数量,避免排名冲突。
扩容逻辑核心修复
- 后续池编号整体递减:所有池编号大于目标池的玩家,统一将
lp_pool_order减1,确保池编号连续; - 原池剩余玩家排名重排:记录被抽取玩家的原池编号,对每个原池的剩余玩家按原排名排序后,重新分配1开始的连续排名;
- 上拉玩家排名正确设置:上拉玩家进入目标池后,排名从
playersInPool + 1开始递增,确保排在目标池原有玩家的末尾。
内容的提问来源于stack exchange,提问作者decata plachat
相关产品推荐
相关产品推荐

