本课作品
制作练习伤害计算器
会用参数把数据送进方法;会用 return 把结果带回调用处;能编写 boolean 查询方法并理解重载;最终完成考虑武器、锋利、暴击和护甲的伤害计算器。 前置背包:会定义并调用 static 方法。上一课的配方卡只有固定材料;这一课给它装上材料槽和成品出口。
开始前:建议先完成第 12 课
- 实参提供本次材料
- 方法按契约计算
- 返回值调用者接收结果
01 / 15
开始前:把示例放对地方
本章使用 JDK 21,不需要预览功能。每个普通示例都给出完整程序,按标注的文件名保存。多个示例各放在自己的文件夹,避免辅助类同名。
终端命令:把中文占位符替换成实际名称
javac -encoding UTF-8 示例文件名.java
java 示例类名类名区分大小写。完整挑战代码若分成多段,请按顺序接在同一个文件中,不要为续段另建类。运行核对只列程序输出;需要输入的地方另给输入序列。
02 / 15
附魔台不收心灵感应
附魔师问:“基础伤害多少?锋利几级?这次暴击吗?”玩家回答:“你猜。”附魔师把书一合:方法不会心灵感应。
参数是方法定义里的材料槽,实参是调用时真正放进去的数据。返回值则是方法完成计算后交出来的成品。
- base基础伤害,double
- sharp锋利等级,int
- critical暴击状态,boolean
- armor目标护甲,double
带着四个问题出发
- 形参和实参分别出现在哪里?
- 多个参数为什么必须按顺序传入?
- void 与有返回值的方法有什么区别?
- 重载为什么不能只改返回类型?
03 / 15
参数槽和实参材料
double base 和 int level 是形参;7.0 和 3 是实参。调用发生时,实参值会进入对应参数。
- 实参调用处提供值
- 形参与计算方法使用值的副本
- return把结果交回调用处
L13Example02.java · 完整独立示例
public class L13Example02 {
static double damage(double base, int level) { return base + level * 1.5; }
public static void main(String[] args) {
System.out.println(damage(7.0, 3));
System.out.println(damage(5.0, 0));
System.out.println(damage(8.0, 2));
}
}运行结果
11.5
5.0
11.004 / 15
多个参数不能站错格
如果两个参数类型相同,传反后 Java 可能照样编译。房子会从 9×7 变成 7×9,然后理直气壮地说自己没有报错。
- width第一项,横向宽度
- height第二项,纵向高度
- 正确调用9,7得到宽9高7
- 传反7,9能编译但含义改变
L13Example03.java · 完整独立示例
public class L13Example03 {
static void describeArea(int width, int height) {
System.out.println(width + " x " + height);
}
public static void main(String[] args) {
int houseWidth = 9, houseHeight = 7;
describeArea(houseWidth, houseHeight);
describeArea(houseHeight, houseWidth);
}
}运行结果
9 x 7
7 x 9调用检查
- 参数太多时,每个实参单独一行。
- 使用含义清楚的变量名,不直接堆数字。
- 测试宽高不同的值,传反时更容易看出来。
05 / 15
return 把结果送回来
有返回值的方法像工作台:放入材料,取出成品。return 一执行,方法立刻结束,并把值交给调用处。 本例每种材料限定0到64;非法输入返回0是本方法约定,不是所有计算方法都应采用的策略。
- 实参调用处提供值
- 形参与计算方法使用值的副本
- return把结果交回调用处
L13Example04.java · 完整独立示例
public class L13Example04 {
static int torchCount(int coal, int sticks) {
if (coal < 0 || sticks < 0 || coal > 64 || sticks > 64) return 0;
return Math.min(coal, sticks) * 4;
}
public static void main(String[] args) {
int torches = torchCount(7, 10);
System.out.println(torches);
System.out.println(torchCount(2, 5) >= 8);
}
}运行结果
28
true06 / 15
提前 return 守住边界
边界检查放在方法开头,能让后面的正常公式保持清楚。提前返回不是逃课,而是保安把负数苦力怕请出工作台。
- 负数量直接返回0
- 正常数量按配方计算
- 过大材料本例超过64也拒绝
- 锋利等级修正到0到5
L13Example05.java · 完整独立示例
public class L13Example05 {
static int torchCount(int coal, int sticks) {
if (coal < 0 || sticks < 0 || coal > 64 || sticks > 64) return 0;
return Math.min(coal, sticks) * 4;
}
static int safeLevel(int level) { return Math.max(0, Math.min(5, level)); }
public static void main(String[] args) {
System.out.println(torchCount(-1, 3));
System.out.println(torchCount(0, 64));
System.out.println(safeLevel(9));
}
}运行结果
0
0
507 / 15
boolean 方法回答真假
返回 boolean 的方法适合回答问题。调用处读起来像一句话,因此方法名要带问题味道。
- canCraftPickaxe仅检查材料数量
- true材料至少3钻石2木棍
- false有一种材料不足
- 调用处根据答案决定后续动作
L13Example06.java · 完整独立示例
public class L13Example06 {
static boolean canCraftPickaxe(int diamonds, int sticks) {
return diamonds >= 3 && sticks >= 2;
}
public static void main(String[] args) {
System.out.println(canCraftPickaxe(5, 1));
if (canCraftPickaxe(3, 2)) System.out.println("材料够了");
}
}运行结果
false
材料够了08 / 15
同名方法的不同配方
重载让相关操作共享一个方法名,但参数列表必须不同。它适合“同一动作,不同材料组合”。
- 单参数版本物品名,默认数量1
- 双参数版本物品名与数量
- 重载规则参数列表必须不同
- 调用Java按参数选择版本
L13Example07.java · 完整独立示例
public class L13Example07 {
static void giveItem(String item) { giveItem(item, 1); }
static void giveItem(String item, int count) {
System.out.println(item + " x" + count);
}
public static void main(String[] args) {
giveItem("钻石");
giveItem("火把", 16);
}
}运行结果
钻石 x1
火把 x1609 / 15
Java 怎样选择重载
调用重载方法时,Java 查看实参的数量和类型。若两个版本都同样合适,就会出现“我该进哪扇门”的编译错误。
- show(int)整数3选择这个版本
- show(double)3.5选择这个版本
- 类型转换整型可兼容变为double
- 注意不能只靠返回类型选择
L13Example08.java · 完整独立示例
public class L13Example08 {
static void show(int n) { System.out.println("整数 " + n); }
static void show(double n) { System.out.println("小数 " + n); }
public static void main(String[] args) {
show(3);
show(3.5);
}
}运行结果
整数 3
小数 3.510 / 15
伤害公式拆开计算
复杂公式不要塞进一行。先计算武器与锋利,再处理暴击,最后扣除护甲,并用 Math.max 防止伤害变成负数。
- 实参调用处提供值
- 形参与计算方法使用值的副本
- return把结果交回调用处
L13Example09.java · 完整独立示例
public class L13Example09 {
static double damage(double base, int sharp,
boolean critical, double armor) {
if (!Double.isFinite(base) || !Double.isFinite(armor)) return 0;
base = Math.max(0, Math.min(100, base));
sharp = Math.max(0, Math.min(5, sharp));
armor = Math.max(0, Math.min(100, armor));
double raw = base + sharp * 1.5;
if (critical) raw *= 1.5;
return Math.max(0, raw - armor);
}
public static void main(String[] args) {
System.out.println(damage(7, 2, false, 5));
System.out.println(damage(7, 5, true, 0));
}
}运行结果
5.0
21.7511 / 15
三类测试照出漏洞
测试不是“多点几次运行”。每个测试要有输入、预期和实际结果。
- 正常普通命中与暴击
- 边界等级0或5,护甲0
- 错误负数与非有限小数
- 比较小数测试允许极小误差
L13Example10.java · 完整独立示例
public class L13Example10 {
static double damage(double base, int sharp,
boolean critical, double armor) {
if (!Double.isFinite(base) || !Double.isFinite(armor)) return 0;
base = Math.max(0, Math.min(100, base));
sharp = Math.max(0, Math.min(5, sharp));
armor = Math.max(0, Math.min(100, armor));
double raw = base + sharp * 1.5;
if (critical) raw *= 1.5;
return Math.max(0, raw - armor);
}
public static void main(String[] args) {
double result = damage(7, 2, false, 5);
System.out.println(Math.abs(result - 5.0) < 0.0001);
System.out.println(damage(-2, 9, false, -1));
System.out.println(damage(Double.NaN, 2, false, 0));
}
}运行结果
true
7.5
0.0| 类别 | 输入 base, sharp, critical, armor | 预期 |
|---|---|---|
| 正常 | 7, 2, false, 5 | 5.0 |
| 边界 | 0, 0, false, 0 | 0.0 |
| 边界 | 7, 5, true, 0 | 21.75 |
| 修正 | -2, 9, false, -1 | 7.5 |
| 错误 | NaN, 2, false, 0 | 0.0 |
12 / 15
参数与返回值故障诊所
先读方法头,它就是契约。调用处必须提供正确数量和类型的实参;非 void 方法的每条可达路径都要返回值。
- 漏返回有路径没有return
- 重载冲突参数一样,仅改返回类型
- 少实参数量不匹配
- 修复核对方法契约
BadReturn.java · 故意错误示例
public class BadReturn {
static int count(int n) { if (n > 0) return n; }
public static void main(String[] args) { }
}BadOverload.java · 故意错误示例
public class BadOverload {
static int value(int n) { return n; }
static double value(int n) { return n; }
public static void main(String[] args) { }
}13 / 15
挑战 伤害计算器
新建 DamageCalculator.java。挑战 方法对负数输入做保护,把锋利限制在0到5,再计算最终伤害。
- 输入契约base和armor在0到100
- 等级契约sharp修正到0到5
- 计算规则自定义练习伤害
- 输出契约返回有限且非负的值
DamageCalculator.java · 完整独立示例
public class DamageCalculator {
static double damage(double base, int sharp,
boolean critical, double armor) {
if (!Double.isFinite(base) || !Double.isFinite(armor)) return 0;
base = Math.max(0, Math.min(100, base));
sharp = Math.max(0, Math.min(5, sharp));
armor = Math.max(0, Math.min(100, armor));
double raw = base + sharp * 1.5;
if (critical) raw *= 1.5;
return Math.max(0, raw - armor);
}
public static void main(String[] args) {
System.out.println(damage(7, 2, false, 5));
System.out.println(damage(7, 5, true, 0));
System.out.println(damage(-2, 9, false, -1));
}
}运行结果
5.0
21.75
7.514 / 15
拓展任务与通关复盘
每档都要写至少三个测试,其中必须有一个边界值。
- 木镐材料计算与边界
- 铁镐坐标距离方法
- 钻石镐增加有区别的重载
- 复盘解释形参与实参
三档作业
- 木镐:写 torchCount(coal, sticks),返回最多能合成的火把数量。
- 铁镐:写 distance(x1, y1, x2, y2),返回两点直线距离。
- 钻石镐:重载三种 giveItem,分别支持默认数量、指定数量和指定玩家。
| 自评 | 能 | 还要练 |
|---|---|---|
| 我能解释形参与实参 | □ | □ |
| 我能使用 return | □ | □ |
| 我能判断重载是否成立 | □ | □ |
15 / 15
自己的验收记录
运行之前写预期,运行之后记录实际结果。正常案例说明程序会做事;边界案例说明它知道何时停;错误案例说明它能拒绝不合理的请求。
| 类别 | 你选择的输入 | 预期与实际 |
|---|---|---|
| 正常 | 一个常用值或一次成功操作 | 是否逐行一致? |
| 边界 | 最小值、最大值及相邻值 | 有没有少一格、多一步? |
| 错误 | 非法数量、缺失对象或错误语法 | 是否明确拒绝?状态是否保持? |
- 把一个 Bug 写成:触发条件、现象、原因、最小修复。
- 整理一个值得记住的规则,用自己的话解释,不能只复制定义。
- 改变一个示例,保留测试记录,让结果证明你的理解。
TAKE IT WITH YOU
下载本课 PDF
完整课文、代码、图解与练习,选择你需要的语言。