Avatar billede tjacob Juniormester
30. december 2016 - 21:35 Der er 6 kommentarer og
1 løsning

Emulere en ældre MS RNG

Hej

Jeg er ved at forsøge at lave et program der emulerer det gamle Microsoft FreeCell, og jeg har et problem med algoritmen der emulerer den "gamle" MS C RNG. Dvs at jeg ønsker en algoritme der kan spytte de samme 52 kort ud i den samme rækkefølge som i originalen med spilnummeret som seed.

Algoritmen er kendt, og problemet er beskrevet grundigt her:

http://rosettacode.org/wiki/Deal_cards_for_FreeCell

Der er 43 kode-eksempler, men ingen VB NET, og jeg kan simpelthen ikke få det til at spille, selvom jeg er rimelig kendt med både Java og C#.

Min kode ser sådan ud (meget kort og i omvendt rækkefølge,men det burde være korrekt).

Public Sub TestRNG()

        Dim pSeed As Single = 1
        Dim Cards(51) As Integer
        For i = 0 To 51
            Cards(i) = i
        Next i
        Dim pIndex As Integer
        Dim tmp As Integer
        For i = 51 To 0 Step -1
            pSeed = ((214013 * pSeed + 2531011) And Integer.MaxValue)
            pIndex = (pSeed >> 16) Mod (i + 1)
            tmp = Cards(pIndex)
            Cards(pIndex) = Cards(i)
            Cards(i) = tmp
        Next i


    End Sub

Det første kort er korrekt ved et hvilket som helst spilnummer, men de efterfølgende bliver forkerte, så jeg tror måske fejlen ligger i
pSeed= linien.
Avatar billede tjacob Juniormester
30. december 2016 - 21:50 #1
Jeg glemte lige at nævne, at min kode giver tal (0 til 51) i stedet for kortbetegnelser.
Nummereringen følger den gamle Cards.dll fra MS, og jeg konverterer bagefter.
Outputtet i mit eksempel (som kommer i omvendt rækkefølge) med spilnummer 1 burde være:  Cards(51)=41, Cards(50)=5, Cards(49)=34 osv......
Avatar billede arne_v Ekspert
31. december 2016 - 02:37 #2
Et oplagt gaet er at:

Dim pSeed As Single = 1

skal vaere:

Dim pSeed As Integer = 1

LCG seeds er altid heltal aldrig floating point.
Avatar billede arne_v Ekspert
31. december 2016 - 02:38 #3
Det er ret nemt at konvertere fra C# til VB.NET, saa har du overvejet at tage noget C# kode og autokonvertere?
Avatar billede tjacob Juniormester
31. december 2016 - 09:27 #4
Heltallet var simpelthen løsningen, Arne.
Den skulle så være Long, da linien:
pSeed = ((214013 * pSeed + 2531011) And Integer.MaxValue) ellers gav overflow.
Men hvorfor egentlig? Burde 'And Integer.MaxValue' ikke sikre at værdien bliver en Integer?

Dum fejl som jeg lavede i starten, netop fordi jeg fik overflow, så lavede jeg den til Single for at være på den sikre side og glemte alt om den.
Utroligt at det kan give forkerte resultater.
Det må så være nogle afrundingsfejl, når tallene bliver store?

Anyway det spiller nu og mange tak for hjælpen.
Jeg er netop begyndt at bruge Eksperten igen efter nogle års pause.
Du hjalp mig ofte for 5-15 år siden, Arne og det gør du stadigvæk :)
Skønt at se at der stadig er nogle af de 'gamle' brugere.

Jeg antager at jeg blot skal 'Markér som løsning', -ingen point mere?

MVH tjacob
Avatar billede arne_v Ekspert
31. december 2016 - 14:32 #5
I.s.f. at skifte fra Integer til Long kunne du ogsaa bare have disablet integer overflow check i project properties compile options.

Jeg er ikke klar over hvad der sker med 32 bit floating point binary and 32 bit integer. Jeg vil altid undgaa en saadan.

32 bit floating point kan kun gemme helttal eksakt op til lige godt 16 millioner. Det er ikke ret meget.
Avatar billede tjacob Juniormester
31. december 2016 - 15:07 #6
Jeg kan godt se at det er noget rod med binære operatorer, så jeg har ændret koden til:

        pSeed = (214013 * pSeed + 2531011) Mod (2 ^ 31)
        pIndex =  pSeed \ (2 ^ 16)

hvilket giver samme resultat.
Avatar billede arne_v Ekspert
31. december 2016 - 20:32 #7
Binaere operatorer kan vaere OK. Men det forudsaetter altsaa at alt er heltal.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester