这篇主要根据MeoHero项目简单介绍Lua的循环和流程控制。

  1. if条件语句

    -- 基本if语句
    if hero:is_alive() then
     hero:add_buff('无敌')
    end
    
    -- if-else语句
    if damage > 100 then
     print("高伤害")
    else 
     print("低伤害")
    end
    
    -- if-elseif-else语句
    if level < 6 then
     skill = "普通技能"
    elseif level < 11 then
     skill = "终极技能"
    else
     skill = "特殊技能"
    end

参考代码:

function self.main()
    --注册英雄
    ac.game:event '玩家-注册英雄' (function(self, player, hero)
        --英雄死亡后复活
        hero:event '单位-死亡' (function()
            local lv = hero:get_level()
            local player = hero:get_owner()
            -- if-then结构
            if not self:is_ability_enable() and hero:get_owner() == ac.player.self then
                jass.ForceUICancel()
            end
            
            local time = math.floor(5 + lv * lv * 0.077)
            player:sendMsg(('你将在 |cffffff00%d|r 秒后复活'):format(time))        
        end)
    end)
end
  1. for循环

a) 数值for循环:

-- 基本for循环
for i = 1, 10 do
    print(i)  -- 打印1到10
end

-- 带步长的for循环
for i = 0, 100, 25 do 
    print(i)  -- 打印0,25,50,75,100
end

-- 倒计时循环
for i = 10, 1, -1 do
    print(i)  -- 打印10到1
end

参考代码:

for i = 1, 16 do
    local p = ac.player(i)
    p.ability_list = {}
    if i <= 10 then
        p.ability_list['英雄'] = {size = 4}
        p.ability_list['学习'] = {size = 4}
        p.ability_list['智能施法'] = {size = 4}
        for x = 1, p.ability_list['英雄'].size do
            p.ability_list['英雄'][x] = ('A0%d%d'):format(i - 1, x - 1)
        end
    end
end

b) 泛型for循环:

-- 遍历表
local heroes = {'小悟空', '惠惠', '雷姆'}
for index, name in ipairs(heroes) do
    print(index, name)
end

-- 遍历字典
local hero_data = {
    name = "小悟空",
    hp = 1000,
    mp = 500
}
for key, value in pairs(hero_data) do
    print(key, value)
end

参考代码:

-- 遍历属性
for k, v in pairs(hero_data.attribute) do
    u:set(k, v)
end
  1. while循环

    -- while循环
    local hp = 100
    while hp > 0 do
     hp = hp - 10
    end
    
    -- 死循环(需要内部有break条件)
    while true do
     if game_over then
         break
     end
     update_game()
    end

参考代码:

local times = 0
--开启计时器,等待同步完成
ac.loop(100,
    function(t)
        while not self:is_player() do
            sync.using[index] = nil
            t:remove()
            if func then
                func(false)
            end
        end
    end
)
  1. repeat-until循环

    -- 至少执行一次的循环
    local count = 0
    repeat
     count = count + 1
     print(count)
    until count >= 10
  2. 循环控制语句
-- break: 跳出循环
for i = 1, 100 do
    if i > 50 then
        break  -- 到50就结束循环
    end
end

-- continue的替代方法(Lua没有continue)
for i = 1, 10 do
    if i % 2 == 0 then
        goto continue  -- 跳过偶数
    end
    print(i)
    ::continue::
end
  1. 多重返回和多重赋值

    -- 多重返回
    function get_hero_info()
     return "小悟空", 100, 500
    end
    
    -- 多重赋值
    local name, hp, mp = get_hero_info()

参考代码:

function mt:get_point()
    return self.point or self:get_position()
end
  1. 错误处理

    -- pcall安全调用
    local success, result = pcall(function()
     -- 可能出错的代码
     return dangerous_function()
    end)
    
    if not success then
     print("发生错误:", result)
    end
    
    -- xpcall带错误处理
    xpcall(function()
     -- 危险代码
    end, function(err)
     -- 错误处理
     print("错误:", err)
     print(debug.traceback())
    end)

参考代码:

--错误汇报
function runtime.error_handle(msg)
    base.error_handle(msg)
end

重要提示:

  1. 选择合适的循环方式

    • 明确循环次数用for
    • 不明确循环次数用while
    • 至少执行一次用repeat-until
  2. 循环性能考虑

    • 避免在循环中创建新的局部变量
    • 尽可能使用break提前退出
    • 大循环考虑使用协程分帧处理
  3. 代码可读性

    • 适当的缩进
    • 清晰的循环变量命名
    • 必要的注释说明循环目的
  4. 错误处理

    • 关键操作使用pcall/xpcall
    • 合理使用错误处理机制
    • 记录必要的错误日志