Java条件分支逻辑问题:Codewars用户Rank进度计算代码调试
Codewars 用户Rank进度计算问题调试
业务规则
- 用户初始Rank为-8,最高到8,无0 Rank,-1之后直接升级至1
- 完成对应Rank的活动后更新进度(progress),累计满100 progress即可升级Rank,剩余进度保留;Rank达到8后停止更新
- 有效Rank范围:[-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8],传入非法值需抛出异常
- 进度计算规则:
- 完成同Rank活动:增加3 progress
- 完成比当前Rank低1级的活动:增加1 progress
- 完成比当前Rank低2级及以上的活动:无进度
- 完成比当前Rank高的活动:进度增加
10*d*d(d为Rank差值,需跳过0的Rank)
问题现象
调用incProgress(1)后,预期用户Rank变为-1,但实际结果为-2。
现有代码
public class User { int rank = -8; int progress = 0; public User() { } public int getRank() { return rank; } public void setRank(int rank) { this.rank = rank; } public int getRankProgress() { return progress; } public void setRankProgress(int progress) { this.progress = progress; } public void updateRank() { while (progress >= 100) { int newRank = this.rank + 1; if (rank == -1) { newRank = 1; } else if (rank == 8) { return; } setRank(newRank); setRankProgress(progress - 100); } } public void incProgress(int activityRank) { if (activityRank < -8 || activityRank == 0 || activityRank > 8) { throw new IllegalArgumentException(); } System.out.println("Called with activity rank " + activityRank + " user rank " + getRank()); if (activityRank == getRank()) { setRankProgress(progress + 3); } else if (getRank() > activityRank && getRank() - activityRank == 1) { setRankProgress(progress + 1); } else if (getRank() > activityRank && getRank() - activityRank >= 2) { return; } else if (activityRank > getRank()) { System.out.println("Called 5"); int d; if (activityRank >= 0 && getRank() < 0) { d = (activityRank - getRank()) - 1; } else { d = activityRank - getRank(); } int progress = 10 * d * d; setRankProgress(progress); } updateRank(); } }
问题原因及修复方案
1. 进度覆盖而非累加(核心错误)
在处理高Rank活动的分支中,代码直接用新计算的进度覆盖了原有进度,没有执行累加操作。比如用户原有进度为70,完成高Rank活动得到40进度,正确总进度应为110,但原代码直接设置为40,导致无法触发升级。
修复代码:
将高Rank分支中的:
int progress = 10 * d * d; setRankProgress(progress);
修改为:
int addProgress = 10 * d * d; setRankProgress(this.progress + addProgress);
2. Rank升级逻辑的循环漏洞
原updateRank方法中,当Rank达到8时直接返回,但未清零进度;同时循环条件未判断Rank是否已到上限,可能出现无效循环。另外,升级后进度更新的逻辑可以更简洁直观。
修复后的updateRank方法:
public void updateRank() { // 仅在未达最高Rank且进度足够时循环升级 while (progress >= 100 && rank != 8) { if (rank == -1) { setRank(1); } else { setRank(rank + 1); } // 扣除升级消耗的进度 setRankProgress(progress - 100); } // 达到最高Rank后清零进度 if (rank == 8) { setRankProgress(0); } }
3. 变量命名优化(可选)
高Rank分支中,局部变量progress与成员变量重名,容易造成混淆,建议修改为addProgress之类的命名,提升代码可读性。
内容的提问来源于stack exchange,提问作者Amos Machora
相关产品推荐
相关产品推荐

