Войти на сайт

Авторизация, ждите ...
×

ТЕМА: Неповторимый рандом

Неповторимый рандом 2 нед. 6 дн. назад #125204

  • DarchanKaen
  • DarchanKaen аватар
  • Вне сайта
  • Мастер
  • Сообщений: 192
  • Спасибо получено: 157
  • РазработчикПроект месяца 1 местоВетеран
Неповторимый рандом




Доброго времени суток!
Вероятно все вы знаете, что в RpgMaker есть переменные и возможность присваивать им случайное значение в некотором диапазоне.
Это бесспорно удобная функция, которую можно использовать для большого количества игровых ситуаций.

Но что делать, если нам нужно, чтобы все случайные значения были уникальными и не повторялись? Например, мы делает игру-викторину с уникальными вопросами или некий текстовой квест со случайными событиями, которые не должны повторяться. Конечно, можно стандартными средствами мейкера, переключателями и проверками условий, но это муторно в настройке и крайне неудобно, когда такого рандома должно быть больше 10 вариантов.

И тут на помощь нам приходит команда скрипт и тот факт, что в мейкере можно выполнять код на JavaScript; так как данный урок для MV (и MZ) в Ruby для Xp-Vx-Vx Ace, вероятно делается схожим подходом, но с другим синтаксисом.

Уточним условия примера. У нас игра-викторина, при которой 9 вопросов должны задаваться в любом порядке, но только по одному разу…то есть не повторяться (число вопросов может быть любым!).
Достигнуть подобного можно, храня перечень номеров вопросов в массиве, который будет хранится в определенной переменной мейкера и, после выбора случайного номера вопроса, данный номер будет удаляться из массива и отфильтровываться.

Для этого выполним несколько простых действий (номера переменных могут быть любыми):

1)В инициализирующем событии, в команде «Скрипт», напишем такой код:
let randomNumbersList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 
$gameVariables.setValue(1, randomNumbersList);

где:
«randomNumbersList» - массив с номерами вопросов;
«$gameVariables.setValue()» - сохранение массива в определенной переменной мейкера.

2)В событии, в котором мы выбираем номер, в команде «Скрипт», напишем такой код:
let randomNumbersList = $gameVariables.value(1);
 
let randomIndex = Math.floor( Math.random() * randomNumbersList.length ); 
let randomNumber = randomNumbersList[randomIndex];
$gameVariables.setValue(2, randomNumber);
 
delete randomNumbersList[randomIndex];
let uniqueRandomNumbersList = randomNumbersList.filter( elem => elem );
$gameVariables.setValue(1, uniqueRandomNumbersList);

где:
«$gameVariables.value()» - получение массива с номерами вопросов из переменной мейкера и сохранение его во временную переменную «randomNumbersList»;
«randomIndex» - получение случайного индекса массива, под которым хранится номер вопроса;
«randomNumber» - получение номера вопроса при помощи случайного индекса массива;
«$gameVariables.setValue()» - здесь это сохранение выбранного номера вопроса в определенной переменной мейкера;
«delete randomNumbersList[randomIndex]» - удаление номера вопроса, выбранного по случайному индексу, из массива с вопросами.

И вот тут важный момент! После удаления элементов, в массиве остаются пустые места. Поскольку мы не хотим для выбора вопроса вводить какие-то доп. проверки, нам нужно исключить из массива вопросов эти самые пустые места. Как? Фильтрацией, а именно:
«randomNumbersList.filter( elem => elem )»

Данный фрагмент кода возвращает массив с номерами вопросов, но уже без пустых мест. Ну и дальше мы привычным способом сохраняем его в переменную мейкера, причем в ту же, в какую писали при инициализации:
«$gameVariables.setValue»

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

Ну а сами номера вопросов в нужном событии мы используем в условии по переменной, в которой сохранили номер.

И с каждым вызовом скрипта из пункта №2 массив с вариантами ответов будет уменьшаться...пока не достигнет нуля и массив будет пустым, весь. Поэтому количество ответов / случайных событий / для чего вы это используете нужно контролировать, как минимум учитывая в отдельной переменной сколько раз этот рандом уже использовали (в нашем случае - сколько ответов уже дали).

Вот и все, спасибо за внимание!

P.S: допускаю, что такой урок уже был – но поиском я не нашел…в случае, если такое уже было – смело снимайте с конкурса.

update-1 от 10.11.2021
Спасибо Lekste, он напомнил, как важно правильно называть переменные.
Изменен код, в фильтрации "index" заменен на "elem", так как первая переменная фильтра - элемент массива.

И Lekste прав, есть еще один вариант кода фильтрации, без удаления элемента из массива, а именно:
randomNumbersList.filter( (elem, index) => index != randomIndex );
где
"elem" - элемент массива, первый параметр фильтра;
"index" - собственно индекс элемента;
в условии фильтрации указываются, что возвращаются все индексы, кроме равного случайно выбранному.
При использовании такого подхода удаление при помощи:

"delete randomNumbersList[randomIndex];"

уже не нужно!
Мои игры [ Нажмите, чтобы развернуть ]
Последнее редактирование: 2 нед. 5 дн. назад от DarchanKaen.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: Безликий, VeselyRodger, miller404, Alx_Yago, Братец Лис, SirAndriy, xrenj

