Как реально перетасовать колоду карт
Когда мне нужно перетасовать колоду карт покера в Java/Android, я использую Collections.shuffle(List<?> list)
, конечно. Я когда-либо делал это, и результаты казались приемлемыми. Но это не так.
Как указано в этой статье, есть 52! возможны уникальные перетасовки колоды для покера с 52 карточками. Это составляет около 2 ^ 226.
Но Collections.shuffle(List<?> list)
по умолчанию использует new Random()
, который использует 48-битное семя и поэтому может создавать только 2 ^ 48 уникальных тасов - это всего лишь 3.49*10^(-52)
процентов всех возможных тасов!
Итак, как правильно перетасовать карты?
Я начал использовать SecureRandom
, но этого достаточно, наконец?
List<Card> cards = new ArrayList<Card>();
...
SecureRandom secureRandom;
try {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
}
catch (NoSuchAlgorithmException e) {
secureRandom = new SecureRandom();
}
secureRandom.nextBytes(new byte[20]); // force SecureRandom to seed itself
Collections.shuffle(cards, secureRandom);
Ответы
Ответ 1
Вы можете получить только 2 48 разных рук с определенной стартовой компоновки, но не требуется, чтобы вы начинали с одной и той же компоновки каждый раз.
Предположительно, после окончания колоды (руки в покере, блэкджек и т.д.) она будет в неопределенном порядке, и любая из этих перестановок будет подходящей.
И если вы беспокоитесь о том, что каждый раз, когда вы запускаете свою программу, вы начинаете с фиксированной договоренности, просто сохраняйте заказ при выходе и перезагрузке в следующий раз.
В любом случае 2 48 по-прежнему представляет собой огромное количество возможностей (около 280 000 000 000 000), что более чем подходит для карточной игры, тем более, когда вы осознаете, что это ограничивает перетасовку, а не договоренности. Если вы не серьезный статистик или криптограф, то у вас должно быть хорошо.
Ответ 2
Хотя вы используете SecureRandom
, все еще имеет ограниченное состояние. Пока это входное семя имеет меньший диапазон, чем 52! он не может быть полностью случайным.
Фактически, SHA1PRNG
занесено в 160 бит, что означает, что он все еще не является случайным. Следуйте этой ссылке, он имеет решение несколько лет назад, используя стороннюю библиотеку под названием UnCommons Math
.
Ответ 3
Если вам нужна реальная случайность, вы можете просто пропустить псевдослучайные генераторы и перейти к чему-то лучшему, например, случайным числам, генерируемым из атмосферного шума.
random.org предлагает API для интеграции случайных числа, сгенерированные таким образом в ваше собственное программное обеспечение.
Ответ 4
Кража ответа из статьи, которую вы указываете:
START WITH FRESH DECK
GET RANDOM SEED
FOR CT = 1, WHILE CT <= 52, DO
X = RANDOM NUMBER BETWEEN CT AND 52 INCLUSIVE
SWAP DECK[CT] WITH DECK[X]
Генератор случайных чисел должен быть хорошим и использовать 64-битное семя, которое вы выбираете непредсказуемо, предпочтительно используя аппаратное обеспечение.
Ответ 5
Как реально перетасовать колоду?
Существует несколько методов перетасовки.
Либо (Снятие/Сверху):
Cut the deck in two
Add a small (pseudorandom) amount of one half to the front of the front of the other
Add a small (pseudorandom) amount of one half to the front of the back of the other
Do this until one hand is empty
Repeat
Или (Riffle):
Cut the deck in two
Set down a small (pseudorandom) portion of one half
Set down a small (pseudorandom) portion of the other
Do this until both hands are empty, and you have a new deck
Repeat
И есть еще что-то в этом роде, как описано в моей ссылке выше.
Несмотря на это, существует так много комбинаций, что даже идеальный алгоритм перетасовки заставил машину исследовать 2*10^50
уникальные перестановки в секунду, чтобы завершить изучение каждой перестановки за время существования Вселенной. Ожидается, что к 2019 году только современные компьютеры прогнозируют поражение 1 ExaFLOP (1*10^18
операций с плавающей запятой в секунду).
Ни один человеческий shuffler не изучит этот диапазон возможностей, и вы, я полагаю (на самом базовом уровне), имитируя человеческое перетасовку, правильно? Не могли бы вы найти, что крупье может перетасовать постепенно упорядоченную колоду в порядке убывания в одном перетасовке? Расколоть колоду с четными рангами до нечетного, в одном перетасовке?
Я не считаю неприемлемым ограничивать себя (хотя и чрезвычайно) небольшим подразделением этого фазового пространства (2^48
возможных случайных чисел) в каждом тасовании, если вы не будете постоянно посеять таким же образом и т.д..
В колоде 52-карточек имеется ровно 52 факториала (выраженного в стенограмме 52!) возможных порядков карточек. Это приблизительно 8 × 10 67 возможных порядков или, в частности: 80,658,175,170,943,878,571,660,636,856,403,766,975,289,505,440,883,277,824,000,000,000,000
.
Величина этого числа означает, что чрезвычайно маловероятно, чтобы две случайно выбранные, действительно рандомизированные колоды никогда, даже в истории Вселенной, не были бы одинаковыми. Однако, хотя точная последовательность всех карты в рандомизированной колоде непредсказуемы, может быть возможно сделать некоторые вероятностные прогнозы относительно колоды, которая недостаточно рандомизирована.
~ Wikipedia
Кроме того, стоит отметить, что Bayer и Diaconis в 1992 году доказали, что для правильной рандомизации колоды требуется 7 хороших тасований, здесь - это раздел на нем из википедии, в которой есть много ссылок на бумаги, обсуждающие это.