Lua 循环(深入浅出)

Lua 循环:让程序自动“重复做对的事”

在编程的世界里,重复是常态。无论是处理数据、遍历列表,还是等待用户输入,我们总需要让程序“重复执行一段代码”。Lua 语言通过简洁而强大的循环机制,帮助开发者高效完成这类任务。今天,我们就来深入聊聊 Lua 循环,从基础语法到实战技巧,手把手带你掌握这一核心功能。

如果你刚接触编程,可能会觉得“循环”听起来很抽象。不妨把它想象成一个自动洗衣机:你把衣服放进去,设定好时间,它就会自动完成清洗、漂洗、脱水等一系列动作。而 Lua 循环,就是你写下的那串指令,它会自动重复执行,直到你设定的条件满足为止。

for 循环:计数型循环的精准控制

Lua 中最常用的循环结构之一是 for 循环,它特别适合你知道循环次数的场景。比如你要打印 1 到 10 的数字,或者遍历一个固定长度的数组。

-- 从 1 循环到 10,每次递增 1
for i = 1, 10, 1 do
    print("当前数字是:" .. i)
end

上面这段代码中:

  • i = 1 是循环变量的初始值,相当于洗衣机开始运转前的设定。
  • 10 是循环的结束条件,当 i 超过 10 时,循环停止。
  • 1 是步长,表示每次 i 增加多少。默认步长是 1,可以省略。

如果你想要倒序输出,比如从 10 到 1,只需要把步长改为 -1:

-- 倒序输出 10 到 1
for i = 10, 1, -1 do
    print("倒计时:" .. i)
end

for 循环的灵活性

for 循环不仅限于整数。你还可以使用浮点数作为步长,比如打印 0.1 到 1.0 的小数:

-- 打印 0.1 到 1.0,步长为 0.1
for i = 0.1, 1.0, 0.1 do
    print("数值:" .. i)
end

这种写法在处理物理计算、动画帧、时间轴等场景非常有用。

while 循环:条件驱动的“持续运行”

当循环次数不确定时,while 循环就派上用场了。它的核心思想是:只要条件为真,就继续执行;一旦条件变为假,就退出循环。

-- 简单的猜数字游戏
local secret_number = 42
local guess = 0

while guess ~= secret_number do
    print("请输入一个数字:")
    guess = tonumber(io.read())  -- 从控制台读取输入
    if guess < secret_number then
        print("太小了!")
    elseif guess > secret_number then
        print("太大了!")
    else
        print("恭喜你,猜对了!")
    end
end

这段代码中:

  • guess ~= secret_number 是判断条件,表示“如果猜的数不等于正确答案”。
  • io.read() 用于读取用户输入,tonumber() 将字符串转换为数字。
  • 循环会一直持续,直到用户猜中为止。

while 循环的陷阱与防范

一个常见的错误是忘记更新循环变量,导致无限循环。比如下面这段代码:

-- ❌ 错误示例:缺少更新逻辑
local i = 1
while i <= 5 do
    print(i)
    -- 没有 i = i + 1,循环永远无法结束!
end

这个程序会卡死,一直打印 1。因此,使用 while 循环时,务必确保条件最终能变为假。

repeat...until 循环:先执行再判断

repeat...until 是 Lua 中一个非常独特的循环结构,它的特点是:先执行一次,再判断条件。这在需要至少执行一次的场景中特别有用。

-- 用户输入验证:必须输入非空内容
local input = ""

repeat
    print("请输入你的名字:")
    input = io.read()
until input ~= ""  -- 直到输入非空才退出

print("你好," .. input .. "!")

while 不同,repeat...until 保证至少执行一次。这就像你去餐厅点菜,服务员必须先问你“要吃什么”,然后才判断你有没有回答。

与 while 循环的对比

特性 while 循环 repeat...until 循环
执行顺序 先判断条件,再执行 先执行,再判断条件
至少执行一次
适合场景 条件明确,可能不执行 必须至少执行一次

