XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Результаты опроса: Какая функция оптимальнее?
Изначальная функция 4 57.14%
Альтернативная функция 1 14.29%
Без разницы которую использовать 2 28.57%
Голосовавшие: 7. Вы еще не голосовали в этом опросе

Ответ
 
silumin

offline
Опыт: 11,153
Активность:
Брудворк с массивами... (попытка приделать 5е колесо)
По сабжу: пока использую перебор индексов массивов при поиске свободной ячейки. Последее время в голове летает мысль о некоторой несостоятельности функции перебора, из-за чего появился альтернативный вариант. Что выбрать, я не знаю. Все свои мысли изложу кодом, а вы, участники форума, помогайте, но только с комментами.

Изначальная функция:Функция перебирает массив ключей, пока ключ не будет = true. После чего ключ фальсится (ячейка занимается) и возвращается индекс. Всё просто до предела.
Код:
function GetEmptyDynSlot takes nothing returns integer
local integer i = 0
  loop
    exitwhen udg_DYN_Key[i] //=== udg_DYN_Key[i] - boolean type
    set i = i + 1
  endloop
  set udg_DYN_Key[i] = false
return i
endfunction


Альтернативная функция:Функция тоже перебирает массив ключей, но не с нуля, а со значения хранящегося в переменной udg_SaveIndex. Немного отягощён цикл - добавлена проверка.
Код:
function GetEmptyDynSlot takes nothing returns integer
local integer i = udg_SaveIndex
  loop
    exitwhen udg_DYN_Key[i]
    set i = i + 1
    if i==100 then
      set i = 0
    endif
  endloop
  set udg_DYN_Key[i] = false
  set udg_SaveIndex = i + 1
return i
endfunction

Собственно различия минимальны, но существенны с точки зрения поиска.

п.с. Убедительная просьба отвечать по сабжу и не критиковать само использование брудворка.

Отредактировано silumin, 04.10.2010 в 15:46.
Старый 04.10.2010, 14:08
Clamp
Lost in space
offline
Опыт: 71,158
Активность:
Зависит от того, может ли у тебя любая случайная ячейка принимать значение истины и от чего это зависит.
Если может, то первый вариант оптимальнее.
Старый 04.10.2010, 14:32
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
Я это давно уже решил(но придумал не совсем я) то что ты спрашиваешь.
Щас в кратце объясню:
Нужен второй массив (по умолчанию все ячейки равны 0) для хранения индексов свободных ячеек в твоем массиве и целочисленная переменная в которой записано кол-во использованых ячеек.
Когда нужен номер свободной ячейки то прибавляем к целочисленной 1 и обращаемся ко второму массиву под индексом целочисленной переменной,
ЕСЛИ в этой ячейке хранится 0, то присваиваем этой ячейке номер самой целочисленной и это будет номер свободного индекса,
ИНАЧЕ - номер свободной ячейки равен хранившемуся в нем числу, тогда это будет номером свободного индекса.
Когда ячейка освобождается, то мы нааборот записываем номер освободившейся ячейки в массив под индексом целочисленной и уменьшаем целочисленную на 1.
Вот держи пример:
Создается футман и ему присваивается CustomValue, когда он умирает его CV сохраняется в массив и при следующем создании юнита ему будет присвоен CV из массива.
Система создавалась для моих тригерных спеллов, но я перешел на Хендлы поэтому тут GUI вперемешку с JASS.
Работает безотказно. Тут нет абсолютно никаких переборов/циклов. Можешь проверить мои пред-пред последние спеллы.
В массиве юнитов записываются юниты под их CV чтобы было удобно к ним обращаться зная CV юнита.
Прикрепленные файлы
Тип файла: w3x CustomValue.w3x (17.6 Кбайт, 13 просмотров )

Отредактировано Zanozus, 04.10.2010 в 15:10.
Старый 04.10.2010, 14:56
Clamp
Lost in space
offline
Опыт: 71,158
Активность:
Zanozus, ужас, столько кода и лишних переменных вместо 9 строк...
Старый 04.10.2010, 15:00
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
И где ты тут лишние переменные увидел ? Массив и целочисленная да и кода почти нет.
(ты хоть пример смотрел?)
Массив юнитов можно удалить он для спеллов.
проще этого уже не придумуать:
globals
integer array A [1000]
integer I
endglobals

