|
|
|||||
Процентый шанс ответа.
Как сделать систему шансов. Например у меня есть 10 чисел. При нажатии на кнопку выбирается одно из чисел. Если оно выбралось, оно будет выпадать чаще других. То есть шанса выпада этого числа повысится.
Я думал делать так: Создать массив с вариантами (1,2,3,4,5,6,7,8,9,0) Создать массив с шансами (10,10,10,10,10,10,10,10,10,10) Потом делать рандом и выбирать шанс из массива, а потом выбирать число и когда оно выпадает, увеличивать шанс. Но у меня не получилось. Подскажите как такое можно осуществить? Добавлено через 2 минуты И как вообще осуществить процентный шанс? Как сделать при увеличении одного параметра ,равномерное сниженое других, но учитывая, что все равно в общем должно выходить 100%..? |
|
|||||
Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
|
после выбора, добавить это число в исходный массив еще раз (или несколько раз). Теперь, в исходном массивет его будет 2 (или более), когда остальных по-прежнему останется по-одному. Шансы получить выбранное число повысятся.
__________________
Загружаем картинки, минуя ошибки безопасности Последний раз редактировалось i.o.; 21.05.2011 в 14:49. |
|
|||||
Спасибо, попробую.
Добавлено через 6 минут Получилось. Спасибо, оказалось проще, чем думал. Добавлено через 4 часа 45 минут Мне требуется другое решение. Так как иногда некоторые варианты могут отпадать. Например в процессе отключить цифру 5. А как сделать при вашем коде? Делать цикл по удалению всех полей с 5? Но тогда будет значение null, а это мне не подходит. Последний раз редактировалось Lyso; 21.05.2011 в 19:29. |
|
|||||
Регистрация: Oct 2009
Сообщений: 155
|
так удаляйте со смешением, чтобы не было пустых null
|
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
|
|
|||||
[+1 23.05.11]
Регистрация: Dec 2001
Сообщений: 4,159
|
Цитата:
В общем случае проще оставить числа как есть, но добавить веса. Изначально вес каждого равен 1. Ели число выбрано -- его вес увеличиваем (до 2, 10, 1000 -- как нужно). Далее формируем случайное число, причем в качестве диапазона берем сумму всех весов. Как потом найти выпавшее число, полагаю, достаточно очевидно. Цитата:
__________________
GIT d++ s++:++ a C++$ UB++ P++ L+ E+ W+++ N++ w++ O+ M V- t-- 5-- X+ R+++ tv- b+++ D++ |
|
|||||
Цитата:
__________________
Чтобы доказать, что вы не робот, причините вред другому человеку. |
|
|||||
Регистрация: Mar 2011
Сообщений: 35
|
Алгоритм древний и проверенный, но непосредственно АС3-класс написан на коленке (NP++) за 5 минут (в АС3 не использовал ибо), так что, возможно, придётся внести фикссы, чтобы компилировалось. Без оптимизации работает не самым быстрым способом. Помимо того, возможно накопление ошибок при сложении чисел с плавающей точкой. При таком раскладе первая зарегистрированная грань будет выпадать гипотетически чаще. Чтобы этого избежать, шансы граней должны быть одного или близких порядков. Грубо говоря, самый маленький шанс и самый большой не должны отличаться более чем на три-четыре порядка. Но в большинстве задач можно забить на эту ошибку, она реально ничтожна.
package { public class VirtualDice // виртуальная кость (ваш К.О.) { protected var _chances:Vector.<Number> = new Vector.<Number>; // стороны кости protected var _faces:Vector.<Number> = new Vector.<Number>; // абсолютные шансы для каждой стороны protected var _range:Number = 0; // кеш суммы всех шансов, используется при кидании кости public function getFaceChance(face:Number):Number // текущий вес для грани кости { var index:uint = _faces.lastIndexOf(face); // найти грань в наборе return (index == -1) ? 0 : _chances[index]; // вернуть шанс найденной грани, либо нуль, если не найдена } public function setFaceChance(face:Number, chance:Number = 1):void // установить вес грани { if(chance < 0) // отрицательные шансы невозможны chance = 0; // особо дотошные пишут throw new Error("Dice face chance negative value assigned"); var index:uint = _faces.lastIndexOf(face); // найти грань в наборе if (index == -1) // а нету такой грани в наборе, придётся добавить { if(chance == 0) // её и так нет, нет смысла ставить нулевой шанс return; _faces.push(face); _chances.push(chance); index = _faces.lenght - 1; } else if(chance == 0) // грань с занулённым шансом удалим для экономии памяти { _faces.splice(index,1); _chances.splice(index,1); } _range = 0; // нужно обновить кеш for each (var intermediate:Number in _chances) result += intermediate; } public function roll():Number { if(!_faces.lenght) // опа, граней то нету! rhrow new Error("Rolling dice without faces"); // сферическая кость в ваккууме никогда бы не остановилась var fortune_charge:Number = _range * Math.random; // Holy Random is True God and only var lucker:Number = _faces.lenght - 1; while(lucker) { fortune_charge -= _chances[lucker]; if(fortune_charge <= 0.0001) break; lucker--; } return _faces[lucker]; } } } Так же легко работать и с целочисленными шансами, но я не думаю, что это удобно. Последний раз редактировалось ShadowsInRain; 22.05.2011 в 01:24. Причина: UPD |
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
Цитата:
Например, у нас есть три значения с весами 5, 3 и 2. Получаем случайное число в промежутке 0-1, далее: - если до 0.5 - выпало первое значение - больше 0.5 и меньше 0.8 - второе - больше 0.8 - третье |
|
|||||
Modus ponens
|
Собственно, решил сделать эксперимент интереса ради
package tests { import flash.display.Sprite; /** * ... * @author wvxvw */ public class ProbablityTester extends Sprite { private const _variants:Vector.<uint> = new <uint>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; private const _weights:Vector.<uint> = new <uint>[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; public function ProbablityTester() { super(); // position: 0 total: 99435 // position: 1 total: 100361 // position: 2 total: 99991 // position: 3 total: 99921 // position: 4 total: 99452 // position: 5 total: 100059 // position: 6 total: 100715 // position: 7 total: 100259 // position: 8 total: 99848 // position: 9 total: 99959 this.testDistribution(); // exclude 5 from the pool completely this.setChance(5, 0); // position: 0 total: 111148 // position: 1 total: 111645 // position: 2 total: 111153 // position: 3 total: 111161 // position: 4 total: 111147 // position: 5 total: 0 // position: 6 total: 111019 // position: 7 total: 110609 // position: 8 total: 110869 // position: 9 total: 111249 this.testDistribution(); // double the chances for 6 this.setChance(6, 2); // position: 0 total: 100195 // position: 1 total: 99949 // position: 2 total: 99909 // position: 3 total: 99673 // position: 4 total: 100513 // position: 5 total: 0 // position: 6 total: 200260 // position: 7 total: 99795 // position: 8 total: 99600 // position: 9 total: 100106 this.testDistribution(); } public function setChance(of:uint, to:uint):void { of = of % 10; this._weights[of] = to; } private function testDistribution():void { var results:Vector.<uint> = new Vector.<uint>(10); var i:int; for (i = 0; i < 1e6; i++) { results[this.selectRandom()]++; } for (i = 0; i < 10; i++) { trace("position:", i, "total:", results[i]); } } private function selectRandom():uint { var result:uint; var weight:uint; var random:uint = this.sum() * Math.random(); for (var i:int; i < 10; i++) { weight = this._weights[i]; if (random < weight) { result = i; break; } else random -= weight; } return result; } private function sum():uint { var result:uint; for each (var i:uint in this._weights) result += i; return result; } } }
__________________
Hell is the possibility of sanity Последний раз редактировалось wvxvw; 22.05.2011 в 01:09. |
Часовой пояс GMT +4, время: 02:53. |
|
« Предыдущая тема | Следующая тема » |
Теги |
выпад , массив , Рандом , шанс |
|
|