LUA:通过变量查找特定表

LUA:通过变量查找特定表,lua,inventory,items,take,Lua,Inventory,Items,Take,我现在开始在Lua中开发一个文本冒险游戏——没有插件,我的第一个项目就是纯Lua。本质上,这是我的问题我正在尝试找出如何使用表的一个变量对表进行“反向查找”。以下是我尝试执行的一个示例: print("What are you trying to take?") bag = {} gold = {name="Gold",ap=3} x = io.read("*l") if x == "Gold" then table.insert(bag,gold) print("You t

我现在开始在Lua中开发一个文本冒险游戏——没有插件,我的第一个项目就是纯Lua。本质上,这是我的问题我正在尝试找出如何使用表的一个变量对表进行“反向查找”。以下是我尝试执行的一个示例:

print("What are you trying to take?")
bag = {}
gold = {name="Gold",ap=3}
x = io.read("*l")
if x == "Gold" then
     table.insert(bag,gold)
     print("You took the " .. gold.name .. ".")
end
显然,用游戏中的每一个物体写一行这样的文字是非常。。。让人筋疲力尽——特别是因为我认为我不仅可以使用这个解决方案获取项目,还可以使用每个房间(x,y)坐标的反向查找从一个房间移动到另一个房间。有人对如何制作一个更灵活的系统有什么想法吗?这个系统可以通过玩家输入一个变量来查找表格?提前谢谢


-blockchainporter

这并不能直接回答您提出的问题,但我认为这将有助于实现您的目标。我创建了一个名为“战利品”的表格,它可以容纳许多物品,玩家可以通过键入名称将这些物品中的任何一个放在他们的“包”中

bag = {}
loot = {
    {name="Gold", qty=3},
    {name="Axe", qty=1},
}

print("What are you trying to take?")
x = io.read("*l")
i = 1
while loot[i] do
    if (x == loot[i].name) then
        table.insert(bag, table.remove(loot,i))
    else
        i = i + 1
    end
end
对于奖励积分,你可以检查“袋子”,看看玩家是否已经有一些物品,然后只更新数量

while loot[i] do
    if (x == loot[i].name) then
        j, found = 1, nil
        while bag[j] do
            if (x == bag[j].name) then
                found = true
                bag[j].qty = bag[j].qty + loot[i].qty
                table.remove(loot,i)
            end
            j = j + 1
        end
        if (not found) then
            table.insert(bag, table.remove(loot,i))
        end
    else
        i = i + 1
    end
end
再说一次,这不是您要求的“反向查找”解决方案。。。但我认为它更接近于你试图通过让用户选择掠夺东西来实现的目的

我的免责声明是,我在自己的lua使用中没有使用IO函数,因此我必须假设您的x=IO.read(“*l”)是正确的


注:如果您只希望对象具有名称和数量,而不希望对象具有任何其他属性(如条件、附魔或其他),那么您也可以通过使用键/值对简化我的解决方案:

bag = {}
loot = { ["Gold"] = 3, ["Axe"] = 1 }

print("What are you trying to take?")
x = io.read("*l")
for name, qty in pairs(loot) do
    if x == name then
        bag.name = (bag.name or 0) + qty
        loot.name = nil
    end
end

在我具体回答你的问题之前,我有一些笔记要开始。(我只是想在我忘记之前做这件事,所以请容忍我!)

我建议使用
stderr
而不是
stdout
打印到终端——Lua功能
print
使用后者。在编写Lua脚本时,我经常创建一个名为
eprintf
的C风格函数,将格式化输出打印到
stderr
。我是这样实现的:

local function eprintf(fmt, ...)
    io.stderr:write(string.format(fmt, ...))
    return
end
local function getline()
    local read = tostring(io.read("*l"))
    return read
end
请注意,与打印不同,此函数不会自动向输出字符串追加换行符;为此,请记住将
\n
放在
fmt
字符串的末尾

接下来,定义一个helper函数可能很有用,该函数调用
io.read(“*l”)
,以获取整行输入。在编写一些示例代码来帮助回答您的问题时,我调用了我的函数<代码> GETLeIO<代码>——类似于具有类似行为的C++函数——并定义如下:

local function eprintf(fmt, ...)
    io.stderr:write(string.format(fmt, ...))
    return
end
local function getline()
    local read = tostring(io.read("*l"))
    return read
end
如果我正确理解了你要做的事情,玩家将拥有一个清单——你称之为
——他可以通过在
stdin
中输入物品名称将物品放入其中。因此,例如,如果玩家发现一个装有黄金、剑和药剂的宝箱,他想拿走黄金,他会在
stdin
中键入
gold
,并将其放入他的库存中

根据目前的情况,您似乎正在使用Lua表来创建这些项:每个表都有一个
名称
索引和另一个名为
ap
;而且,如果玩家的文本输入与某个项目的名称匹配,则该玩家将拾取该项目

我建议创建一个
Item
类,您可以通过将它放在自己的脚本中,然后根据需要使用
require
加载它来很好地抽象它。这是我写的一个非常基本的
项目
类模块:

----------------
-- Item class --
----------------
local Item = {__name = "Item"}
Item.__metatable = "metatable"
Item.__index = Item

-- __newindex metamethod.
function Item.__newindex(self, k, v)
    local err = string.format(
        "type `Item` does not have member `%s`",
        tostring(k)
    )
    return error(err, 2)
end

-- Item constructor
function Item.new(name_in, ap_in)
    assert((name_in ~= nil) and (ap_in ~= nil))
    local self = {
        name = name_in,
        ap = ap_in
    }
    return setmetatable(self, Item)
end

return Item
在此基础上,我编写了一个主驱动程序来封装您在问题中描述的一些行为。(是的,我知道我的Lua代码看起来更像C。)

现在,对于您描述的反向搜索,此时您需要做的就是对照
项的名称检查用户的输入。这是它的主要功能:

local function main(argc, argv)
    local gold = Item.new("Gold", 3)
    local bag = {}
    eprintf("What are you trying to take? ")
    local input = getline()
    if (input == gold.name) then
        table.insert(bag, gold)
        eprintf("You took the %s.\n", gold.name)
    else
        eprintf("Unrecognized item `%s`.\n", input)
    end
    return 0
end

我希望这有帮助

我建议在函数、循环体等内部将变量声明为
local
。@人物完全同意local范围;我只是为了反映问题中使用的语法而忽略了这一点