开发 / ROBLOX
Luau 函数:参数、return 与结果检查
学习如何接收函数结果、区分 return 和 print,并检查输入。本原创练习计算路线剩余站点,提供可运行的示例与边界检查。
先明确函数回答的问题 #
想象一条有十个站点的教学路线。已知站点总数与已访问的数量,需要计算还剩多少。函数只回答算术问题:从 total 中减去 visited。它不会移动角色、读取存档,也不会确认玩家真的访问过游戏中的站点。
先写下输入含义:total 是站点总数,visited 是已经访问的数量。本练习要求两者都是非负整数,visited 不能超过 total。这是示例约定,不是所有 Roblox 路线都必须采用的规则。明确约定后,才能判断问题来自输入、计算过程还是错误的预期。
定义函数,再调用它 #
第一个示例定义 local function remainingStops(total, visited)。定义行与 end 之间是函数体,return 把计算得到的差值交给调用方。仅定义函数还没有执行这次计算。调用 remainingStops(10, 3) 时,括号内的两个实参才进入函数。
两次调用将结果保存到不同变量。十个站点访问三个,预期剩下 7;十个站点访问六个,预期剩下 4。随后 print 显示保存的数值。可在独立的教学 Script 中运行完整代码并比较两行 Output。这些原创示例也已通过独立 Luau 解释器执行;它验证语言和算术行为,不表示 Studio 中的真实路线已经测试。
local function remainingStops(total, visited)
return total - visited
end
local firstRemaining = remainingStops(10, 3)
local secondRemaining = remainingStops(10, 6)
print(firstRemaining)
print(secondRemaining)区分形参名称与实参值 #
total 与 visited 是函数内部的形参名称,10 与 3 是某次调用传入的实参。下一次调用可以给相同形参提供不同数值。外部变量可以叫 routeLength,不必与形参同名;关键是其值符合 total 的约定含义。
顺序很重要。remainingStops(10, 3) 与 remainingStops(3, 10) 使用不同输入。最初的简单函数不检查含义,因此第二种调用会算出负数。改变输出标签不能修复输入错误。先核对传参顺序和实际数值,再加入有效性检查。
观察没有 return 的 print #
第二个示例 showRemaining 在函数体内打印差值。传入 10 和 3 时,Output 确实出现 7。但函数没有显式返回数值,调用方的 result 变量得到 nil。之后的 print(result) 因而显示 nil,而不是再次显示七。
正确的 Output 信息并不证明调用方收到所需数值。如果后续代码需要这个数量,计算函数就应返回它。练习时保留两个 print,观察先出现函数内的数值,再出现调用方的 nil。把结果改成固定的七只会隐藏问题:输入改变后仍需要正确计算。
local function showRemaining(total, visited)
print(total - visited)
end
local result = showRemaining(10, 3)
print(result)将返回结果保存在需要的位置 #
第一个示例中,firstRemaining 和 secondRemaining 保存返回的数字。调用方可以比较、继续传递或显示它们。计算与展示成为两个步骤。理解 return 只需要局部变量和结果检查,不必先搭建用户界面。
return 会结束当前函数分支的执行。不要把继续计算放在同一分支的 return 后面,期待它改变返回值。Luau 也支持用逗号分隔多个返回值。检查版函数返回“结果、有效标记”这一对值,明确区分缺失结果与成功计算。
在减法之前检查输入 #
第三个示例 checkedRemaining 先检查类型。缺少 visited 时,该形参得到 nil;函数会在算术之前返回 nil, false。字符串 "10" 也被拒绝,因为示例只接受数字,不负责解析文本输入。接着排除 NaN 与正无穷;负数及负无穷无法通过非负检查。
除以 1 的余数检查用于排除小数数量,最后一个条件排除 visited 大于 total 的情况。只有符合约定的输入才能执行 return total - visited, true。这样的顺序让规则容易阅读,但它不能证明客户端传来的数量就是玩家的真实进度。
local function checkedRemaining(total, visited)
if type(total) ~= "number" or type(visited) ~= "number" then
return nil, false
end
if total ~= total or visited ~= visited then
return nil, false
end
if total == math.huge or visited == math.huge then
return nil, false
end
if total < 0 or visited < 0 or total % 1 ~= 0 or visited % 1 ~= 0 then
return nil, false
end
if visited > total then
return nil, false
end
return total - visited, true
end
print(checkedRemaining(10, 3))
print(checkedRemaining(10))
print(checkedRemaining(10, 12))检查缺失参数与超额进度 #
代码包含三次调用。checkedRemaining(10, 3) 输出 7 与 true。checkedRemaining(10) 因第二个参数缺失而输出 nil 与 false。checkedRemaining(10, 12) 同样输出 nil 与 false:按照本练习规则,十个站点不能已经访问十二个。
用 local value, valid = checkedRemaining(total, visited) 保存两个返回值。显示数字前先检查 valid == true;false 时准备清楚的数据错误提示。不要自动把 nil 变成零,否则错误会看起来像路线已经完成。应在生成输入的位置修复数据。
将零视为有效结果 #
checkedRemaining(10, 10) 返回 0, true,表示十个站点全部访问后剩余数量为零。空教学路线 checkedRemaining(0, 0) 也返回 0, true。这些都是有效计算;nil, false 才表示输入被拒绝,没有可用结果。
在 Luau 条件判断中,零是真值,不过显式检查 valid == true 更能表达本函数的约定。仅使用 value > 0 会错误排除正确的零结果。真实游戏如何处理路线完成,应在有效性检查之后另行设计,并确认游戏采用这一进度模型。
检查边界,不只检查一次成功调用 #
建立测试表:10 与 3 得到 7,10 与 0 得到 10,10 与 10 得到 0,0 与 0 得到 0。每组都应返回 true。另外列出无效输入:缺少参数、字符串、负数、小数,以及 visited 超过 total;这些应返回 nil 与 false。
配套检查文件已使用 assert 执行这些情况,并额外检查 NaN 与无穷。先记录预期,再比较实际返回值对。如果出现差异,应报告具体输入和两个实际值。正确的算术并不验证存档、客户端可信度或奖励发放。
| 输入 total / visited | 预期结果 |
|---|---|
| 10 / 3 | 7, true |
| 10 / 10 | 0, true |
| 0 / 0 | 0, true |
| 10 / 缺少第二个参数 | nil, false |
将输入输出约定与代码一起交接 #
为下一位开发者保存函数名、参数含义与顺序、允许输入、返回值对及测试表。标明这是原创的纯 Luau 教学代码。以后接入真实路线时,要另行规定服务器如何获得经过确认的 total 与 visited,以及缺失数据时如何处理。
本练习没有 Roblox 对象、事件、网络通信或持久存储,因此不是完整的进度系统。练习的价值是理解 Output 信息与调用方可用结果之间的区别,并用明确输入验证它。后续扩展时保留已检查的输入输出约定。
| 字段 | 保存内容 |
|---|---|
| 参数 | 总数与已访问数量 |
| 规则 | 有限非负整数 |
| 结果 | 数字与独立 valid 标记 |
| 检查 | 正常输入与边界输入 |