LUA:通过变量查找特定表



我目前正在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(坐标的反向查找从一个房间移动到另一个房间。有人对如何制作一个更灵活的系统有任何想法,该系统可以通过玩家输入其中一个变量来找到表格?提前感谢!

-区块链搬运工

这并没有直接回答你的问题,但我认为它会达到你正在尝试做的事情的目的。 我创建了一个名为"战利品"的表格,可以容纳许多物品,玩家可以通过输入名称将其中任何一个放入他们的"袋子"中。

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

请注意,与print不同,此函数不会自动将换行符附加到输出字符串;为此,请记住将n放在fmt字符串的末尾。

接下来,定义一个帮助程序函数可能会很有用,该函数调用io.read("*l")以获取整行输入。在编写一些示例代码来帮助回答您的问题时,我将我的函数称为getline- 就像具有类似行为的C++函数一样 - 并像这样定义它:

local function getline()
local read = tostring(io.read("*l"))
return read
end

如果我正确理解您要做什么,玩家将拥有一个物品栏 - 您bag称之为 - 他可以通过在stdin中输入物品名称来将物品放入其中。因此,例如,如果玩家发现一个装有黄金、一把剑和药水的宝箱,并且他想拿走金币,他会Gold输入stdin,然后它将被放入他的物品栏中。

根据您目前所拥有的内容,您似乎正在使用Lua表来创建这些项目:每个表都有一个name索引,另一个称为ap;并且,如果玩家的文本输入与项目的名称匹配,则玩家会拾取该项目。

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

----------------
-- 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。

#!/usr/bin/lua
-------------
-- Modules --
-------------
local Item = assert(require("Item"))
local function eprintf(fmt, ...)
io.stderr:write(string.format(fmt, ...))
return
end
local function printf(fmt, ...)
io.stdout:write(string.format(fmt, ...))
return
end
local function getline()
local read = tostring(io.read("*l"))
return read
end
local function main(argc, argv)
local gold = Item.new("Gold", 3)
printf("gold.name = %sngold.ap = %in", gold.name, gold.ap)
return 0
end
main(#arg, arg)

现在,至于你描述的反向搜索,此时你应该做的只是根据Item的名称检查用户的输入。这是在主函数中:

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

我希望这有帮助!

最新更新