Алгоритм вычисления буквы Skill

Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Не разобрался, как мне лучше всего получить букву скилла.
Через свитч самый простой вариант для меня, но, как сказали, получим сотню if'ов

Допустим скил находится в iSkill, а буква в szSkillLevel
Код:
    [L- <   60]---------------------------
    [LS >=  60]    L group < 85
    [L+ >=  75]---------------------------
    [M- >=  85]---------------------------
    [MS >= 100]    M group < 130
    [M+ >= 115]---------------------------
    [H- >= 130]---------------------------
    [HS >= 140]    H group < 165
    [H+ >= 150]---------------------------
    [P- >= 165]---------------------------
    [PS >= 180]    P group < 210
    [P+ >= 195]---------------------------
    [G  >= 210]
iSkill = 145 допустим
szSkillLevel = ?
19 Мар 2019
Подкинули код, но я все ровно не понял =D
Код:
    if(skillPlayer >= 210 && skillAttacker < 210
    || skillPlayer >= 195 && skillAttacker < 195
    || skillPlayer >= 180 && skillAttacker < 180
    || skillPlayer >= 165 && skillAttacker < 165
    || skillPlayer >= 150 && skillAttacker < 150
    || skillPlayer >= 140 && skillAttacker < 140
    || skillPlayer >= 130 && skillAttacker < 130
    || skillPlayer >= 115 && skillAttacker < 115
    || skillPlayer >= 100 && skillAttacker < 100
    || skillPlayer >= 85 && skillAttacker < 85
    || skillPlayer >= 75 && skillAttacker < 75
    || skillPlayer >= 60 && skillAttacker < 60)
    {
        return HC_SUPERCEDE;
    }
    return HC_CONTINUE;
19 Мар 2019
В Statsx GUI нашел этот код, но это жутко, мне кажется.

Код:
    if ((formula >= SKILL_VALUE[0] && formula < SKILL_VALUE[1]) || !izStats[STATS_KILLS])
        copy(user_skill, charsmax(user_skill), "L-")
    else if (formula >= SKILL_VALUE[1] && formula < SKILL_VALUE[2])
        copy(user_skill, charsmax(user_skill), "L")
    else if (formula >= SKILL_VALUE[2] && formula < SKILL_VALUE[3])
        copy(user_skill, charsmax(user_skill), "L+")
    else if (formula >= SKILL_VALUE[3] && formula < SKILL_VALUE[4])
        copy(user_skill, charsmax(user_skill), "M-")
    else if (formula >= SKILL_VALUE[4] && formula < SKILL_VALUE[5])
        copy(user_skill, charsmax(user_skill), "M")
    else if (formula >= SKILL_VALUE[5] && formula < SKILL_VALUE[6])
        copy(user_skill, charsmax(user_skill), "M+")
    else if (formula >= SKILL_VALUE[6] && formula < SKILL_VALUE[7])
        copy(user_skill, charsmax(user_skill), "H-")
    else if (formula >= SKILL_VALUE[7] && formula < SKILL_VALUE[8])
        copy(user_skill, charsmax(user_skill), "H")
    else if (formula >= SKILL_VALUE[8] && formula < SKILL_VALUE[9])
        copy(user_skill, charsmax(user_skill), "H+")
    else if (formula >= SKILL_VALUE[9])
        copy(user_skill, charsmax(user_skill), "P")
    else
        copy(user_skill, charsmax(user_skill), "L-")
 
Сообщения
584
Реакции
1,006
Помог
18 раз(а)
Код:
enum SkillNames {
    SkillConst,
    Name[16]
}

new const info[][SkillNames] =  {
    { 210, "G" },
    { 195, "P+" },
    { 180, "PS" },
    { 165, "P-" },
    { 150, "H+" }
}

get_name(skill, name[], len)
{
    for(new i; i < sizeof(info); i++) {
        if(skill >= info[i][SkillConst]) {
            copy(name, len, info[i][Name])
            break;
        }
    }
}
 
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
UPD: новый алгоритм
Код:
#define MAX_SKILL_LENGTH 3

