To są moje szczęśliwe kości [zamknięte]


10

Zaimplementuj program lub funkcję, która symuluje wspólne kości do gier RPG. Powinien obsługiwać przynajmniej d6 i d20, dwie najczęściej używane kości.

Powinno jednak działać tak, jak oczekują od stereotypowych graczy, a nie jak w prawdziwych kościach.

Żart między graczami polega na tym, że można mieć wyjątkowo szczęśliwą kostkę za bardzo ważny rzut, uprzednio rzucając dużą ilością kości, wybierając te, które dały wynik „1”, a następnie rzucając je ponownie, aż otrzymasz kilka, które rzuciły „1” wiele razy. Następnie ostrożnie je zachowaj, ponieważ rzuciły 1 wielokrotnie w sekwencji, więc prawdopodobieństwo rzutu 1 następnym razem powinno być bardzo niskie.

Oczywiście nie tak działają kości w prawdziwym życiu , ponieważ rzuty są statystycznie niezależne.

Twoje symulowane kości muszą brać pod uwagę wcześniejsze rzuty i działać podobnie do tego, jak hazardzista z błędu gracza oczekuje, że zadziała. Na przykład, jeśli wyrzucono wiele niskich liczb, należy zwiększyć prawdopodobieństwo wyrzucenia większej liczby.

Ponieważ jest to oszustwo, musisz to dobrze ukryć . Oznacza to, że przypadkowe spojrzenie na program nie powinno ujawniać, że oszukiwałeś. Oznacza to, że jawne zapisywanie poprzednich wyników i czytanie ich przy każdym rzucie byłoby zbyt podejrzane. Musisz ukryć tę „właściwość” swoich kości i punkty bonusowe, jeśli sprawisz, że będzie to możliwe, bez wątpienia, i ukryj to jako uczciwy błąd. (na przykład tworzysz własne RNG z „niezamierzoną” wadą)

Głosujący, proszę wziąć pod uwagę, jak dobrze ukryta jest ta „wada”.

Programy powinny być jasne i nie zaciemniać. Zbyt łatwo ukryć zły kod w zaciemnionym programie.


3
Jak dobrze rozmawiamy? IMO, cokolwiek poza językowym odpowiednikiem getRandomBetween(1,d)spowodowałoby, że zajrzałbym głębiej.
— Geobits

@Geobits: tutaj możesz znaleźć bardzo fajny przykład rozwiązywania podstępnych problemów: codegolf.stackexchange.com/questions/19569/... Mam na myśli, że możesz zrobić wszystko, jeśli uzasadnisz to wystarczająco dobrze, oczywiście uzasadnienie może być wielkie kłamstwo.
— vsz

Cholera jasna, java nie ma dość dziwactw do podstępnych rzeczy ...
— masterX244


4
Głosuję za zamknięciem tego pytania jako nie na temat, ponieważ podstępne wyzwania są teraz nie na temat, i jakoś to ześlizgnęło się pod radarem.
— Mego

Odpowiedzi:


3

Jawa

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;
    }
}

Jest tak prosty, że oczywiście niczego nie ukrywa: ale java.util.Randomjest prostym liniowym generatorem kongruencjalnym i wykorzystuje technikę odrzutu, aby zapewnić jednorodność, więc gwarantuje, że w każdej serii największej wielokrotności sizemniejszej niż 2 ^ 48 próbek rozdzieli liczby równomiernie, spełniając wymagania.


Nie mogę się za wyjaśnić, jak działa java.util.random
— masterX244

Odrzucanie, które java.util.Randomwykonuje, ma bardzo niewiele wspólnego z zachowaniem tej odpowiedzi. Naprawdę to, na czym polega ta odpowiedź, to fakt, że jak każdy RNG java.util.Randomma kropkę, a jeśli wygenerujesz liczbę liczb w porządku tego okresu, jej właściwości statystyczne się rozpadną. To nie jest bardzo interesujące; to samo stanie się z nawet bezpiecznym kryptograficznie RNG, takim jak Blum Blum Shub, jeśli uruchomisz go wystarczająco długo.
— user2357112 obsługuje Monikę

@ user2357112, odrzucenie jest istotne, ponieważ pytanie wymaga jednolitości, a nie niewielkiego uprzedzenia do mniejszych liczb. Moim zdaniem odpowiedź ta uosabia podstępność: celowe użycie standardowej biblioteki w sposób, który na pierwszy rzut oka wydaje się transparentnie poprawny, ale w rzeczywistości wykracza poza jego parametry projektowe.
— Peter Taylor

Jednak prawie każdy RNG robi coś odrzucającego. To nic specjalnego. Mógłbyś użyć tej odpowiedzi dosłownie z dowolnym generatorem liczb pseudolosowych, ponieważ jeśli RNG 1) ma kropkę, a 2) może wygenerować więcej niż 1 inną liczbę, to w ramach jednego okresu, tym bardziej liczba się wyświetla w stosunku do innych liczb, tym mniej wyświetli się do następnego okresu za pomocą prostego argumentu liczenia.
— user2357112 obsługuje Monikę

Analiza w tej odpowiedzi wymaga rzędu 2 ^ 48 rolek, aby pojawił się efekt. Być może, jeśli zastosowałeś bardziej wyrafinowaną analizę, która pokazuje, że użycie LCG powoduje pojawienie się mierzalnych anomalii statystycznych w obrębie szeregu rzutów, które prawdopodobnie pojawiłyby się w grze stołowej, może to być dobra odpowiedź. Kiedy mówisz o trylionach bułek, nie jest to zbyt mało zrozumiałe.
— user2357112 obsługuje Monikę

0

Rubin

Obecnie obsługuje tylko d6, doda obsługę d20 później ...

I oto - te kości są paskudne!

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

Dodałbym „przerwanie” wymaga ruby ​​2 ”, jeśli gdzieś tam RUBY_VERSION <„ 2 ”, tak jakbyś uruchomił go na wcześniejszych wersjach, psuje to sztuczkę
— bazzargh

0

Haskell

Użyj jednej losowej rzeczy, aby zrobić inną losową rzecz: w tym przypadku potasuj karty, aby wygenerować rzuty kostkami.

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

Przyjmuje jeden argument, liczbę twarzy na kości. Dane wyjściowe są takie:

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

... i tak dalej dla wszystkich kart (odrzuty nie są drukowane). Zbyt oczywisty?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.