Avatar billede mega-hawk Nybegynder
06. november 2010 - 10:41 Der er 15 kommentarer og
1 løsning

hjælp til randomizr i kort spil.

Jeg har lige brug for lidt hjælp til at komme videre i mit kortspil jeg er igang med at lave.

Her er et lille kode eks fra mit spil.

Dim kort As New System.Collections.Queue

Form load----
        kort.Enqueue("Cards\1_1.gif")
        kort.Enqueue("Cards\1_2.gif")
        kort.Enqueue("Cards\1_3.gif")
        kort.Enqueue("Cards\1_4.gif")
        kort.Enqueue("Cards\1_5.gif")
        kort.Enqueue("Cards\1_6.gif")
        kort.Enqueue("Cards\1_7.gif")
        kort.Enqueue("Cards\1_8.gif")
        kort.Enqueue("Cards\1_9.gif")
 
Knap tryk

PictureBox1.Image = Image.FromFile(CStr(kort.Dequeue))

Det virker fint. Jeg får et billed af mit kort hver gang og når stakken er tom får jeg også det at vide.

Det er så bare ikke særlig smart at lave et spil hvor kort kommer i rækkefølge.

Så jeg har brug for en random funktion
Har prøvet med den her:

Dim i As Integer = 0
        i = CInt((Rnd() * 8))
        PictureBox1.Image = Image.FromFile(CStr(kort.Dequeue(i)))

Virker ikke Option strict on disallows late binding.

Så har jeg tænkt på at lave noget i stil med:

knap tryk

        Dim i As Integer = 0
        Dim kort_arry(8) As String

        kort_arry(0) = ("Cards\1_1.gif")
        kort_arry(1) = ("Cards\1_2.gif")
        kort_arry(2) = ("Cards\1_3.gif")
        kort_arry(3) = ("Cards\1_4.gif")
        kort_arry(4) = ("Cards\1_5.gif")
        kort_arry(5) = ("Cards\1_6.gif")
        kort_arry(6) = ("Cards\1_7.gif")
        kort_arry(7) = ("Cards\1_8.gif")
        kort_arry(8) = ("Cards\1_9.gif")
        i = CInt((Rnd() * 8))

        PictureBox1.Image = Image.FromFile(kort_arry(i))

Virker fint, men så bliver jeg jo ved med at have en masse kort
så jeg skal have noget med at efter den har vist mit kort så bliver det fjernet
noget i stil med kort_arry remove (i) eller sådan noget

Er forholdsvis begynder til det her endnu så en vild avanceret kode kan jeg ikke bruge til noget.

Hvordan ville i løse problemet og hvordan kommer jeg her på rette vej?
Avatar billede nielle Nybegynder
06. november 2010 - 11:14 #1
Du skal ikke putte kortene i en Queue fo den er netop beregnet til at tingene ligger i en bestemt orden.

Prøv i stedet med noget i denne stil:

        Dim kort As ArrayList = New ArrayList()

        kort.Add("Cards\1_1.gif")
        kort.Add("Cards\1_2.gif")
        kort.Add("Cards\1_3.gif")
        kort.Add("Cards\1_4.gif")
        kort.Add("Cards\1_5.gif")
        kort.Add("Cards\1_6.gif")
        kort.Add("Cards\1_7.gif")
        kort.Add("Cards\1_8.gif")

        Randomize()
        For kortNr1 As Integer = 0 To kort.Count - 1
            Dim kortNr2 As Integer = Int(Rnd() * kort.Count)

            Dim kort1 As String = kort(kortNr1)
            Dim kort2 As String = kort(kortNr2)

            kort(kortNr1) = kort2
            kort(kortNr2) = kort1
        Next
Avatar billede mega-hawk Nybegynder
06. november 2010 - 12:33 #2
Så nielle så har jeg fået kigget lidt på det.
Har lige lavet en copy + paste.

Altså jeg får random kort. Sådan ca da, men det gjorde jeg også i mit eget eksempel da jeg brugte arry og ikke queue.

Problemet er bare stadig at jeg bliver ved med at have mine kort.
Jeg har som sagt brug for noget som så efterfølgende sletter mine kort fra mit arry.
Eks med din kode som bliver kørt igennem er resultatet:

