- Сообщений: 257
- Спасибо получено: 234
Неповторимый рандом
Доброго времени суток!
Вероятно все вы знаете, что в RpgMaker есть переменные и возможность присваивать им случайное значение в некотором диапазоне.
Это бесспорно удобная функция, которую можно использовать для большого количества игровых ситуаций.
Но что делать, если нам нужно, чтобы все случайные значения были уникальными и не повторялись? Например, мы делает игру-викторину с уникальными вопросами или некий текстовой квест со случайными событиями, которые не должны повторяться. Конечно, можно стандартными средствами мейкера, переключателями и проверками условий, но это муторно в настройке и крайне неудобно, когда такого рандома должно быть больше 10 вариантов.
И тут на помощь нам приходит команда скрипт и тот факт, что в мейкере можно выполнять код на JavaScript; так как данный урок для MV (и MZ) в Ruby для Xp-Vx-Vx Ace, вероятно делается схожим подходом, но с другим синтаксисом.
Уточним условия примера. У нас игра-викторина, при которой 9 вопросов должны задаваться в любом порядке, но только по одному разу…то есть не повторяться (число вопросов может быть любым!).
Достигнуть подобного можно, храня перечень номеров вопросов в массиве, который будет хранится в определенной переменной мейкера и, после выбора случайного номера вопроса, данный номер будет удаляться из массива и отфильтровываться.
Для этого выполним несколько простых действий (номера переменных могут быть любыми):
1)В инициализирующем событии, в команде «Скрипт», напишем такой код:
где:
«randomNumbersList» - массив с номерами вопросов;
«$gameVariables.setValue()» - сохранение массива в определенной переменной мейкера.
2)В событии, в котором мы выбираем номер, в команде «Скрипт», напишем такой код:
где:
«$gameVariables.value()» - получение массива с номерами вопросов из переменной мейкера и сохранение его во временную переменную «randomNumbersList»;
«randomIndex» - получение случайного индекса массива, под которым хранится номер вопроса;
«randomNumber» - получение номера вопроса при помощи случайного индекса массива;
«$gameVariables.setValue()» - здесь это сохранение выбранного номера вопроса в определенной переменной мейкера;
«delete randomNumbersList[randomIndex]» - удаление номера вопроса, выбранного по случайному индексу, из массива с вопросами.
И вот тут важный момент! После удаления элементов, в массиве остаются пустые места. Поскольку мы не хотим для выбора вопроса вводить какие-то доп. проверки, нам нужно исключить из массива вопросов эти самые пустые места. Как? Фильтрацией, а именно:
Данный фрагмент кода возвращает массив с номерами вопросов, но уже без пустых мест. Ну и дальше мы привычным способом сохраняем его в переменную мейкера, причем в ту же, в какую писали при инициализации:
Как видите, несколько строчек кода позволяет удобным способом сделать нам рандом неповторимым и уникальным.
Ну а сами номера вопросов в нужном событии мы используем в условии по переменной, в которой сохранили номер.
И с каждым вызовом скрипта из пункта №2 массив с вариантами ответов будет уменьшаться...пока не достигнет нуля и массив будет пустым, весь. Поэтому количество ответов / случайных событий / для чего вы это используете нужно контролировать, как минимум учитывая в отдельной переменной сколько раз этот рандом уже использовали (в нашем случае - сколько ответов уже дали).
Вот и все, спасибо за внимание!
P.S: допускаю, что такой урок уже был – но поиском я не нашел…в случае, если такое уже было – смело снимайте с конкурса.
update-1 от 10.11.2021
Спасибо Lekste, он напомнил, как важно правильно называть переменные.
Изменен код, в фильтрации "index" заменен на "elem", так как первая переменная фильтра - элемент массива.
И Lekste прав, есть еще один вариант кода фильтрации, без удаления элемента из массива, а именно:
"elem" - элемент массива, первый параметр фильтра;
"index" - собственно индекс элемента;
в условии фильтрации указываются, что возвращаются все индексы, кроме равного случайно выбранному.
При использовании такого подхода удаление при помощи:
"delete randomNumbersList[randomIndex];"
уже не нужно!
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Мои проекты:
rpgmakerunion.ru/user/veselyrodger
Мой канал на Ютубе:
youtube.com/channel/UCyttExMfXo8ke_PhQjNPyuw
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
— а вот в этом месте поподробней. А как она работает?
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
alexgunwork пишет: Вероятно все вы знаете, что в RpgMaker есть переменные и возможность присваивать им случайное значение в некотором диапазоне.
— а вот в этом месте поподробней. А как она работает?
При вызове этой опции в переменную каждый раз заносится случайное значение из диапазона.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Lekste пишет: А зачем удалять и фильтровать, когда можно сразу отфильтровать по условию: index != randomIndex?
Разверните мысль. Как всё будет работать в этом случае?
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Правильный вопрос.Lekste пишет: А зачем удалять и фильтровать, когда можно сразу отфильтровать по условию: index != randomIndex?
Начнем с того, что я неверно назвал параметры в фильтре, ведь первый параметр (который по-умолчанию) не индекс - а сам элемент.
Индекс - второй параметр, опциональный. Используя его и такое условие действительно можно не удалять, а сразу фильтровать.
Такой код корректно работает и не требует предварительного удаления элемента:
Добавил секцию update с примером кода и скорректировал название параметра фильтра в основной секции.
Спасибо за толчок в правильном направлении!
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Самое интересное - в Общих событиях.
www.mediafire.com/file/0jpqxxj2pgo8nzu/D...dom_Demo_MV.zip/file
P.S:
Можно открыть и MZ, если подбросить в папку проекта файл game.rmmzproject, взятый из любого проекта MZ.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
xrenj пишет: Снова вернулся к этому уроку, задумавшись (возможно, тупой будет вопрос), а возможно ли создать 2 (или более) таких массива для двух или более разных событий? Просто копированием и изменением переменных явно дело не решилось, потому что рандом тут же перестаёт быть рандомом - второе событие повторяет полностью последовательность ответов за первым. А до больше, увы, пока ума не хватает.
скорее всего надо изменить название у переменной randomNumbersList , например на randomNumbersList_2
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
В первом эвента ("установочном"):
Во втором эвенте (перед выбором):
В результате в переменной №1 хранится первый массив вариантов ("A"), в переменной №2 - случайный выбор из них.
И в переменной №21 хранится второй массив вариантов ("B"), в переменной №22 - случайный выбор из второго массива.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
- Sleeping Visitor
-
- Не в сети
- Бывалый
-
- Сообщений: 80
- Спасибо получено: 31
Можно сделать очень простую систему.
Пишем генерацию рандома для викторины:
Принцип почти как в костыле с метками .
Создаём отдельные условия не связанные друг с другом (это для будующих вопросов), в условиях указываем требование - нужное вам число рандомящейся переменной "victorina" (в каждом отдельном условии должны быть разные числа).
В каждом условии, создаём ещё одно условие с проверкой на выключенный переключатель этого вопроса из викторины. Внутри этого условия пишем включение собственного переключателя вопроса, а затем и сам вопрос, после ответа на который начисляем очки, какие вы сами захотите, за верные и нет, ответы.
После каждого такого вопроса начисляем в новую переменную, пусть будет названа "victorina_number" по +1 - это будет счётчик заданных вопросов!
В условии с переключателем вопроса ставим галочку на "ИНАЧЕ", на случай если переключатель вопроса включён.
В "ИНАЧЕ" пишем переход к метке "vic_start".
Когда кончатся все ваши условия с вопросами, под ними (снаружи условий, последним действием) ставим переход к метке "vic_start".
Между меткой "vic-start" и рандомящейся переменной "victorina" ставим условие на проверку переменной "victorina_number", проверям если эта переменная равна количеству необходимых вопросов, которые "событие" должно задать игроку, то перебрасываем локальным переключателем "событие" на следующую страницу.
Как это в теории должно работать:
- Проверяется генерирующееся число в условии с вопросами, а затем проверяется переключатель, задавался ли вопрос раньше. Если число совпадает, а переключатель включён (вопрос задан) - игра перебросит нас к началу "события", где число в рандомной переменной зарандомится заново и цикл пойдёт сначала, так до тех пор пока не выпадет вопрос, который ещё не был задан.
- Как только нужное количество вопросов будет задано - игра перебросит нас на следующую страницу "события".
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
