2014-12-13 2 views
2

Я пытался найти более умный способ решить эту проблему.Петля до тех пор, пока в таблице не будет найдено 2 конкретных значения?

Это отрывок из кода, связанный с игрой, то петли корыта каждого паза каждого рюкзака до тех пор пока он находит лопату и веревку

local continue 
local foundShovel, foundRope 
     for i = 0, Container.GetLast():Index() do -- looping trough backpacks 
     local cont = Container(i) 
      for j = 0, cont:ItemCount()-1 do -- looping trough each slot 
      local id = cont:GetItemData(j).id -- Getting ID of that slot 
      foundShovel, foundRope = GetToolIndex(id,0) or foundShovel,GetToolIndex(id,1) or foundRope -- confusing... 
       if foundShovel and foundRope then 
        continue = true 
        break 
       end 
      end 
      if continue then 
       -- do something i need to do 
      end 
     end 
    end 
-- Switches ID to corresponding index : 
function GetToolIndex(id,retrn) 
    local shovel = { 
    [9598] = 4 , -- whacking driller of fate 
    [9599]= 4 , -- whacking driller of fate(jammed) 
    [9596]= 3 , -- squeezing gear of girlpower 
    [9597]= 3 , -- squeezing gear of girlpower(jammed) 
    [9594]= 2 , -- sneaky stabber of elitenesss 
    [9595]= 2 , -- sneaky stabber of elitenesss(jammed) 
    [5710]= 1, -- light shovel 
    [3457] = 0 -- shovel 
    } 
    local rope = { 
    [646]= 1, -- elvenhair rope 
    [3003] = 0, -- rope 
    [9598] = 4 , -- whacking driller of fate 
    [9599]= 4 , -- whacking driller of fate(jammed) 
    [9596]= 3 , -- squeezing gear of girlpower 
    [9597]= 3 , -- squeezing gear of girlpower(jammed) 
    [9594]= 2 , -- sneaky stabber of elitenesss 
    [9595]= 2 -- sneaky stabber of elitenesss(jammed) 
    } 
    if retrn == 0 then 
     return shovel[id] 
    elseif return == 1 then 
     retrn rope[id] 
    end 
end 

Но это не работает, и я думал, там должен быть лучшим способом для этого подхода, что, если мне нужно найти значения X в таблице вместо двух? Надеюсь, моя проблема может быть понята здесь.

+0

Я удивлен, что 'если возвращение == 0 'Безразлично Не вызывать ошибку. – greatwolf

+0

он делает, мой плохой – Mojimi

+0

Можете ли вы подтвердить, как игра индексирует вещи на самом деле на основе 0, а не на 1? – greatwolf

ответ

3

Ну, хранение всех данных в таблицах намного лучше, чем вызов функции для получения данных контейнеров.

В любом случае, вот скрипт, который получит все рюкзаки id, сохранит их в таблице, а затем просто вызовет функцию с каждым идентификатором.

Backpack = {data = {}}; 
function Backpack:update(refresh) 
    if(#self.data==0 or refresh) then 
     for i = 0, Container.GetLast():Index() do 
      local cont = Container(i); 
      for j = 0,cont:ItemCount()-1 do 
       --table.insert(self.data,cont:GetItemData(j).id) 
       self.data[#self.data+1] = cont:GetItemData(j).id; -- faster than table.insert 
      end 
     end 
    end 
end 
function Backpack:refresh() 
    self:update(true) 
end 
function Backpack:find(func,...) -- func should return a value if id is good, otherwise false, add extra args to call with the function 
    if (not func) then 
     return false; 
    end 
    self:update(); -- Incase there is no inventory data; 
    for key,value in pairs(self.data) do 
     local value = func(value,...); -- calls the function with the id (as first parameter) of the 'cached' user inventory 
     if (value) then 
      return value 
     end 
    end 
    return false; 
end 

Пример:

function GetToolIndex(id,return) 
    local shovel = { 
    [9598] = 4 , -- whacking driller of fate 
    [9599]= 4 , -- whacking driller of fate(jammed) 
    [9596]= 3 , -- squeezing gear of girlpower 
    [9597]= 3 , -- squeezing gear of girlpower(jammed) 
    [9594]= 2 , -- sneaky stabber of elitenesss 
    [9595]= 2 , -- sneaky stabber of elitenesss(jammed) 
    [5710]= 1, -- light shovel 
    [3457] = 0 -- shovel 
    } 
    local rope = { 
    [646]= 1, -- elvenhair rope 
    [3003] = 0, -- rope 
    [9598] = 4 , -- whacking driller of fate 
    [9599]= 4 , -- whacking driller of fate(jammed) 
    [9596]= 3 , -- squeezing gear of girlpower 
    [9597]= 3 , -- squeezing gear of girlpower(jammed) 
    [9594]= 2 , -- sneaky stabber of elitenesss 
    [9595]= 2 -- sneaky stabber of elitenesss(jammed) 
    } 
    if return == 0 then 
     return shovel[id] 
    elseif return == 1 then 
     return rope[id] 
    end 
end 

function Test() 
    local shovel,rope = Backpack:find(GetToolIndex,0),Backpack:find(GetToolIndex,1) 
    if (shovel and rope) then 
     print("Shovel and rope exist"); 
    end 
end 
Test(); 

EDIT:

Подумав некоторое время, вы, кажется, пытаются проверить, если пользователь имеет этот конкретный идентификатор.

Вот еще один метод, который будет проверять все данные пользовательского рюкзака (поиск глубоких таблиц), он будет искать на основе табличного или табличного значения, он также будет работать на вложенных таблицах, это должно сделать вас хорошим.

Backpack = {data = {}}; 
function Backpack:update(refresh) 
    if(#self.data==0 or refresh) then 
     for i = 0, Container.GetLast():Index() do 
      local cont = Container(i); 
      for j = 0,cont:ItemCount()-1 do 
       local data = cont:GetItemData(j); -- pretty sure this returns a table 
       self.data[data.id] = data; -- self.data[9598] = {...} 
      end 
     end 
    end 
end 
function Backpack:refresh() 
    self:update(true) 
end 
function Backpack:MultiTableSearch(input,value,case,index_check) 
    if (input and type(input) == 'table') then 
     if (type(value) == 'table' and value == input) then 
      return true; 
     end 
     for key,object in pairs(input) do 
      if (index_check) then 
       if (case and type(input)=='string' and type(key)=='string') then 
        if (value:lower() == key:lower()) then -- to avoid exit the loop 
         return true; 
        end 
       else 
        if (key == value) then 
         return true 
        elseif(type(object)=='table') then 
         return self:MultiTableSearch(object,value,case,index_check) 
        end 
       end 
      else 
       if (case and type(value)=='string' and type(object) == 'string') then 
        if (value:lower() == object:lower()) then 
         return true; 
        end 
       elseif(type(object)=='table') then 
        if (value == object) then 
         return true; 
        else 
         return self:MultiTableSearch(object,value,case) 
        end 
       else 
        if (object == value) then 
         return true; 
        end 
       end 
      end 
     end 
    end 
    return false; 
end 
function Backpack:exists(value,case,index_check) 
    self:update(); 
    return self:MultiTableSearch(self.data,value,case,index_check) 
end 
-- checks the value 9598, case-insensitive is set to false, 
-- index_checking is set to true (checks table index --> Backpack.data[9598], if it was set it'll return true); 
if (Backpack:exists(9598,false,true)) then 
    print("User has whacking driller of fate"); 
end 
if (Backpack:exists("Shovel of doom")) then -- will try to find any table-value that has the of "Shovel of doom" (case-sensitive) 
    print("User Shovel of doom"); 
end 

Если вы беспокоитесь о выполнении MultiTableSearch (потому что это выглядит немного тяжеловато), это довольно быстро, провел несколько тестов.

Функция

function MultiTableSearch(input,value,case,index_check) 
    if (input and type(input) == 'table') then 
     if (type(value) == 'table' and value == input) then 
      return true; 
     end 
     for key,object in pairs(input) do 
      if (index_check) then 
       if (case and type(input)=='string' and type(key)=='string') then 
        if (value:lower() == key:lower()) then -- to avoid exit the loop 
         return true; 
        end 
       else 
        if (key == value) then 
         return true 
        elseif(type(object)=='table') then 
         return MultiTableSearch(object,value,case,index_check) 
        end 
       end 
      else 
       if (case and type(value)=='string' and type(object) == 'string') then 
        if (value:lower() == object:lower()) then 
         return true; 
        end 
       elseif(type(object)=='table') then 
        if (value == object) then 
         return true; 
        else 
         return MultiTableSearch(object,value,case) 
        end 
       else 
        if (object == value) then 
         return true; 
        end 
       end 
      end 
     end 
    end 
    return false; 
end 

Тесты (добавляющим значения в таблицу и сканирование вложенных таблиц, оба теста в размерах нонсенс таблицы)

local start_time = os.clock(); 
t = {} 
for i=1,500000 do --500k table size 
    t[i]=i-1 
end 
print(os.clock()-start_time) -- 0.05 sec to create the table 
local start_time = os.clock(); 
print(tostring(MultiTableSearch(t,500000,false)))-- will try to find a key with the value of 500,000 
print(os.clock()-start_time) -- 0.197sec sec to scan the whole table 

function nestedTable(object,times) -- creates nested table -> object={{{{..n times}}}} 
    if (times > 0) then 
     object[#object+1] = {times = times} 
     return (nestedTable(object[#object],times-1)) 
    end 
end 
local start_time = os.clock(); 
t = {}; 
nestedTable(t,15000) --> will create table inside a table x 15000 times. 
print(os.clock()-start_time) -- 0.007 sec to create the nested table 
local start_time = os.clock(); 
print(tostring(MultiTableSearch(t,1,false)))-- will try to find a 1 (as a table value), the very last table value 
print(os.clock()-start_time) -- 0.014 sec to find the value in the nested table 
+0

. Я не делал этого так, потому что я хотел остановиться на случай, если я их найду, избегая ненужных действий. – Mojimi

+0

@mojimi, «возвращаемое значение» выйдет из цикла, лучше обрабатывать элементы в массивах (таблицах), они быстрей, так или иначе я написал другой метод. – das

Смежные вопросы