You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua表格单选逻辑异常:ComputerCraft商店NPC仅首个选项生效

问题:ComputerCraft商店NPC选项选择逻辑异常

我在Minecraft的ComputerCraft模组里开发商店NPC功能,当前函数传入三个选项,但只有第一个选项能正确终止循环。我需要实现两次选择同一选项才确认的防误触逻辑,但目前仅有第一个选项能正常更新状态。

原代码如下:

function UTOptions(opt)
    local FR = 0
    local max = 14
    local w,h = term.getSize()
    local check = {}
    while true do
        for i,v in ipairs(opt) do
            if(string.len(v)>max) then
                error("Option is too long.")
            end
            if (FR == 0) then
                check[i] = 0
            end
            term.setCursorPos(w-15,i+2)
            if (check[i]== 1) then
                term.setTextColor(colors.red)
                write("*")
                term.setTextColor(colors.white)
                write(v)
            else
                write("*"..v)
            end
        end
        local event, side, mx, my = os.pullEvent("monitor_touch")
        if (check[my-2] == 0) then
            check[my-2] = 1
            for i,v in ipairs(check) do
                if (v ~= my-2) then
                    check[i] = 0
                end
            end
        elseif (check[my-2]==1) then
            return my-2
        end
        FR = 1
    end
end

我尝试修改触摸事件中的my偏移值(比如改成my-3或my-4),但只能改变生效的选项,其余选项仍无法更新。我怀疑问题出在这段代码:

for i,v in ipairs(check) do
    if (v ~= my-2) then
        check[i] = 0
    end
end

问题分析与修复

你找的问题点完全正确:这段循环的逻辑错误。check数组存储的是每个选项的选中状态(0未选中,1已选中),但你把数组的值v和选项索引my-2做对比,这逻辑完全不成立——v是0或1,而my-2是1、2、3这类索引值,所以条件判断完全错位,根本没起到重置其他选项的作用。

正确的逻辑是:遍历每个选项索引i,如果i不等于当前选中的选项索引my-2,就把check[i]设为0。另外还要补充清屏重绘的逻辑,否则旧的显示内容会残留,导致视觉上状态没更新。

修正后的代码:

function UTOptions(opt)
    local max = 14
    local w,h = term.getSize()
    local check = {}
    -- 初始化所有选项为未选中状态
    for i in ipairs(opt) do
        check[i] = 0
    end

    while true do
        -- 清除选项区域的旧内容,避免残留
        term.setCursorPos(w-15, 3)
        for _ in ipairs(opt) do
            write(string.rep(" ", 15)) -- 覆盖原位置内容
            term.setCursorPos(w-15, term.getCursorY() + 1)
        end

        -- 重绘所有选项
        for i,v in ipairs(opt) do
            if(string.len(v)>max) then
                error("Option is too long.")
            end
            term.setCursorPos(w-15, i+2)
            if check[i] == 1 then
                term.setTextColor(colors.red)
                write("*")
                term.setTextColor(colors.white)
                write(v)
            else
                write("*"..v)
            end
        end

        local event, side, mx, my = os.pullEvent("monitor_touch")
        local selectedIdx = my - 2
        -- 检查索引是否在有效范围内
        if selectedIdx < 1 or selectedIdx > #opt then
            goto continue -- 点击了选项外的区域,跳过处理
        end

        if check[selectedIdx] == 0 then
            -- 第一次选择,标记为选中,重置其他选项
            check[selectedIdx] = 1
            for i in ipairs(check) do
                if i ~= selectedIdx then
                    check[i] = 0
                end
            end
        else
            -- 第二次选择同一选项,确认并返回索引
            return selectedIdx
        end
        ::continue::
    end
end

关键修改点

  • 提前初始化check数组,去掉不必要的FR变量
  • 每次循环先清除选项区域的旧内容,避免显示残留
  • 修正重置其他选项的循环逻辑:对比索引i而非数组值v
  • 添加索引有效性检查,防止点击选项外区域导致报错
  • 使用goto跳过无效点击的处理逻辑,代码更清晰

内容的提问来源于stack exchange,提问作者CrimboJimbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 22:22:50