Это мои счастливые кости [закрыто]


10

Реализуйте программу или функцию, которая имитирует обычные кости для ролевых игр. Он должен обрабатывать как минимум d6 и d20, два самых распространенных кубика.

Тем не менее, он должен работать так, как ожидают от него стереотипные геймеры, а не как настоящая игра в кости.

Это игра в шутку между игроками, что можно получить особенно удачный кубик для очень очень важного броска, предварительно бросив много кубиков, выбрав те, которые привели к «1», затем бросая их снова, пока вы не получите несколько, которые бросили "1" несколько раз. Затем вы тщательно сохраняете их, потому что они бросают 1 несколько раз подряд, поэтому вероятность бросить 1 в следующий раз должна быть чрезвычайно низкой.

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

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

Однако, поскольку это обман, вы должны хорошо это скрывать . Это означает, что случайный взгляд на программу не должен показывать, что вы обманули. Это означает, что явно сохранять предыдущие результаты и читать их при каждом броске было бы слишком подозрительно. Вы должны скрыть это «свойство» ваших костей и бонусные очки, если вы сделаете его правдоподобным, отрицающим и замаскируете его как честную ошибку. (например, вы делаете свой собственный ГСЧ с «непреднамеренным» недостатком)

Избиратели, примите во внимание, насколько хорошо скрыт этот «недостаток».

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


3
Насколько хорошо мы спрятаны? ИМО, что-либо за пределами языкового эквивалента getRandomBetween(1,d)заставило бы меня глубже вникнуть в это.
— Geobits

@Geobits: вы можете найти очень хороший пример того, как решить скрытые проблемы, здесь: codegolf.stackexchange.com/questions/19569/… Я имею в виду, что вы можете сделать что-нибудь, если вы достаточно хорошо это оправдываете, конечно, оправдание может быть большая ложь.
— вс

Godmaydamnit, Java не хватает причуд для закулисных вещей ...
— masterX244


4
Я голосую, чтобы закрыть этот вопрос как не по теме, потому что закулисные вызовы сейчас не по теме, и каким-то образом этот вопрос ускользнул от радаров.
— Мего

Ответы:


3

Ява

public class GamerDie {
    private final java.util.Random rnd;
    private final int sides;

    public GamerDie(int sides) {
        this.sides = sides;
        this.rnd = new java.util.Random();
    }

    public int throw() {
        return rnd.nextInt(sides) + 1;
    }
}

Это так просто, что он, очевидно, ничего не скрывает: он java.util.Randomявляется прямым линейным конгруэнтным генератором и использует метод отбрасывания для обеспечения однородности, поэтому он гарантирует, что при любом запуске наибольшего кратного из sizeменее чем 2 48 выборок он будет распределять числа равномерно, удовлетворяющие требованию.


не могу объяснить, как работает java.util.random
— masterX244

Отбрасывание, которое java.util.Randomвыполняет, имеет очень мало общего с поведением этого ответа. На самом деле, этот ответ основан на том факте, что, как и у любого ГСЧ, java.util.Randomесть период, и если вы генерируете число чисел порядка этого периода, его статистические свойства нарушаются. Это не очень интересно; то же самое произошло бы даже с криптографически защищенным ГСЧ, таким как Blum Blum Shub, если вы выполняете его достаточно долго.
— user2357112 поддерживает Monica

@ user2357112, отбрасывание актуально, потому что вопрос требует единообразия, а не небольшого смещения к меньшим числам. По моему мнению, этот ответ олицетворяет скрытность: преднамеренное использование стандартной библиотеки способом, который на первый взгляд кажется прозрачно правильным, но на самом деле выводит его за пределы проектных параметров.
— Питер Тейлор

Тем не менее, почти каждый ГСЧ отбрасывает вещи. Ничего особенного Вы могли бы использовать этот ответ буквально с любым генератором псевдослучайных чисел, потому что, если ГСЧ 1) имеет период и 2) может произвести более 1 различного числа, то в пределах одного периода, чем больше число появилось относительно других чисел, тем меньше он будет отображаться до следующего периода с помощью простого аргумента подсчета.
— user2357112 поддерживает Monica

