Сложный(наверное) алгоритм рандомизации
| |
Black_Hawk1451
|
Дата: Воскресенье, 13.03.2016, 23:26:34 | Сообщение # 1 |
|
Сообщений: 11
Репутация: 0 [ +/- ]
|
|
Итак, представим что у меня есть 48 различных картинок. Среди этих 48 картинок существует 14 картинок в единичном экземпляре а остальные 17 повторяются только 1 раз(т.е. двойной экземпляр). Итого 14 + 17*2 = 48. При этом среди 14 картинок в единичном экземпляре существует еще 10 единичных VIP-картинок.
Далее, представим что у меня есть 10 телевизоров, среди которых есть один VIP-телевизор. И я хочу чтобы при старте карты происходил такой алгоритм: - в первом телевизоре отображается рандомная картинка из 48 оставшихся - во втором телевизоре отображается рандомная картинка из 47 оставшихся, при этом, она не должна повторяться с первой! - в третьем телевизоре отображается рандомная картинка из 46 оставшихся, при этом, она не должна повторяться с первой и второй! ...и так далее до десятого телевизора. - в десятом, VIP-телевизоре, может отобразиться только одна из 10 VIP-картинок, при этом она, конечно же, не должна повторяться с теми, которые уже могли появиться на предыдущих 9 телевизорах. То есть, должна быть реальна ситуация, когда на всех 9 обычных телевизорах появились VIP-картинки. Однако, повторяться не должен только порядковый номер каждой картинки. Те картинки, которые в двойном экземпляре, имеют бОльший шанс на появление на телевизоре и должны иметь возможность при проходе этого алгоритма появиться, например, на двух разных телевизорах.
Затем, у меня должна быть возможность один раз активировать второй триггер для каждого телевизора. Его алгоритм должен быть следующим(тут у меня 2 варианта):
I вариант: - На каждом телевизоре, кроме VIP, я могу нажать, например, на красную кнопку, и после нажатия картинка на этом телевизоре должна смениться на любую из оставшихся 28-38 картинок, так как 10 картинок уже были использованы в первом триггере и еще максимум 10 могут быть использованы. На VIP-телевизоре же кнопка должна выполнять ту же функцию, но выбирать только из оставшихся VIP-картинок(мог ошибиться в подсчетах на единичку, хочется спать, извиняйте )
II вариант: - На каждом телевизоре я могу нажать, например, на красную кнопку, и таким образом отметить все телевизоры, картинки на которых я хочу поменять. Затем нажать, например, на оранжевую кнопку(она одна) и после этого все картинки на отмеченных телевизорах сменятся на те, которые еще не были использованы.
Второй вариант мне кажется более геморным, поэтому я его не особо рассматриваю. Но, возможно, я ошибаюсь.
В общем, на форуме мапперов мне сказали, что сурс движок не очень хорошо ладит с использованием большого количества энтитей(а там по-другому никак :c) и посоветовали написать отдельный плагин под все это дело. Я подумал над этим и примерно набросал как это должно выглядеть:
1. Первым делом нужно объявить переменные из карты в самом плагине, а также привязать нажатия кнопок и мб что-то еще. 2. Затем, мне нужна такая функция, которая из 48 чисел(от 1 до 48 включительно) выберет 9 штук без повторений. Не знаю, реально ли такое в языке SourcePawn, но раз в редакторе карт такая возможность есть, то скорее всего и в языке должна быть. 3. Когда выбралось какое-то число, то передавать на карту в нужные энтити(через targetname) 2 значения: - номер попытки(от 1 до 9) - число, которое выбралось рандомно и без повторений(от 1 до 48, ноль учитывать не нужно) 4. Еще должен быть случайный выбор из 10 VIP-картинок, без повторений. Кстати, скорее всего именно его нужно провести первым и затем как-то передать полученное число в функцию из пункта 2, чтобы это же число не могло быть выбрано, т.е VIP-картинка никак не повторится. Опять же не знаю, возможно ли это или нет. 5. Теперь к функции перевыбора. Она должна быть привязана к 10 кнопкам. 6. При нажатии на любую не VIP-кнопку, она должна передавать на карту в нужную энтити: - новое рандомное число(все также без повторений) Передавать номер попытки уже не стоит, так как это будет делать своя собственная кнопка на каждом телевизоре. 7. При нажатии на VIP-кнопку происходить должно все то же самое, только новое рандомное число выбирается уже как минимум из 9 вариантов и, конечно же, не должно быть повторений.
Заранее выложу список энтитей, используемых в этом плагине: 10 штук func_wall - телевизоры, каждый со своим именем, начиная с televisor[1,2,3...10]. 10 штук func_button - кнопки на телевизорах, каждая со своим именем, but[1,2,3...10] 10 штук env_texturetoggle - энтити, отвечающие за смену текстуры на другую. Каждая со своим именем, texture[1,2,3...10] 9 штук math_counter - энтити, отвечающие за выбор правильного телевизора при первом проходе алгоритма рандома. В них передаются попытки. Для VIP-телевизора такая не нужна, потому что он всего лишь один, и работает, по сути, по другому алгоритму рандома. counter[1,2,3...9]. Последние, теоретически, можно убрать если в самый первый проход рандома добавить такую вещь, что выбранное число будет по очереди для каждой texture[1,2,3...10] именно в самом плагине активировать команду SetTextureIndex [число]. Опять же не знаю насколько реально через плагины активировать команды из редактора карт.
Я честно не знаю насколько муторный должен получиться плагин, мб кто-то тут подобные за пять минут пишет. Тем не менее, я не прошу Вас написать его за меня, мне просто нужны подсказки, мб примеры плагинов с исходниками, где подобный алгоритм уже был реализован и т.д. Если нужен будет исходник карты, то могу кинуть чуть позже. В данный момент он немного не соответствует тому, о чем я написал выше. Заранее очень благодарен за любую помощь!
Сообщение отредактировал Black_Hawk1451 - Понедельник, 14.03.2016, 00:37:37 |
|
| |
barcelona58341
|
Дата: Понедельник, 14.03.2016, 10:23:00 | Сообщение # 2 |
|
Сообщений: 18
Репутация: 0 [ +/- ]
|
|
Цитата Заранее выложу список энтитей, используемых в этом плагине: Реализация, можно сделать но по другими функциями без некоторых энтитей, а подобный плагин наверно нету
|
|
| |
BarD
|
Дата: Понедельник, 14.03.2016, 12:51:57 | Сообщение # 3 |
|
Сообщений: 943
Репутация: 137 [ +/- ]
|
|
Не очень понял, что тебе нужно. Попробуй затолкать в массив все картинки и отсортируй через
Код SortIntegers(array[], array_size, Sort_Random); Затем выцепляй по одной. Гарантированно будет без повторений.
Сообщение отредактировал BarD - Понедельник, 14.03.2016, 12:52:17 |
|
| |
_wS_
|
Дата: Понедельник, 14.03.2016, 13:40:09 | Сообщение # 4 |
|
Цитата BarD ( ) Не очень понял, что тебе нужно +1, как-то запутан(н?)о. Говоришь что одни картинки повторяются, другие нет, но на каждом телевизоре должна быть уникальная картинка без повторений, зачем тогда инфа о том что какие-то повторяются, а какие-то нет? Исходя из того что я понял, вот пару строк кода:
Код // Текущая картинка на телевизоре new Handle:g_hCurrentTvImageAr;
// Номера картинок new Handle:g_hImageAr;
public OnPlubinStart() { decl i;
// по умолчанию у каждого телевизора (от 1 до 10) картинка отключена (0) g_hCurrentTvImageAr = CreateArray(1); for (i = 1; i < 11; i++) PushArrayCell(g_hCurrentTvImageAr, 0);
// номера картинок от 1 до 48 (вип картинки от 1 до 10) g_hImageAr = CreateArray(1); for (i = 1; i < 49; i++) PushArrayCell(g_hImageAr, i); }
// Меняем картинку (на телевизорах всегда разные картинки) // Tv - номер телевизора от 1 до 10 stock wS_SetRandomTvImage(Tv) { decl image; new max = Tv == 10 ? 10 : 48;
new Handle:hAr = CreateArray(1); for (new i = 0; i < max; i++) { image = GetArrayCell(g_hImageAr, i); if (FindValueInArray(g_hCurrentTvImageAr, image) < 0) { PushArrayCell(hAr, image); } } image = GetArrayCell(hAr, GetRandomInt(0, GetArraySize(hAr) - 1)); CloseHandle(hAr);
SetArrayCell(g_hCurrentTvImageAr, --Tv, image);
SetVariantInt(image); AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex");
-- вместо AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex"); можно попробовать так:
decl String:info[65]; new entity = CreateEntityByName("info_target"); FormatEx(info, 65, "env_texturetoggle_%d,SetTextureIndex,%d,0,1", Tv, image); DispatchKeyValue(entity, "OnUser1", info); AcceptEntityInput(entity, "FireUser1"); AcceptEntityInput(entity, "Kill"); -- }
|
|
| |
Black_Hawk1451
|
Дата: Понедельник, 14.03.2016, 15:28:24 | Сообщение # 5 |
|
Сообщений: 11
Репутация: 0 [ +/- ]
|
|
Цитата _wS_ ( ) +1, как-то запутан(н?)о. Говоришь что одни картинки повторяются, другие нет, но на каждом телевизоре должна быть уникальная картинка без повторений, зачем тогда инфа о том что какие-то повторяются, а какие-то нет? Исходя из того что я понял, вот пару строк кода:
Сорри если запутал, просто считал должным донести эту информацию. Еще раз более подробно объясню: Всего 31 картинка, из них: 14 - в единичном экземпляре, среди которых 10 являются VIP-картинками 17 - в двойном экземпляре. Каждой картинке присвоен свой порядковый номер, в том числе и двойным, именно из-за этого условия общее количество возможных картинок вырастает до 48. Надеюсь, сейчас стало более понятно.
_wS_, по коду есть несколько вопросов: 1. Я не много не понял в каком месте я должен подставить имена своих энтитей в код, чтобы плагин работал корректно.
2. Не понял вот эту строку:
Код // номера картинок от 1 до 48 (вип картинки от 1 до 10) g_hImageAr = CreateArray(1); for (i = 1; i < 49; i++) PushArrayCell(g_hImageAr, i); То есть для этого кода я должен буду заранее обозначить все вип картинки под порядковыми номерами от 1 до 10?
3. По поводу этой строки:
Код // по умолчанию у каждого телевизора (от 1 до 10) картинка отключена (0) g_hCurrentTvImageAr = CreateArray(1); for (i = 1; i < 11; i++) PushArrayCell(g_hCurrentTvImageAr, 0); А есть ли в ней смысл? Если я заранее на карте могу сделать так, что картинки будут отключены.
4. Вот в этой функции очень много непонятных для меня вещей, был бы признателен если бы Вы смогли оставить хотя бы комментарий рядом с каждой строчкой:
Код stock wS_SetRandomTvImage(Tv) { decl image; new max = Tv == 10 ? 10 : 48;
new Handle:hAr = CreateArray(1); for (new i = 0; i < max; i++) { image = GetArrayCell(g_hImageAr, i); if (FindValueInArray(g_hCurrentTvImageAr, image) < 0) { PushArrayCell(hAr, image); } } image = GetRandomInt(0, GetArraySize(hAr) - 1); CloseHandle(hAr);
SetArrayCell(g_hCurrentTvImageAr, --Tv, image);
SetVariantInt(image); AcceptEntityInput(env_texturetoggle_ENTITY_INDEX, "SetTextureIndex");
Пока попробую сам разобраться в Вашем коде, но, чувствую, это будет ооочень долго :<
|
|
| |
|