enum _:Skill {
    SkillNum,
    SkillName[MAX_SKILL_LENGTH]
}

new const SKILLS[][Skill] =  {
    { 0, "L-" },
    { 60, "LS" },
    { 75, "L+" },
    { 85, "M-" },
    { 100, "MS" },
    { 115, "M+" },
    { 130, "H-" },
    { 140, "HS" },
    { 150, "H+" },
    { 165, "P-" },
    { 180, "PS" },
    { 195, "P+" },
    { 210, "G" }
};

getSkillName(skill, name[], len) {
    new i = sizeof SKILLS;
    while (skill < SKILLS[i][SkillNum] && i > 0) { i--; }
    copy(name, len, SKILLS[i][SkillName]);
}
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Mistrick, fantom, спасибо, я просто думал, что возможно сразу обращаться к промежутку как-то, без прогона циклом по всему массиву.
 
Сообщения
219
Реакции
184
Помог
3 раз(а)
fantom, больше всего игроков будет со скилом от М до Н, поэтому профитнее идти от начала, а не с конца
 
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
gyxoBka, а еще лучше заюзать бинарный поиск. Не совсем бинарный, но примерно он и есть
 
Сообщения
219
Реакции
184
Помог
3 раз(а)
fantom, ну, можно в принципе вообще тупо индексировать(кэшировать) скил игрока и сверять больше ли он след порога
 
Сообщения
273
Реакции
424
Помог
5 раз(а)
Javekson, Я маленько не понял за что идёт борьба? За читаемость кода или за скорость? Можно вообще сделать массив на 211 элементов и вычислять букву всего с одним if например:
Код:
#define MAX_SKILL_LENGTH 3

enum _:Skill {
    SkillNum,
    SkillName[MAX_SKILL_LENGTH]
}

new const SKILLS[][Skill] =  {
    { 0, "L-" },
    { 1, "L-" },
    ...
    { 60, "LS" },
    { 61, "LS" },
    ...
    { 75, "L+" },
    { 76, "L+" },
    ...
    { 85, "M-" },
    { 86, "M-" },
    ...
    { 100, "MS" },
    { 101, "MS" },
    ...
    { 115, "M+" },
    { 116, "M+" },
    ...
    { 130, "H-" },
    { 131, "H-" },
    ...
    { 140, "HS" },
    { 141, "HS" },
    ...
    { 150, "H+" },
    { 151, "H+" },
    ...
    { 165, "P-" },
    { 166, "P-" },
    ...
    { 180, "PS" },
    { 181, "PS" },
    ...
    { 195, "P+" },
    { 196, "P+" },
    ...
    { 210, "G" }
};

getSkillName(skill, name[], len) {
    if(skill < 210)
        copy(name, len, SKILLS[skill][SkillName]);
    else
        copy(name, len, SKILLS[210][SkillName]);
}
Это всего лишь пример и его можно ещё оптимизировать.:smile3:
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
Я маленько не понял за что идёт борьба? За читаемость кода или за скорость?
Ни за то ни за другое, это лишь для общих знаний больше всего. Свои тараканы ))) Спасибо )
20 Мар 2019
Я немного тупенький, че ему нужно? )
На строчке client_print_color warning 213: tag mismatch

Код:
client_print_color(id, print_team_default, "Вы занимаете %d из %d (Убито %d. Смертей %d. В голову %d. Скилл %s (%.2f))",
    iRank, g_iSQLSize, g_eSQLData[id][PD_KILLS], g_eSQLData[id][PD_DEATHS],
    g_eSQLData[id][PD_HEAD], GetSkillName(g_eSQLData[id][PD_SKILL]), g_eSQLData[id][PD_SKILL]
);