Анализ в этом ответе требует порядка 2 ^ 48 бросков для проявления эффекта. Может быть, если бы вы использовали более сложный анализ, показывающий, что использование LCG приводит к появлению измеримых статистических аномалий в течение ряда бросков, которые правдоподобно появляются в настольной игре, это может быть правильным ответом. Когда вы говорите о триллионах рулонов, это просто не очень закулисно.
— user2357112 поддерживает Monica

0

Рубин

В настоящее время поддерживает только d6, позже добавлю поддержку d20 ...

И вот, эти кубики противны!

# first idea was to create 6 super cool dices just by copy&paste
# -> each dice holds its number at the beginning of the array
# -> we don't need all of them now, so we comment them out
dice0 = %w[[[[[[[[[ 0 . : :. :: ::. ::: ]]]]]]]]
#dice1 = %w[[[[[[[ 1 : . :. ::. :: ::: ]]]]]]]
#dice2 = %w[[[[[[ 2 . : :. :: ::. ::: ]]]]]]
#dice3 = %w[[[[[[ 3 : . :. ::. :: ::: ]]]]]]]
#dice4 = %w[[[[[[[ 4 . : :. :: ::: ::. ]]]]]]]
#dice5 = %w[[[[[[[[ 5 . : :. :: ::. ::: ]]]]]]]]]

# and hey, those dices are almost ascii art ;)

# well, let's just create a standard dice
# -> get rid of the number at the beginning
# -> then sort (maybe we need that later due to the
#    currently unused dices being unsorted)
dice = dice0.select!{|e| /[:.]+/ === e}.sort

def roll(d)
  # rolling is easy
  # -> use size instead of hardcoded number,
  #   maybe we'll have other dices later
  d.slice!(rand(d.size - 1))
end

# and here you have 8 very underhanded dices!
dices = [dice]*8

# roll like a champion
roll(dices[0])
...

Я бы добавил "abort", требующий ruby ​​2 ", если где-то там RUBY_VERSION <" 2 "', как будто вы запускаете его на более ранних версиях, это портит трюк
— bazzargh

0

Haskell

Используйте одну случайную вещь, чтобы сделать другую случайную вещь: в этом случае перетасуйте карты, чтобы генерировать броски костей.

import System.Environment
import System.Random
import Data.Array.IO
import Control.Monad
-- make random dice from random cards
suit c=map (\(a,b)->[a,b])$zip "A23456789TJQK" (repeat c)
deck=concatMap(\s->suit s) "♠♥♦♣"
-- just like casinos, use more decks for extra randomness
decks=concat$take 8$repeat deck
-- shuffle the cards
shuffle :: [a] -> IO [a]
shuffle xs = do
        ar <- newArray n xs
        forM [1..n] $ \i -> do
            j <- randomRIO (i,n)
            vi <- readArray ar i
            vj <- readArray ar j
            writeArray ar j vi
            return vj
  where
    n = length xs
    newArray :: Int -> [a] -> IO (IOArray Int a)
    newArray n xs =  newListArray (1,n) xs
-- convert a card to a die, by counting along the original deck
-- then taking mod (faces). If we don't have enough cards to make
-- a full set of faces, assign the 'extra' cards a value of 0
card2die faces card=
  let index=(head[i|(i,c)<-zip[0..]deck,c==card]) in
  if (index > (length deck-(length deck`mod`faces)))
  then 0
  else (index`mod`faces)+1
main=
  do
    args <- getArgs
    let faces = read (args!!0)
    -- throw away cards we can't map to die faces
    cards<-shuffle$filter (\card->card2die faces card/=0) decks
    mapM_ (\card->putStrLn (card++" -> "++(show (card2die faces card)))) cards

Принимает один аргумент, количество лиц на кубике. Вывод такой:

./cards 20|head
2♦ -> 8
7♥ -> 20
J♦ -> 17
6♥ -> 19
9♥ -> 2
8♥ -> 1
5♥ -> 18
4♠ -> 4
Q♥ -> 5
2♣ -> 1

... и так далее для всех карт (сбросы не печатаются). Слишком очевидно?

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.