function GetFreeIndex takes nothing returns integer
set I = I+1
if A[I]==0 then
 set A[I]=I
 return I
else
 return A[I]
endif
endfunction

function SaveFreeIndex takes integer i returns nothing
set A[I]=i
set I = I-1
endfunction

Отредактировано Zanozus, 04.10.2010 в 15:34.
Старый 04.10.2010, 15:22
silumin

offline
Опыт: 11,153
Активность:
Clamp, всё под триггерные спеллы, которые в своём большинстве занимают ячейку на 3-20 сек. Есть и висяки по 60-180 сек. Ячейки освобождаются как попадёт.

Zanozus, спасибо, но тогда уже проще применить альтернативную функцию, ведь перебор в ней, я так думаю, будет от 0 до 10 циклов, учитывая специфику спеллов.

silumin добавил:
Zanozus, темболее параллельных массивов у меня за 15 штук...
Старый 04.10.2010, 15:28
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
от 0 до 10 циклов это много особенно для MUI.
Для паралельных не нужно для каждого писать ты ведь в них под одним индексом сохраняешь.

Отредактировано Zanozus, 04.10.2010 в 16:06.
Старый 04.10.2010, 15:29
Clamp
Lost in space
offline
Опыт: 71,158
Активность:
silumin, короче юзай первый вариант и не приделывай пятые/десятые колёса
Старый 04.10.2010, 15:30
ScorpioT1000
Работаем
offline
Опыт: отключен
Вы забыли реализовать операцию удаления объекта из любого места в массиве. А ведь это часто пригоджается и считается правилом хорошего тона - очищать память при выходе.
Старый 04.10.2010, 15:33
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
function DeleteObject takes integer i returns nothing
set B[i]=0 //или null
set C[i]=0 //или null
call SaveFreeIndex(i)
endfunction
где B,C - паралельный массив из которого ты удаляешь объект
и одновременно сохраняется освободившийся индекс.

Отредактировано Zanozus, 04.10.2010 в 15:56.
Старый 04.10.2010, 15:44
Elf_Stratigo

offline
Опыт: 4,699
Активность:
silumin:
loop
exitwhen udg_DYN_Key[i]
set i = i + 1
if i==100 then
set i = 0
endif
endloop
вечный цикл если всё занято?!
очевидно первая функция работает быстрее ибо меньше одним сравнением
Старый 04.10.2010, 20:00
silumin

offline
Опыт: 11,153
Активность:
Elf_Stratigo, не успеют игроки накастовать столько спеллов, чтобы занять все 100 ячеек.
Цитата:
Сообщение от Elf_Stratigo
очевидно первая функция работает быстрее ибо меньше одним сравнением
или вторая ибо не стартует каждый раз с нуля и не сталкивает все ячейки в кучу.

silumin добавил:
ScorpioT1000, я не совсем тебя понял. Если ты про очистку ячеек (аналог дестракта структуры), то такая функция есть.

silumin добавил:
Цитата:
Сообщение от Zanozus
от 0 до 10 циклов это много особенно для MUI
да ну... Это может и много, но не таких "содержательных" как у меня.
Старый 04.10.2010, 21:18
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
смотря как часто ты перебирать будешь, если пару раз за игру при касте спелла то да,
а если в периодическом таймере с малым периодом и по 10 и более раз + несколько игроков то ничего хорошего...
короче выбирай сам.
Старый 04.10.2010, 22:03
silumin

offline
Опыт: 11,153
Активность:
Zanozus, это только поиск свободных ячеек, а получение индекса ячеек при работе спелла происходит через хеш. Не знаю как остальные делают триггерные спеллы на парал-ных массивах, но поиск свободной ячейки происходит только при активации спелла.
Старый 04.10.2010, 22:36
DioD

offline
Опыт: 45,134
Активность:
вот вам убертрушная функция выделения ячеек из массива, да так, чтобы всегда было известно какие ячейки заняты, а какие свободны
library Pool

