Це мої щасливі кубики [закриті]


10

Створіть програму або функцію, яка імітує звичайні кістки для рольових ігор. Він повинен обробляти щонайменше d6 та d20, дві найпоширеніші кістки.

Однак це повинно працювати так, як стереотипні геймери очікують, що вони працюватимуть, а не як справжні кістки.

Це в жарті між геймерами, що можна мати спеціально пощастило загинути за дуже важливий рулон, попередньо кидаючи багато кісток, вибираючи ті, в результаті яких було "1", а потім кидаючи їх знову, поки не отримаєш декілька, які прокатували "1" кілька разів. Потім ви ретельно зберігаєте їх, оскільки вони прокручуються 1 кілька разів послідовно, тому ймовірність прокрутити 1 наступного разу повинна бути вкрай низькою.

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

Ваші імітовані кістки повинні враховувати попередні рулони та працювати аналогічно тому, як гравець, котрий вважає помилку гравця, очікує, що він працює. Наприклад, якщо було зафіксовано багато низьких чисел, слід збільшити ймовірність перенесення більшого числа.

Однак, оскільки це обман, ви повинні це добре приховати . Це означає, що випадковий погляд на програму не повинен виявити, що ви обдурили. Це означає, що явно зберігати попередні результати та читати їх під час кожного кидка було б занадто підозріло. Ви повинні приховати це "властивість" своїх кісток і бонусні бали, якщо зробите це правдоподібним і маскуєте його як чесну помилку. (наприклад, ви створюєте власну RNG із "ненавмисною" вадою)

Виборці, будь ласка, врахуйте, наскільки добре прихований цей "недолік".

Програми повинні бути чіткими, а не заплутаними. Приховати злий код у затуманеній програмі занадто просто.


3
Наскільки добре приховано ми говоримо? ІМО, все, що не відповідає мовному еквіваленту getRandomBetween(1,d), змусить мене зазирнути все глибше.
Геобіц

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

Godmaydamnit, java doesnt вистачає
химерності для недоброзичливих


4
Я голосую за те, щоб закрити це питання як позатематичне, тому що непрофесійні виклики зараз поза темою, і якимось чином цей заліз під радари.
Мего

Відповіді:


3

Java

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дуже мало стосується поведінки цієї відповіді. Дійсно, на що покладається ця відповідь - це той факт, що, як і будь-який RNG, java.util.Randomє період, і якщо ви генеруєте кілька чисел на порядку періоду, його статистичні властивості руйнуються. Це не дуже цікаво; те ж саме станеться з навіть криптографічно захищеним RNG, як Blum Blum Shub, якщо ви керуєте ним досить довго.
user2357112 підтримує Моніку

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

Правда, кожен RNG робить справу відкидання. Це нічого особливого. Ви можете використати цю відповідь буквально з будь-яким генератором псевдовипадкових чисел, тому що якщо RNG 1) має період, і 2) може видавати більше 1 різного числа, то в межах одного періоду, тим більше число з'являється відносно інших чисел, тим менше буде відображатися до наступного періоду простим аргументом підрахунку.
user2357112 підтримує Моніку

Аналіз у цій відповіді потребує порядку 2 ^ 48 рулонів, щоб проявити ефект. Можливо, якби ви використали більш складний аналіз, який показує, що використання LCG спричиняє вимірні статистичні аномалії в межах декількох рулонів, які, правдоподібно, з'являться в настільній грі, це може бути правильною відповіддю. Якщо ви говорите про трильйони булочок, це просто не надто добре.
user2357112 підтримує Моніку

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])
...

Я додав би, що для "переривання" потрібен рубін 2 ", якщо RUBY_VERSION <" 2 "'десь там, ніби запустивши його на більш ранніх версіях, це
зіпсує

0

Хаскелл

Використовуйте одну випадкову річ, щоб зробити ще одну випадкову річ: у цьому випадку перетасовуйте картки для створення кидків.

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.