9-3-3-8-6-4-9-2-6-6-7-4-3

Som du kan se får jeg de samme kort mere end en gang.
Det er ik rigtig meningen i et spil kort, så som efterlyst tidliger søger jeg noget kode som efterfølgende sletter mine kort fra mit arry så det ikke bliver genbrugt før jeg starter et nyt spil.
Avatar billede tjacob Juniormester
06. november 2010 - 13:20 #3
Nielles loop er blot en simpel blandingsalgoritme.

Hvis det samme tal optræder mere end en gang, er det fordi det gør det i den oprindelige ArrayList.

Den funktionalitet du efterlyser kan du opnå ved at fjerne allerede brugte elementer i listen f.eks. sådan:


et kort = kort(0)
kort.RemoveAt(0)

På denne måde trækker du hele tiden det første element, og derefter fjerner du det, så det næste element bliver det første til næste gang.
Denne fremgangsmåde kræver naturligvis at listen er blandet først, hvis trækket skal være tilfældig.

For i øvrigt vil jeg anbefale dig at bruge List i stedet for ArrayList, hvis listen kun skal indeholde en type.

Altså Dim kort As New List(Of String)

-Så slipper du for en masse type konverteringer (I hvert fald hvis du bruger Option Strict On, hvad der kan anbefales).
Avatar billede mega-hawk Nybegynder
06. november 2010 - 15:51 #4
så tjacob så tror jeg snart jeg har noget her.

Public Class Form1

    Dim kort As New List(Of String)
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim i As Integer = 0
        i = CInt((Rnd() * 8))
        MsgBox(i)
        PictureBox1.Image = Image.FromFile(kort(i))
        kort.RemoveAt(i)
        MsgBox("Kort tilbage " & kort.Count)
    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        kort.Add("Cards\1_1.gif")
        kort.Add("Cards\1_2.gif")
        kort.Add("Cards\1_3.gif")
        kort.Add("Cards\1_4.gif")
        kort.Add("Cards\1_5.gif")
        kort.Add("Cards\1_6.gif")
        kort.Add("Cards\1_7.gif")
        kort.Add("Cards\1_8.gif")
        kort.Add("Cards\1_9.gif")
        MsgBox(kort.Count)
    End Sub
End Class

Jeg skal bare have gjort sådan at i ikke er den samme 2 gange, men det kan jeg forstå på dig at nielle's kode gør?

Eller hvordan ville du lave det?

Og bare skriv det som et svar for jeg er kommet videre med det du har skrevet og det var lige det jeg manglede.
Avatar billede mega-hawk Nybegynder
06. november 2010 - 18:21 #5
Ser ud til det her faktisk virker fint:

i = CInt((Rnd() * 8))
        Do While i > kort.Count - 1
            i = CInt((Rnd() * 8))
        Loop

Så tjacob kommer du bare med et svar.

og nielle. Tak for din hjælp alligevel.
Jeg kan måske bruge din ide en anden gang, men tak for indsatsen alligevel.
Avatar billede tjacob Juniormester
06. november 2010 - 18:35 #6
Din kode ser ud til at køre som den skal.
Når du fjerner element i, -som er valgt tilfældigt, behøver du ikke blande først.

Det er jo ligegyldigt at du trækker to ens i:

i=5:  Du fjerner element 5 i listen
næste gang: i=5: Nu er det 5. element jo et andet end før!

Men du har en fejl:
i = CInt((Rnd() * 8))  << du trækker et tal mellem 0 og 8

Men anden gang du trækker er der et element mindre. Så du skal bruge: i = CInt((Rnd() * kort.Count - 1)), således at du trækker et tal mellem 0 og listens størrelse.

Det er muligt at der skal noget +/- 1 til. Jeg har ikke lige mulighed for at teste hvor jeg sidder.


PS: Jeg synes at du skal dele pointene, da Nielle kom med ideen om en liste.
Avatar billede tjacob Juniormester
06. november 2010 - 18:35 #7
-Det skulle have været et svar ;)
Avatar billede tjacob Juniormester
06. november 2010 - 18:46 #8
Hovsa, jeg så ikke din sidste kommentar.