globals
    hashtable     HASH = InitHashtable()
    integer array VALUES
    real    array WEIGHT_META
    integer array META
endglobals

function POOL_NEW takes nothing returns integer
    local integer I = META[0]
    
    if I > 0 then
        set META[0] = META[META[0]]
    else
        if I == -64 then
            return F_NULL
        endif
        set META[0] = META[0] - 1
        set I = -META[0]
    endif
    
    set META[I] = -1
    return I
endfunction

function POOL_REM takes integer I returns nothing
    if META[I] != -1 then
        return
    endif
    set META[I] = META[0]
    set META[0] = I
    set META[127*I - 63 + 1] = 0
    set META[127*I - 63 + 2] = 0
endfunction

function POOL_ADD_INT takes integer POOL, integer VALUE, real WEIGHT returns nothing
    local integer TMP
    
    if META[POOL] != -1 or META[127*POOL -63 +1] == 127 then
        return
    endif
    
    set TMP = LoadInteger(HASH, POOL, VALUE)
    if TMP == 0 then
        set META[127*POOL -63 +1] = META[127*POOL -63 +1] +1
        set TMP    = 128*(POOL-1) + META[127*POOL -63 +1]
        call SaveInteger(HASH, POOL, VALUE, TMP)
        set VALUES[TMP] = VALUE
    endif
    if WEIGHT <= 0.0 then
        set META[127*POOL -63 +2] = 1
        return
    endif
    set WEIGHT_META[128*(POOL-1)] = WEIGHT_META[128*(POOL-1)] +WEIGHT -WEIGHT_META[TMP]
    set WEIGHT_META[TMP] = WEIGHT    
    
endfunction

function POOL_REM_INT takes integer POOL, integer VALUE returns nothing
    
    local integer I = LoadInteger(HASH, POOL, VALUE)
    
    if I == 0 then
        return
    endif
    
    call RemoveSavedInteger(HASH, POOL, VALUE)    
    set WEIGHT_META[128*(POOL-1)] = WEIGHT_META[128*(POOL-1)] -WEIGHT_META[I]
    
    set VALUES[I]                 =      VALUES[128*(POOL-1) +META[127*POOL -63 +1]]
    set WEIGHT_META[I]            = WEIGHT_META[128*(POOL-1) +META[127*POOL -63 +1]]
    
    call SaveInteger(HASH,POOL,VALUES[I],I)
    set META[127*POOL -63 +1] = META[127*POOL -63 +1] - 1
    
endfunction

function POOL_REM_LST takes integer POOL returns integer
    
    if META[127*POOL -63 +1] == 0 then
        return F_NULL
    endif
        
    call RemoveSavedInteger(HASH, POOL, VALUES[META[127*POOL -63 +1] +128*(POOL-1)])
    
    set WEIGHT_META[128*(POOL-1)] = WEIGHT_META[128*(POOL-1)] -WEIGHT_META[META[127*POOL -63 +1] +128*(POOL-1)]
    set META[127*POOL -63 +1] = META[127*POOL -63 +1] - 1
    
    return VALUES[META[127*POOL -63 +1] + 128*(POOL-1) + 1]
        
endfunction 

function POOL_RND_INT takes integer POOL returns integer
    local real    RANDOM = 0
    local integer OFFSET = 128*(POOL-1)
    
    if META[127*POOL -63 +1] == 0 then
        return F_NULL
    endif
    
    if META[127*POOL - 63 + 2] != 0 then
        set OFFSET = GetRandomInt(1,META[127*POOL -63 +1]) + OFFSET
        return VALUES[OFFSET]
    else
        set RANDOM = GetRandomReal(0,WEIGHT_META[OFFSET])
        loop
            set OFFSET = OFFSET + 1
            set RANDOM = RANDOM - WEIGHT_META[OFFSET]
            exitwhen RANDOM <= 0
        endloop
        
        return VALUES[OFFSET]
    endif
    
endfunction

