Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 08.10.2018, 10:20
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 1  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
По умолчанию Вероятностный расчёт

Друзья, у меня в разработке игры пришло время добавить чуточку рандома. По этому поводу хочу вас спросить, возможно у кого-нибудь есть готовое решение, которым можно поделиться и не изобретать велосипед. Задач две. Во-первых, зная вероятность наступления события, получать значение типа "истина-ложь". Во-вторых, имея несколько событий с разной вероятностью, определить то из них, которое произойдёт.

А если ничего подобного не найдётся, то буду признателен за рекомендации, как реализовать. Пока единственный способ, который мне приходит в голову, выглядит примерно так. Если у нас есть событие, которое должно произойти с вероятностью 0.7, то мы будем генерировать псевдослучайное число в интервале от 0 до 1 и возвращать true, если оно окажется больше 0.3, т.к. (1-0.7).

Примерно так же и с числами: генерировать случайные числа в диапазоне от 0 до значения вероятности каждого и выбирать событие с наибольшим значением.

Корректно?
__________________
Не сломано - не чини!

Старый 08.10.2018, 23:25
Godwarlock вне форума Посмотреть профиль Отправить личное сообщение для Godwarlock Найти все сообщения от Godwarlock
  № 2  
Ответить с цитированием
Godwarlock

Регистрация: Jan 2012
Сообщений: 836
Цитата:
public static Boolean getChance(float percent)
{
Boolean percent_result = Math.random()<(percent/100);

return percent_result;
}
Вот тебе расчет вероятности, но тут код Jav-ы. Думаю сможешь адаптировать по as3

Старый 09.10.2018, 09:57
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 3  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Godwarlock, спасибо. Примерно то же, но лаконичнее.

Забавно, но мне почему-то казалось, что это какая-то такая сложная конструкция должна быть непременно.
__________________
Не сломано - не чини!

Старый 09.10.2018, 13:20
Tails вне форума Посмотреть профиль Отправить личное сообщение для Tails Найти все сообщения от Tails
  № 4  
Ответить с цитированием
Tails
 
Аватар для Tails

блогер
Регистрация: Dec 2008
Адрес: г. Чебоксары
Сообщений: 2,259
Записей в блоге: 6
Цитата:
Сообщение от Appleman Посмотреть сообщение
Зная вероятность наступления события, получать значение типа "истина-ложь".
Код AS3:
var chance:Number = 0.1; // 10%
var result:Boolean = Math.random() > chance;
Цитата:
Сообщение от Appleman Посмотреть сообщение
Имея несколько событий с разной вероятностью, определить то из них, которое произойдёт.
Когда-то делал нечто подобное. Суть в том, чтоб сложить все id и их вероятность в список, а затем случайно выбирать их оттуда:
Код AS3:
var events:RangeArray = new RangeArray();
 
events.setRange(1, 10); // Событие 1, шанс 10
events.setRange(2, 50); // Событие 2, шанс 50
events.setRange(3, 80); // Событие 3, шанс 80
 
trace(events.getItemByRangeIndex(Math.random() * events.summ)); // Случайное событие.
Код AS3:
package volkov.collection
{
 
	/**
	 * Массив с доступов по диапазону значений.
	 * Позволяет обращаться к элементам массива по диапазону индексов.
	 * @author Roman A.V.
	 */
	public class RangeArray
	{
 
		// Приват
		private var _vec:Vector.<RangeArrayItem>;
		private var _hash:Object;
		private var _summ:uint;
		private var _length:uint;
		private var _updated:Boolean;
 
		/**
		 * Создать массив.
		 */
		public function RangeArray()
		{
			_vec = new Vector.<RangeArrayItem>;
			_hash = new Object;
		}
 
		// ПАБЛИК
		/**
		 * Получить элемент списка.
		 * Возвращает элемент списка как из обычного массива, где index должен быть от 0 до length - 1.
		 * @param	index Индекс элемента в списке.
		 * @return	Возвращает элемент списка как из обычного массива, где index должен быть от 0 до length - 1.
		 */
		public function at(index:uint):uint
		{
			return _vec[index].id;
		}
 
		/**
		 * Получить элемент спика по его индексу диапазона.
		 * Возвращает элемент списка диапазон которого содержит переданный индекс или 0, если такого элемента нет в списке.
		 * @param	index Индекс диапазона от 0 до summ - 1 включительно.
		 * @return	Возвращает элемент списка диапазон которого содержит переданный индекс или 0, если такого элемента нет в списке.
		 */
		public function getItemByRangeIndex(index:uint):uint
		{
			if (_updated)
				update();
 
			// Бинарный поиск.
			// Взято с вики и адаптировано: https://ru.wikipedia.org/wiki/%D0%94...B8%D1%81%D0%BA (C#)
 
			if (_length === 0 || index > _vec[_length - 1].lastIndex)
				return 0;
 
			var first:uint;
			var last:uint = _length;
 
			while (first < last)
			{
				var mid:uint = first + (last - first) / 2;
				var item:RangeArrayItem = _vec[mid];
 
				if (index < item.firstIndex)
					last = mid;
				else if (index > item.lastIndex)
					first = mid + 1;
				else
					return item.id;
			}
 
			return _vec[last].id;
		}
 
		/**
		 * Установить/добавить диапазон индексов элементу списка.
		 * Если указанного id нет в списке - он добавляется.
		 * Если указанный id уже имеется в списке, обновляется значение его диапазона.
		 * Если диапазон передан как 0 - указанный id удаляется из списка. (Если есть)
		 * @param	id ID Объекта.
		 * @param	range Диапазон индексов.
		 */
		public function setRange(id:uint, range:uint):void
		{
			var item:RangeArrayItem = _hash[id];
			if (range === 0)
			{
				if (item === null)
					return;
 
				_vec.removeAt(_vec.indexOf(item));
				_length--;
 
				delete _hash[id];
			}
			else
			{
				if (item === null)
				{
					item = new RangeArrayItem;
					item.id = id;
					item.range = range;
 
					_vec[_length++] = item;
					_hash[id] = item;
				}
				else
				{
					item.range = range;
				}
			}
			_updated = true;
		}
 
		/**
		 * Очистить весь список.
		 */
		public function clear():void
		{
			_vec = new Vector.<RangeArrayItem>;
			_hash = new Object;
			_length = 0;
			_summ = 0;
			_updated = false;
		}
 
		// ПРИВАТ
		private function update():void
		{
			_updated = false;
			_summ = 0;
 
			var i:uint;
			var item:RangeArrayItem;
			while (i < _length)
			{
				item = _vec[i++];
				item.firstIndex = _summ;
				item.lastIndex = _summ + item.range - 1;
 
				_summ += item.range;
			}
		}
 
		// ГЕТТЕРЫ
		/**
		 * Количество элементов в списке.
		 */
		public function get length():uint
		{
			return _length;
		}
 
		/**
		 * Сумма всех диапазонов.
		 */
		public function get summ():uint
		{
			if (_updated)
				update();
 
			return _summ;
		}
	}
}
 
