| 
 
 
	
		
		
			| Сложный(наверное) алгоритм рандомизации |  |  |  | 
| 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");
 Пока попробую сам разобраться в Вашем коде, но, чувствую, это будет ооочень долго :<
 |  |  |  |  |  
 |