LUA:通过其变量查找特定的 table
LUA: Looking for a specific table by its variable
我目前正在 Lua 开始开发一款文字冒险游戏 -- 没有插件,只是 Lua 我的第一个项目。本质上,这是我的问题; 我正在尝试找出如何使用其中一个变量对 table 执行 "reverse lookup"。 这是我尝试过的示例做:
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) 坐标进行反向查找来查找房间。任何人都对如何制作一个更灵活的系统有任何想法,该系统可以通过玩家输入其中一个变量来找到 table 吗?提前致谢!
-区块链搬运工
这并没有直接回答您提出的问题,但我认为它可以满足您的目的。我创建了一个名为 'loot' 的 table,它可以容纳许多对象,玩家可以通过输入名称将其中任何一个放入 'bag' 中。
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
对于奖励积分,您可以检查 'bag' 以查看玩家是否已经拥有该物品,然后只需更新数量...
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
同样,这不是您要求的 'reverse lookup' 解决方案...但我认为它更接近于让用户选择掠夺某些东西来尝试做的事情。
我的免责声明是我在自己的 lua 用法中没有使用 IO 函数,因此我必须假设您的 x = io.read("*l") 是正确的。
PS。如果您只希望对象具有名称和数量,而不需要任何其他属性(如条件、附魔或其他),那么您还可以使用 key/val 对来简化我的解决方案:
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
。因此,例如,如果玩家发现一个装有金子、一把剑和一瓶药水的宝箱,并且他想拿走金子,他会在 stdin
中输入 Gold
然后它会被放置在他的库存中。
根据您目前的情况,您似乎正在使用 Lua table 来创建这些项目:每个 table 都有一个 name
索引,并且另一个叫 ap
;并且,如果玩家的文本输入与物品的名称匹配,则玩家会拾取该物品。
我建议创建一个 Item
class,您可以通过将它放在自己的脚本中然后根据需要使用 require
加载它来很好地抽象它。这是一个非常基础的 Item
class 模块 我写的:
----------------
-- 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 = %s\ngold.ap = %i\n", 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
希望对您有所帮助!
我目前正在 Lua 开始开发一款文字冒险游戏 -- 没有插件,只是 Lua 我的第一个项目。本质上,这是我的问题; 我正在尝试找出如何使用其中一个变量对 table 执行 "reverse lookup"。 这是我尝试过的示例做:
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) 坐标进行反向查找来查找房间。任何人都对如何制作一个更灵活的系统有任何想法,该系统可以通过玩家输入其中一个变量来找到 table 吗?提前致谢!
-区块链搬运工
这并没有直接回答您提出的问题,但我认为它可以满足您的目的。我创建了一个名为 'loot' 的 table,它可以容纳许多对象,玩家可以通过输入名称将其中任何一个放入 'bag' 中。
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
对于奖励积分,您可以检查 'bag' 以查看玩家是否已经拥有该物品,然后只需更新数量...
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
同样,这不是您要求的 'reverse lookup' 解决方案...但我认为它更接近于让用户选择掠夺某些东西来尝试做的事情。
我的免责声明是我在自己的 lua 用法中没有使用 IO 函数,因此我必须假设您的 x = io.read("*l") 是正确的。
PS。如果您只希望对象具有名称和数量,而不需要任何其他属性(如条件、附魔或其他),那么您还可以使用 key/val 对来简化我的解决方案:
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
。因此,例如,如果玩家发现一个装有金子、一把剑和一瓶药水的宝箱,并且他想拿走金子,他会在 stdin
中输入 Gold
然后它会被放置在他的库存中。
根据您目前的情况,您似乎正在使用 Lua table 来创建这些项目:每个 table 都有一个 name
索引,并且另一个叫 ap
;并且,如果玩家的文本输入与物品的名称匹配,则玩家会拾取该物品。
我建议创建一个 Item
class,您可以通过将它放在自己的脚本中然后根据需要使用 require
加载它来很好地抽象它。这是一个非常基础的 Item
class 模块 我写的:
----------------
-- 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 = %s\ngold.ap = %i\n", 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
希望对您有所帮助!