Неповторимый рандом 2 нед. 6 дн. назад #125208

  • VeselyRodger
  • VeselyRodger аватар
  • Вне сайта
  • Светлый дракон
  • Сообщений: 831
  • Спасибо получено: 758
  • Проект месяца 1 местоПроект месяца 3 местоТестерОратор
Полезно
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DarchanKaen, SirAndriy

Неповторимый рандом 2 нед. 6 дн. назад #125209

  • xrenj
  • xrenj аватар
  • Вне сайта
  • Бывалый
  • Сообщений: 62
  • Спасибо получено: 82
  • Разработчик
Интересно было, о таком использовании рандома раньше не думал.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DarchanKaen

Неповторимый рандом 2 нед. 5 дн. назад #125214

  • alexgunwork
  • alexgunwork аватар
  • Вне сайта
  • Оседлый
  • Сообщений: 34
  • Спасибо получено: 57
  • Проект месяца 1 местоПроект месяца 2 местоКоммерсант
Вероятно все вы знаете, что в RpgMaker есть переменные и возможность присваивать им случайное значение в некотором диапазоне.
— а вот в этом месте поподробней. А как она работает?
Администратор запретил публиковать записи гостям.

Неповторимый рандом 2 нед. 5 дн. назад #125215

  • DarchanKaen
  • DarchanKaen аватар
  • Вне сайта
  • Мастер
  • Сообщений: 192
  • Спасибо получено: 157
  • РазработчикПроект месяца 1 местоВетеран
alexgunwork пишет:
Вероятно все вы знаете, что в RpgMaker есть переменные и возможность присваивать им случайное значение в некотором диапазоне.
— а вот в этом месте поподробней. А как она работает?


При вызове этой опции в переменную каждый раз заносится случайное значение из диапазона.
Мои игры [ Нажмите, чтобы развернуть ]
Последнее редактирование: 2 нед. 5 дн. назад от DarchanKaen.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: alexgunwork

Неповторимый рандом 2 нед. 5 дн. назад #125216

  • Lekste
  • Lekste аватар
  • Вне сайта
  • Светлый дракон
  • Сообщений: 904
  • Спасибо получено: 556
  • Программист JavaScript ВетеранОраторДаритель СтимкеяПрограммист Ruby
А зачем удалять и фильтровать, когда можно сразу отфильтровать по условию: index != randomIndex?
Последнее редактирование: 2 нед. 5 дн. назад от Lekste.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DarchanKaen, yuryol

Неповторимый рандом 2 нед. 5 дн. назад #125217

  • Alx_Yago
  • Alx_Yago аватар
  • Сейчас на сайте
  • Светлый дракон
  • Сообщений: 793
  • Спасибо получено: 1444
  • 3 местоРазработчикОратор3 место в Обучающем конкурсеПроект месяца 1 местоУчитель
Lekste пишет:
А зачем удалять и фильтровать, когда можно сразу отфильтровать по условию: index != randomIndex?

Разверните мысль. Как всё будет работать в этом случае?
Администратор запретил публиковать записи гостям.

Неповторимый рандом 2 нед. 5 дн. назад #125218

  • DarchanKaen
  • DarchanKaen аватар
  • Вне сайта
  • Мастер
  • Сообщений: 192
  • Спасибо получено: 157
  • РазработчикПроект месяца 1 местоВетеран
Lekste пишет:
А зачем удалять и фильтровать, когда можно сразу отфильтровать по условию: index != randomIndex?
Правильный вопрос.

Начнем с того, что я неверно назвал параметры в фильтре, ведь первый параметр (который по-умолчанию) не индекс - а сам элемент.
Индекс - второй параметр, опциональный. Используя его и такое условие действительно можно не удалять, а сразу фильтровать.

Такой код корректно работает и не требует предварительного удаления элемента:
randomNumbersList.filter( (elem, index) => index != randomIndex );

Добавил секцию update с примером кода и скорректировал название параметра фильтра в основной секции.
Спасибо за толчок в правильном направлении!
Мои игры [ Нажмите, чтобы развернуть ]
Последнее редактирование: 2 нед. 5 дн. назад от DarchanKaen.
Администратор запретил публиковать записи гостям.

Неповторимый рандом 2 нед. 3 дн. назад #125255

  • nirion
  • nirion аватар
  • Вне сайта
  • Бывалый
  • Сообщений: 70
  • Спасибо получено: 40
  • Проект месяца 3 место
Демку бы, а то у меня, много уточняющих вопросов.
Администратор запретил публиковать записи гостям.

Неповторимый рандом 2 нед. 3 дн. назад #125264

  • DarchanKaen
  • DarchanKaen аватар
  • Вне сайта
  • Мастер
  • Сообщений: 192
  • Спасибо получено: 157
  • РазработчикПроект месяца 1 местоВетеран
Вот демо для MV, проект нужно открыть редактором.
Самое интересное - в Общих событиях.

www.mediafire.com/file/0jpqxxj2pgo8nzu/D...dom_Demo_MV.zip/file

P.S:
Можно открыть и MZ, если подбросить в папку проекта файл game.rmmzproject, взятый из любого проекта MZ.
Мои игры [ Нажмите, чтобы развернуть ]
Последнее редактирование: 2 нед. 3 дн. назад от DarchanKaen.
Администратор запретил публиковать записи гостям.
Время создания страницы: 0.562 секунд