function POOL_COPY takes integer POOL returns integer
    local integer A = POOL_NEW()
    local integer B = META[127*POOL - 63 + 1]
    
    if META[POOL] != -1 or A == F_NULL then
        return F_NULL
    endif
    
    set META[127*A - 63 + 2]   = META[127*POOL - 63 + 2]
    set WEIGHT_META[128*(A-1)] = WEIGHT_META[128*(POOL-1)]
    set META[127*A - 63 + 1]   = META[127*POOL - 63 + 1]
    
    loop
        set VALUES     [128*(A-1) + B] = VALUES     [128*(POOL-1) + B]
        set WEIGHT_META[128*(A-1) + B] = WEIGHT_META[128*(POOL-1) + B]
        call SaveInteger(HASH, A, VALUES[128*(POOL-1) + B], 128*(A-1) + B)
        set B = B - 1
        exitwhen B == 0
    endloop
    
    return A
    
endfunction

function VALUE_WEIGHT takes integer POOL, integer VALUE returns real
    return WEIGHT_META[LoadInteger(HASH, POOL, VALUE)]
endfunction

function VALUE_CHANCE takes integer POOL, integer VALUE returns real
    if WEIGHT_META[128*(POOL-1)] > 0. then
        return WEIGHT_META[LoadInteger(HASH, POOL, VALUE)]/WEIGHT_META[128*(POOL-1)]
    endif
    return 0.
endfunction

endlibrary
Если будете читать, сможете увидеть, что выделяются суб массивы в 62 слота каждый, ведётся список всех массивов что были выделены, для каждого массива ведётся список занятых и свободных слотов, если сделать ограничение на один массив в 8190 ячеек, будет один больной массив со списком занятых и свободных слотов, таблица сделана линкованная как в FAT почти.
код писал сам, но давно, версия без накруток не сохранилась, вернее надо искать, перепелить не проблема.

Отредактировано agentex, 05.10.2010 в 17:28.
Старый 05.10.2010, 16:50
silumin

offline
Опыт: 11,153
Активность:
DioD, применять на практике для 100 ячеек, имхо, глупее некуда. Но выпендрёж засчитан! =С
Старый 05.10.2010, 17:02
Zanozus
Уехал учиться
offline
Опыт: 8,512
Активность:
И куда такой убертрушный комбайн ?
И вобще я не понимаю, автор просил системку для определения свободной ячейки из массива.
Я её выложил. Вызвал первую функцию она тебе свободную ячейку из массива\паралельных массивов
вызвал третью функцию (та которая в 10-ом посте) - освободил ячейку.
без всяких циклов, сложных вычислений и других заморочек.
Что еще надо ?
Старый 05.10.2010, 18:24
DioD

offline
Опыт: 45,134
Активность:
чтобы определять заранее без циклов свободную ячейку, нужно вести список этих самых свободных ячеек.
function POOL_NEW takes nothing returns integer
    local integer I = META[0]
    
    if I > 0 then
        set META[0] = META[META[0]]
    else
        if I == -8190 then
            return 453245
        endif
        set META[0] = META[0] - 1
        set I = -META[0]
    endif
    
    set META[I] = -1
    return I
endfunction

function POOL_REM takes integer I returns nothing
    if META[I] != -1 then
        return
    endif
    set META[I] = META[0]
    set META[0] = I
endfunction
Вот эти две функции, первая метит ячейку как занятую, вторая метит ячейку как свободную, при желании докручиваем таблицу разметки и можно делать циклы только по занятым слотам.
то что я выложил даёт реальную возможность иметь массивы дата[62][62] что очень и очень неплохо для решения всевозможных проблем, все метаданные хранятся в самом массиве, отлично накручивается безопасность, так как сбить метаданные и карта загибается по неочевидным причинам.
Старый 05.10.2010, 20:54
silumin

offline
Опыт: 11,153
Активность:
Цитата:
Сообщение от Zanozus
автор просил системку для определения свободной ячейки из массива
автор просил сравнить 2 функции на предмет оптимального поиска свободно ячйки.

DioD, заканчивай флудить, мне не нужны твои тонны кода.
Старый 06.10.2010, 09:37
DioD

offline
Опыт: 45,134
Активность:
я вам говорю что обе функции фуфло и это делается БЕЗ циклов, обе функции фундаментально неверные.
Старый 07.10.2010, 10:58
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 12:25.