Den gør det samme som jeg foreslår i #6, med der er som du kan se ingen grund til at bruge et loop.
Avatar billede mega-hawk Nybegynder
06. november 2010 - 19:02 #9
Ja men tjacob så vil jeg dele points ud til jer begge.
Jeg vil så dele sådan at du får 125 og nielle 75.

Lyder det rimelig så må nielle lige smide et svar også.

Og ja du har ret tjacob med at når i er fjernet så har jeg jo et andet kort. Det havde jeg ikke lige tænkt over...
Så det ser ud til jeg har lidt at arbejde med når den lille er kommet i seng så igen tak til jer begge.
Avatar billede mega-hawk Nybegynder
06. november 2010 - 19:25 #10
iøvrigt tjacob så havde jeg også selv prøvet ideen med i = CInt((Rnd() * kort.Count - 1))
men kan ikke få den til at virke.

Derfor mit loop.

Tjek lige den her:

Dim i As Integer
        If kort.Count = 0 Then
            MsgBox("Der er ikke flere kort at vælge imellem")
            Exit Sub
        End If
        i = CInt((Rnd() * kort.Count - 1))
        PictureBox1.Image = Image.FromFile(kort(i))
        kort.RemoveAt(i)
        MsgBox("Der er nu " & kort.Count & " tilbage")
    End Sub

Så er problemet når den siger. Der er nu 3 kort tilbage.
Så stopper den hver gang.

Indekset lå uden for området. Det må ikke være negativt og skal være mindre end størrelsen på samlingen.
Parameternavn: index

men hvis jeg nu IKKE filføjer noget til mit arry og trykker på min knap siger den fint nok at der ikke er flere kort.
Har også prøvet med + 1 virker heller ikke
Avatar billede tjacob Juniormester
06. november 2010 - 20:12 #11
Ja, det er lidt mystisk.....

I hvilken linie er fejlen?
PictureBox1.Image = Image.FromFile(kort(i))
eller
kort.RemoveAt(i)


Efter at have studeret Rnd er jeg kommet frem til at du nok skal bruge: i = CInt((Rnd() * kort.Count))

Alternativt kan du bruge .NET random:

Dim Rand as New Random
i = Rand.Next(0, kort.Count)
Avatar billede mega-hawk Nybegynder
06. november 2010 - 20:26 #12
Den melder fejl i picture.
Men ikke så vigtig løkken virker jo ;o)

Har også fået et par andre problemer jeg lige skal have løst :o/
Avatar billede nielle Nybegynder
07. november 2010 - 08:21 #13
Springer bare over på denne her, men ellers tak. :)

Min pointe med at blande kortene var egentlig blot at man så havde blandet dem fra starten og at man derfor efterfølgende kunne vælge 1. kort og dernæst 2. kort og 3. osv. uden at skulle tænke på random senere hen. Det svare jo egentligt til at man blander sine kort *inden* at man begynder at spille - i stedet for at trække et tilfældigt kort midt fra bunken hver gang man skal have et.

Husk i øvrigt Randomize() - ellers får du det samme spil hver eneste gang!
Avatar billede mega-hawk Nybegynder
07. november 2010 - 09:00 #14
ah det er det Randomize er til.

Ja for jeg har tit tænkt over hvorfor man først skriver randomize og så Rnd og tænkte det kunne være folk af gammel vane fra de gamle vb programmer men nu ved jeg det så.

Ja men nielle din ide er også fin så er du sikker på du ikke vil være med til at have points?
Avatar billede nielle Nybegynder
07. november 2010 - 12:12 #15
Takker, men jeg har rigeligt med point i forvejen - laaangt flere end jeg nogen siden vil kunne nå at bruge.

I øvrigt - siden det nu er VB.Net - burde du nok bruge .Net's indbyggede Random (som tidligere nævnt).
Avatar billede mega-hawk Nybegynder
07. november 2010 - 12:21 #16
Bare jeg kunne sige det samme med points ;o)

Ja men alt hvad folk siger angående net tager jeg til mig da jeg er helt ny til dette
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
Kategori
Kurser inden for grundlæggende programmering

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