class RangeArrayItem
{
	public var id:uint;
	public var range:uint;
	public var firstIndex:uint;
	public var lastIndex:uint;
}
Вроде всё прекрасно работало, но потести на всякий случай.
__________________
Дети не должны знать о своих родителях

Старый 09.10.2018, 15:39
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 5  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Цитата:
Сообщение от Tails Посмотреть сообщение
Суть в том, чтоб сложить все id и их вероятность в список, а затем случайно выбирать их оттуда
Tails, большое спасибо. Будем посмотреть. Я как раз планировал нечто подобное для ИИ, чтобы при выборе действия на первом этапе рассчитывалась предпочтительность каждой из альтернатив, а затем формировался шорт-лист, например, топ-3. Из него будет выбираться вариант, но также с учётом вероятностей - тем более предпочтительное действие, тем больше вероятность, что оно выпадет.

Хотя всё это хозяйство ещё балансировать и балансировать. С одной стороны, не хочется жёстко детерминированного поведения от NPC, а с другой, как чуть отпустишь, какой-то шаляй-валяй получается с его стороны

Добавлено через 1 час 5 минут
Код AS3:
var chance:Number = 0.1; // 10%
var result:Boolean = Math.random() > chance;
Только не больше, а меньше
__________________
Не сломано - не чини!

Старый 12.10.2018, 18:53
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 6  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
Сообщение от Godwarlock Посмотреть сообщение
Вот тебе расчет вероятности, но тут код Jav-ы. Думаю сможешь адаптировать по as3
В джаве есть random.nextInt() ты можешь сразу с ним сравнивать, зачем ты делишь на 100?
__________________
Ко мне можно и нужно обращаться на ты)

Старый 17.10.2018, 12:20
Appleman вне форума Посмотреть профиль Отправить личное сообщение для Appleman Найти все сообщения от Appleman
  № 7  
Ответить с цитированием
Appleman
 
Аватар для Appleman

Регистрация: Dec 2014
Адрес: Санкт-Петербург
Сообщений: 479
Реализовал вариант выбора одного из нескольких объектов, с учётом сравнительной вероятности каждого.
Вот кусочек кода (всякие проверки я оттуда повыкинул для компактности).

Код AS3:
	public class ProbableOneOf 
	{	
		private var _objArray: Array = []; // Массив объектов, выбираемых с определённой вероятностью
		private var _chances: Vector.<Number> = new Vector.<Number>; // Массив сравнительных вероятностей
		private var _ratings: Vector.<Number> = new Vector.<Number>; // Массив рейтингов выпадания, которые будут непосредственно сравниваться друг с другом
 
		public function ProbableOneOf() {}
 
		public function addObjChancePair(obj: * , chance: Number) : void
		{
			var rating: Number = Math.random() * chance;
 
			_objArray.push (obj);
			_chances.push (chance);
			_ratings.push (rating);
		}
 
		public function getProbableObj() : *
		{			
			while (_objArray.length > 1)
			{
				compareAndRemove();
			}
 
			return _objArray[0];
		}
 
		private function compareAndRemove() : void
		{
			if (_ratings[0] > _ratings[1]) 
			{
				removeAtIndex(1);
				return;
			}
			if (_ratings[0] < _ratings[1])
			{
				removeAtIndex(0);
				return;
			}
 
			removeAtIndex (Math.round(Math.random()));
		}
 
		private function removeAtIndex(index: uint) : void
		{
			_objArray.removeAt(index);
			_chances.removeAt(index);
			_ratings.removeAt(index);
		}
То есть для каждого объекта выбрасываем случайное число от 0 до полученной сравнительной вероятности и возвращаем тот, у которого данный "рейтинг" наибольший. Как считаете, корректно с т.з. математики использовать такой подход?
__________________
Не сломано - не чини!

Создать новую тему Ответ Часовой пояс GMT +4, время: 08:53.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 08:53.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.