GetSkillName(iSkill) {
    new sSkillName[SKILL_NAME_STRLEN];
    for(new i; i < sizeof(SKILL_NAMES); i++) {
        if(iSkill >= SKILL_NAMES[i][SN_SKILL]) {
            copy(sSkillName, charsmax(sSkillName), SKILL_NAMES[i][SN_SKILL_NAME]);
            break;
        }
    }
    return sSkillName;
}
20 Мар 2019
Ответ приходит верный
20 Мар 2019
Все, BlackSignature подсказал, глупая ошибка, отправлял int значение, хотя оно float было
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
fantom, почему? он требует что то вернуть мне
20 Мар 2019
Два часа потратил, что бы сообразить как картинки вставить... Продуктивность на высоте =(

2019-03-20_174632.png
 
Сообщения
1,304
Реакции
2,303
Помог
57 раз(а)
Javekson, у тебя GetSkillName() ещё где-то юзается? А то можно указателем работать

Код:
some_func() {	
	new iSkillNamePtr = GetSkillNamePtr(g_eSQLData[id][PD_SKILL])

	client_print_color(id, print_team_default, "Вы занимаете %d из %d (Убито %d. Смертей %d. В голову %d. Скилл %s (%.2f))",
		iRank, g_iSQLSize, g_eSQLData[id][PD_KILLS], g_eSQLData[id][PD_DEATHS],
		g_eSQLData[id][PD_HEAD], SKILL_NAMES[iSkillNamePtr][SN_SKILL_NAME], g_eSQLData[id][PD_SKILL]
	);
}

GetSkillNamePtr(Float:fSkill) {
	new i;
	
	for( ; i < sizeof(SKILL_NAMES); i++) {
		if(iSkill >= SKILL_NAMES[i][SN_SKILL]) {
			break;
		}
	}
	
	return i;
}
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
BlackSignature, используется, но не будет такой ситуации что указатель будет 0-2 и он выполнит мне PLUGIN_CONTINUE/PLUGIN_HANDLED/PLUGIN_HANDLED_MAIN и не вернет ничего а стопарнет плаг?
 
Сообщения
1,304
Реакции
2,303
Помог
57 раз(а)
Javekson, C какой стати он должен его стопорнуть? Тут в коде об этом ничего нет. Чтобы сказать точно, надо видеть весь код.
 
Сообщения
1,304
Реакции
2,303
Помог
57 раз(а)
Javekson,
Код:
new iSkillNamePtr = GetSkillNamePtr(g_eSQLData[id][PD_SKILL])
Ты не в ядро возвращаешь значение, а присваеваешь его переменной. Проблем не будет.
 
Сообщения
2,751
Реакции
3,017
Помог
61 раз(а)
BlackSignature, ну типа:
i = 0
return i; = return 0; = return PLUGIN_CONTINUE = Стоп
Вот этот вопрос наверное нужно объяснить подробнее человеку.
Там где используется функция, которая "что-то" возвращает - должно проверяться значение возврата.

В противном случае хоть return 133337, если он по коду не задействован - не будет ничего.

Коды возврата PLUGIN_* нужны для использования в форвардах (вызываемых ядром функйий) ядра.

И, у некоторых есть проверка принятого из AMXX значения. Об этом можно прочитать в документации.
21 Мар 2019
В amxx вообще плохо затронута тема возвращаемого значения.
Уже в sourcepawn приходится писать "осознанный" void перед началом объявления функйии
 
Сообщения
273
Реакции
424
Помог
5 раз(а)
Уже в sourcepawn приходится писать "осознанный" void перед началом объявления функйии
Вот это норм (не знал так как не юзал, не люблю source, какой-то он пластилиновый:smile3:), а то в pawn по сравнению с C и C++ как-то непривычно без указания возвращаемого типа. Вот на примере прекрасно объяснено, что PLUGIN_CONTINUE и т.д. влияют только на работу плагинов которые используют общедоступные для всех плагинов хуки и указывают ядру, что делать со следующим плагином в списке использующим один и тот же хук.
Пример
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу