LUA:通过变量查找特定表
我现在开始在Lua中开发一个文本冒险游戏——没有插件,我的第一个项目就是纯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
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范围;我只是为了反映问题中使用的语法而忽略了这一点