遍历表(table)的循环:处理数据集合

在 Lua 中,table 是最核心的数据结构,类似于 Python 的字典或 JavaScript 的对象。我们经常需要遍历一个 table 中的所有键值对。

ipairs:遍历有序表

当你有一个编号从 1 开始的数组式 table 时,使用 ipairs 是最佳选择:

-- 定义一个学生名单
local students = {"小明", "小红", "小刚", "小丽"}

-- 使用 ipairs 遍历
for index, name in ipairs(students) do
    print("第 " .. index .. " 位学生是:" .. name)
end

输出:

第 1 位学生是:小明
第 2 位学生是:小红
第 3 位学生是:小刚
第 4 位学生是:小丽

ipairs 会从下标 1 开始,逐个获取键值对,直到遇到 nil 为止。

pairs:遍历所有键值对

如果你的 table 不是连续编号,或者包含字符串键,应该使用 pairs

-- 定义一个成绩表
local scores = {
    ["语文"] = 85,
    ["数学"] = 92,
    ["英语"] = 78,
    ["物理"] = 88
}

-- 使用 pairs 遍历所有键值对
for subject, score in pairs(scores) do
    print(subject .. " 成绩:" .. score)
end

输出:

语文 成绩:85
数学 成绩:92
英语 成绩:78
物理 成绩:88

注意:pairs 的遍历顺序是不确定的,不要依赖顺序。

实际案例:统计学生成绩

我们来做一个小项目:计算平均分并找出最高分。

local scores = {
    ["小明"] = 85,
    ["小红"] = 92,
    ["小刚"] = 78,
    ["小丽"] = 88
}

local total = 0
local max_score = 0
local best_student = ""

for name, score in pairs(scores) do
    total = total + score
    if score > max_score then
        max_score = score
        best_student = name
    end
end

local average = total / #scores  -- #scores 获取表中元素个数

print("平均分:" .. average)
print("最高分:" .. max_score .. "(由 " .. best_student .. " 获得)")

这段代码展示了如何结合 pairs 和变量更新,完成一个完整的数据处理任务。

循环控制语句:跳出与跳过

Lua 提供了两个控制语句,让你更灵活地管理循环流程:

  • break:立即退出当前循环
  • continue:跳过本次循环,进入下一次(Lua 中通过 goto 实现,但通常用 if 跳过)

break 的使用场景

当你在循环中发现某个条件满足,不需要继续执行时,可以用 break

-- 找到第一个能被 3 整除的数
for i = 1, 100 do
    if i % 3 == 0 then
        print("第一个能被 3 整除的数是:" .. i)
        break  -- 找到后立即退出
    end
end

模拟 continue:跳过特定情况

Lua 没有 continue 关键字,但可以通过嵌套 if 实现跳过:

-- 打印 1 到 10,但跳过 5
for i = 1, 10 do
    if i == 5 then
        -- 跳过 5,不执行下面的 print
        goto continue
    end
    print("当前数字:" .. i)
    ::continue::
end

⚠️ 注意:goto 标签必须在同级作用域中定义,且 ::continue:: 必须在 if 语句之后。

总结:掌握 Lua 循环的关键

Lua 循环是编写高效、可维护代码的基础。通过 forwhilerepeat...until 三种结构,你可以应对几乎所有重复执行的场景。而 ipairspairs 则让你轻松处理数据集合。

记住几个核心原则:

  • for 处理已知次数的循环
  • while 处理条件驱动的重复
  • repeat...until 确保至少执行一次
  • 遍历 table 时选择合适的迭代器
  • 合理使用 break 控制流程

编程的本质,就是让机器替你重复做对的事。当你熟练掌握 Lua 循环,你就真正拥有了让程序“自动工作”的能力。不妨现在就动手写一个小程序,用循环计算 1 到 100 的和,或者实现一个简易的菜单系统——实践,是最好的老师。