Kortleksspel
Hej! Jag försöker läsa en kod där en kortlek blandas och delas ut som sker i följande metod:
public void shuffle() {
for (int i = 51; i >= 1; i--) {
int nbr = rand.nextInt(i+1)
Card temp = cards[nbr];
cards[nbr] = cards[i];
cards[i] = temp;
}
}
Jag tänker som så:
1. "int nbr = rand.nextInt(i+1)" där ett slumpmässigt kort tas från högen vi har. En fundering om det nu skulle vara så, hade det inte tagit väldigt lång tid då slumpmässigt tal ej är begränsat? Eller när den väl är i loopen så kan den inte välja tal mindre än eller större än omfånget som anges?
2. Osäker men antar att det nyligen slumpmässigt plockade kortet (Card temp) sätts som ett temporärt kort.
3. En ny likadan lista som cards[nbr] skapas (cards[i]). Antar för att kunna överföra från gamla listan till den nya. Dock tror jag detta blir fel. Vad skulle hända om det slumpmässiga kortet redan är borta (t.ex. plats 30 redan borta), skulle det bli tomt då i den nya?
4. Det slumpmässigt plockade kortet sätts in i en antagligen ny position i den nya listan.
Helheten:
Jag ser det som om man slumpmässigt plockar ut ett kort och sedan lägger från position 0 till 51. Jag må ha skrivit helt tokigt men fråga då!
Jag antar att rand.nextInt(k) ger heltal från 0 till och med k-1. Så det blir aldrig större än 52.
Det görs ingen ny lista, det finns bara listan 'cards'. Man använder en variabel temp för att hålla i ett Card, för att i de tre sista raderna låta cards[nbr] och cards[i] byta plats.
Skriv ut hela 'cards' varje varv i loopen så ser du vad som händer.
Jag tror inte lista är rätt ord, egentligen, utan snarare vektor eller array, men det kan vara lista, och det framgår inte av den här koden och spelar ingen roll för algoritmen.
1. Här väljs bara en slumpmässig int mellan 0 och 52 minus forloopens iteration. Metoden rand.nextInt går från och med 0 till det som anges som argument (endast till, inte till och med).
2. Exakt, om t ex 32 väljs av rand.nextInt så får objektet på som cards[32] pekar på en tillfällig pekare, temp. Detta för att inte glömmas bort när cards[32] ska få ett nytt kort tilldelat.
3. Ingen ny vektor skapas, allt sker i cards[]. Det slumpmässigt valda kortet (32) tilldelas kortet på forloopens iteration (pos 51 i första iterationen). Det som sker är att pekaren ändras i cards[32] till att peka till objektet på cards[51]. På detta sätt skapas inga nya objekt eller vektorer, och ingenting tas heller bort.
4. I cards[i] = temp så tilldelas cards[51] (som nu är en dublett av cards[32]) det ursprungliga objektet på cards[nbr].
Kort sagt, cards[i] och cards[nbr] byter plats.
@adamcl
1. Då har jag skrivit den rätt, "int nbr = rand.nextInt(i+1);" och inte bara "i", eller? Följdfråga1: Om det gäller en kortlek, ska det inte stå int i = 52 istället? Följdfråga2: Kommer loopen att ta EN gång varje värde eller kan det hända att den plockar (i.o.m. "rand.") redan tagna platser som då är tomma?
Vektorer är 0-indexerade i Java, så på position 51 i Cards[] har du kort nummer 52.
i+1 är för att rand.nextInt som sagt går från och med 0 till argumentet (i första loopen 52). 52 är alltså inte med, däremot 51. Nästa loop är det 51 kort kvar och då går rand.nextInt från och med 0 till 51, dvs 0 till 50 = 51 positioner.
Varje kort kommer att hämtas en gång och flyttas till iterationens värde. Om du är i tionde iterationen (i = 41), så kommer rand.nextInt att ta ett slumpmässigt kort på position 0-41 och flytta det till position 41. Nästa iteration lämnas detta kort utanför, då i minskar i varje iteration och det tas ett slumpmässigt kort på position 0-40 (och flyttas till pos 40). På detta sätt flyttas alla kort förutom det sista.
Notera att inga platser är tomma. Cards[x] är en pekare till ett objekt, när Cards[x] och Cards[y] byter plats byter de egentligen bara adress till objekt med varandra (via tempobjektet).
Jag återkommer nu till denna tråd, sorry about that! Jag tolkar det som om det ska stå "for (int i = 51; i >= 0; i--) {
...
}
Plugghingsten skrev:Jag återkommer nu till denna tråd, sorry about that! Jag tolkar det som om det ska stå "for (int i = 51; i >= 0; i--) {
...
}
Det kan du göra, men när i = 0 så finns bara ett kort att välja, så man byter ut det mot sig självt, dvs. inget händer.
Men om det står "for (int i = 51; i >= 1; i--) {" så kommer aldrig kort nummer 1 väljas då nästa rag säger "i+1" vilket kommer som lägst bli 2.
Plugghingsten skrev:Men om det står "for (int i = 51; i >= 1; i--) {" så kommer aldrig kort nummer 1 väljas då nästa rag säger "i+1" vilket kommer som lägst bli 2.
Då tar man de två första (sista, lägsta, nånting) korten och bestämmer slumpmässigt om man ska låta dem byta plats eller inte.
Jag förstår fortfarande inte helt:
1. En loop mellan 0 och 51 inleds (loopar 52 ggr).
2. Ett slumpmässigt nummer i taget tas mellan 2 och 52.
Det är dessa stegen jag förvirras i. De resterande har jag numera koll på. Jag tolkar det som att loopen genomförs 52 gånger. Dock när ett slumpmässigt tal bestäms förstår jag inte. Jag trodde det var som så att om t.ex. 10 väljs från rand så får objektet cards[10] och har en pekare temp som pekar på detta kort. Detta kort får översta positionen i kortleken. Så i slutet, då det kanske bara finns 40 kvar, cards[40]. Pekaren pekar på detta kort. Detta kort tilldelas kortet på for-loopens iteration (pos 0 då det är sista kortet).
Provar jag att skriva "int i = 51; i >= 0; i--" så bör det fungera. Men som jag tolkar dig så kommer ett kort alltid få samma position. Testar jag köra min kod flera gånger om ser jag att det inte alls blir samma position. Förlåt att jag inte förstår men jag vill förstå.
1:En loop mellan 51 och 0 inleds
Ja, så klart (har redigerat föregående kommentar).
Jag förstår inte alls det här som du skriver: "så får objektet cards[10] och har en pekare temp" och "tilldelas kortet på for-loopens iteration", så jag vet inte vad som är oklart.
Ta t.ex. sex kort i stället för 52 och kör igenom koden för hand, på papper.
Eller kör koden på riktigt, med spårutskrifter.
Förlåt för besväret, förstår det nu igen. Att du inte förstod kan bero på att jag kan skriva oförståeligt då jag "skriver högt" ( som när man tänker högt). Samt att i detta fall inte granskade vad jag hade skrivit.