C#开发:如何移除for循环,编写无循环及分支语句的得分计算代码
移除C#计分代码中的for循环(无循环/分支实现)
嘿,这个问题挺有意思的——要在保龄球计分逻辑里彻底移除循环和分支语句,确实得换个思路绕开常规的控制流!你原来的代码已经用了Convert.ToInt32(bool)转0/1来模拟分支选择(用乘法过滤无效情况),这个思路可以保留,我们只需要用递归来替代for循环的重复执行逻辑。
核心思路
原来的for循环是重复处理10个frame,每次根据当前球的位置判断得分类型并更新分数和球的索引。递归可以完美替代这种重复:我们写一个辅助方法,每次处理一个frame,然后递归调用自己处理下一个,直到处理完10个frame为止。同时继续用「0/1乘法过滤」的方式避免分支语句。
重构后的代码
public int score() { // 初始化递归参数:第0个frame,第0个球的位置,当前分数0 return CalculateScore(0, 0, 0); } // 递归辅助方法:处理单个frame,递归直到完成所有10个frame private int CalculateScore(int frameIndex, int currentRollIndex, int currentScore) { // 递归终止条件:处理完10个frame,返回累计总分 if (frameIndex >= 10) return currentScore; // 处理Strike情况:用0/1乘法仅当是Strike时生效 int isStrike = Convert.ToInt32(isStrike(currentRollIndex)); int strikeScore = getStrikeCalculation(currentRollIndex) * isStrike; int strikeRollOffset = 1 * isStrike; // 处理Spare情况:仅当不是Strike时才生效(用1-isStrike过滤) int isSpare = Convert.ToInt32(isSpare(currentRollIndex)) * (1 - isStrike); int spareScore = getSpareCalculation(currentRollIndex) * isSpare; int spareRollOffset = 2 * isSpare; // 处理Normal情况:仅当既不是Strike也不是Spare时生效 int isNormal = Convert.ToInt32(isNormal(currentRollIndex)) * (1 - isStrike) * (1 - isSpare); int normalScore = getNormalCalculation(currentRollIndex) * isNormal; int normalRollOffset = 2 * isNormal; // 计算更新后的球位置和总分:三种情况只会有一种生效,累加即可 int newRollIndex = currentRollIndex + strikeRollOffset + spareRollOffset + normalRollOffset; int newScore = currentScore + strikeScore + spareScore + normalScore; // 递归处理下一个frame return CalculateScore(frameIndex + 1, newRollIndex, newScore); }
关键细节说明
- 递归替代循环:
CalculateScore方法每次处理一个frame,然后递归调用自己处理下一个,直到frameIndex >=10时终止,对应原for循环的frameIndex <10条件。 - 无分支实现:依然沿用你原来的「布尔转整数」思路,用0或1作为开关,通过乘法过滤掉当前frame不适用的得分类型,完全避免了
if/else/switch这类分支语句。 - 索引正确性:因为每个frame只会是Strike、Spare、Normal中的一种,所以另外两种情况的偏移量和分数都会是0,不会影响最终的
newRollIndex和newScore。
需要注意的是,要确保isStrike、isSpare、isNormal这三个方法的逻辑是互斥的——同一个球的位置不会同时满足多个条件,这样乘法过滤的逻辑才能正常工作。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

