Java骰子游戏代码输出异常,疑似for循环逻辑问题求助
骰子游戏逻辑错误修正
需求说明
- 攻击者掷3个20面骰子,防御者掷2个20面骰子
- 双方丢弃高于各自输入目标值的骰子(保留≤目标值的)
- 攻击者剩余骰子中,丢弃≤防御者剩余骰子的部分,统计剩余骰子数即为命中数
测试用例
输入:攻击者目标15,防御者目标10
预期输出:
0 hit(s): 494741
1 hit(s): 1006677
2 hit(s): 1080423
3 hit(s): 618159
实际输出:
0 hit(s): 1020656
1 hit(s): 100373
2 hit(s): 62674
3 hit(s): 16297
原代码
import java.util.Scanner; public class DiceGame { public static void main(String[] args) { Scanner input = new Scanner(System.in); int[] numHits = new int[4]; int attackerTarget, defenderTarget; System.out.print("Attacker Target(1-20): "); attackerTarget = input.nextInt(); System.out.print("Defender Target(1-20): "); defenderTarget = input.nextInt(); for (int a = 1; a <= 20; a++) { for (int b = 1; b <= 20; b++) { for (int c = 1; c <= 20; c++) { for (int i = 1; i <= 20; i++) { for (int j = 1; j <= 20; j++) { if (i <= attackerTarget && j <= defenderTarget) { int numberOfHits = 0; int attackerNum1 = (int) (Math.random() * 20 + 1); int attackerNum2 = (int) (Math.random() * 20 + 1); int attackerNum3 = (int) (Math.random() * 20 + 1); int defenderNum1 = (int) (Math.random() * 20 + 1); int defenderNum2 = (int) (Math.random() * 20 + 1); if (attackerNum1 < attackerTarget && defenderNum1 < defenderTarget && defenderNum2 < defenderTarget) { if (attackerNum1 > defenderNum1 && attackerNum1 > defenderNum2) { numberOfHits++; } } if (attackerNum2 < attackerTarget && defenderNum1 < defenderTarget && defenderNum2 < defenderTarget) { if (attackerNum2 > defenderNum1 && attackerNum2 > defenderNum2) { numberOfHits++; } } if (attackerNum3 < attackerTarget && defenderNum1 < defenderTarget && defenderNum2 < defenderTarget) { if (attackerNum3 > defenderNum1 && attackerNum3 > defenderNum2) { numberOfHits++; } } numHits[numberOfHits]++; } } } } } } for (int i = 0; i <= 3; i++) { System.out.println(i + " hit(s): " + numHits[i]); } } }
错误点分析
- 循环与随机数逻辑混乱:原代码用5层循环遍历所有可能的骰子组合,但内部又用
Math.random()生成随机数,完全重复且破坏了枚举逻辑,应该直接使用循环变量作为骰子值,不需要随机数。 - 骰子过滤条件错误:需求是保留≤目标值的骰子,原代码用
<判断,漏掉了等于目标值的情况;同时错误地要求防御者两个骰子都符合条件才处理,实际应该分别过滤每个骰子。 - 命中判断逻辑偏离需求:原代码判断单个攻击骰子是否大于两个防御骰子才计数,这和需求中“攻击者丢弃≤防御者剩余骰子,统计剩余数”完全不符。正确逻辑应该是双方过滤后,将剩余骰子降序排列,用攻击骰子逐个对比防御骰子,攻击骰子更大则计数+1。
修正后的代码
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; public class DiceGame { public static void main(String[] args) { Scanner input = new Scanner(System.in); int[] numHits = new int[4]; int attackerTarget, defenderTarget; System.out.print("Attacker Target(1-20): "); attackerTarget = input.nextInt(); System.out.print("Defender Target(1-20): "); defenderTarget = input.nextInt(); // 枚举所有可能的骰子组合:3个攻击者骰子,2个防御者骰子 for (int a1 = 1; a1 <= 20; a1++) { for (int a2 = 1; a2 <= 20; a2++) { for (int a3 = 1; a3 <= 20; a3++) { for (int d1 = 1; d1 <= 20; d1++) { for (int d2 = 1; d2 <= 20; d2++) { // 收集攻击者有效骰子(<=目标值) ArrayList<Integer> attackerDice = new ArrayList<>(); if (a1 <= attackerTarget) attackerDice.add(a1); if (a2 <= attackerTarget) attackerDice.add(a2); if (a3 <= attackerTarget) attackerDice.add(a3); // 收集防御者有效骰子(<=目标值) ArrayList<Integer> defenderDice = new ArrayList<>(); if (d1 <= defenderTarget) defenderDice.add(d1); if (d2 <= defenderTarget) defenderDice.add(d2); // 降序排序,以便从大到小对比 Collections.sort(attackerDice, Collections.reverseOrder()); Collections.sort(defenderDice, Collections.reverseOrder()); int hits = 0; int attackIndex = 0; int defendIndex = 0; // 逐个对比:攻击骰子>防御骰子则计数+1 while (attackIndex < attackerDice.size() && defendIndex < defenderDice.size()) { if (attackerDice.get(attackIndex) > defenderDice.get(defendIndex)) { hits++; attackIndex++; defendIndex++; } else { attackIndex++; } } // 统计命中数 numHits[hits]++; } } } } } // 输出结果 for (int i = 0; i <= 3; i++) { System.out.println(i + " hit(s): " + numHits[i]); } input.close(); } }
内容的提问来源于stack exchange,提问作者mel ur mom
相关产品推荐
相关产品推荐

