Snabbtips Blanda kort (eller några element) med Fisher-Yates Shuffle Algorithm

I denna Snabba Tips, kommer jag att visa dig hur du implementerar Fisher-Yates shuffle-algoritmen. När vi har lärt oss hur det fungerar kommer vi att använda det för att blanda en virtuell kortspel.

Notera: Även om denna handledning skrivs med JavaScript bör du kunna använda samma tekniker och begrepp i nästan vilken spelutvecklingsmiljö som helst.


1. Introduktion till algoritmen

Det finns flera sätt att blanda en uppsättning element, vilket visas i detta inlägg. Medan de är alla giltiga alternativ, är den metod som jag alltid använt den som implementerades av Fisher-Yates Shuffle Algorithm.

Jag gillar den här metoden eftersom den gör en "in place" shuffle utan att behöva skapa en ny array (eller vilken datastruktur du brukar använda).


2. Använda algoritmen

Om du gav Wikipedia-sidan en snabb läsning, så har du sett det nämner ett par olika sätt att implementera algoritmen. Den vi ska använda kallas "Modern Method":

För att blanda en matris a av n-element (index 0 ... n-1): för jag från (n - 1) till 1 ställer du j till ett slumpt heltal med 0 ≤ j ≤ jag byter a [j] och en [i ]
  1. Du börjar med det sista elementet i listan (det övre kortet i däcket, om du vill).
  2. Du väljer ett annat element slumpmässigt mellan den första och din valda.
  3. Du byter dessa två element.
  4. Du väljer det sista men ena elementet i listan (det andra kortet i däcket) och upprepa # 1- # 3 tills du når botten av däcket.

Jag har sammanställt en visuell demo som visar de steg som algoritmen tar. Förhoppningsvis gör den ovanstående förklaringen tydligare:


Översätt detta till a för slingan skulle se ut så här:

var someArray = [1,2,3,4,5,6,7,8,9]; var theLength = someArray.length - 1; var toSwap; // Indexet vi ska byta (dvs slumpmässigt tal) var temp; // En temporär variabel för att hålla referens till indexvariabelen jag poängerar för (i = theLength; i> 0; i--) toSwap = Math.floor (Math.random () * i); temp = someArray [i]; someArray [i] = someArray [toSwap]; someArray [toSwap] = temp; 

Anledningen till att vi behöver temp variabel beror på att vi behöver referens till det första elementet. Om vi ​​inte hänvisade till det första elementet, då vi bytte ut det andra elementet med det första, skulle vi förlora det första elementet. Eftersom det första elementet nu är lika med det andra, då vi bytte ut det första med det andra skulle det vara "det andra elementet", eftersom det andra elementet nu är på första platsen. Genom att hänvisa till det första objektet kan vi sedan ställa in det andra elementet lika med det istället.


3. Att sätta algoritmen i praktiken

Ovanstående demonstration är trevlig för en visuell representation av hur algoritmen fungerar, men för att uttrycka den för verklig världsanvändning kommer vi nu att använda den för att blanda vissa virtuella kort. Nedan är koden.

$ (funktion () var serverString = "http://source.tutsplus.com/gamedev/authors/JamesTyner/FisherYates/src/images/"; var kort = []; var jag; för (i = 1; i <= 13; i++)  cards.push("c" + i);  //console.log(cards); function drawCards() $("#holder").empty(); for (i = 0; i < cards.length; i++)  $("#holder").append(""); drawCards (); $ (" # shuffle ") på (" klicka ", blanda); var theLength = cards.length - 1; var toSwap; var tempCard; funktionsstöd () console.log "Kort före shuffle:" + kort); för (i = längden; i> 0; i--) toSwap = Math.floor (Math.random () * i); tempCard = kort [i]; kort [i ] = kort [toSwap]; kort [toSwap] = tempCard; console.log ("Kort efter blandning:" + kort); drawCards (););

Här skapar vi ett däck med tretton kort, och sedan blandar dem när shuffle-knappen trycks ned. Fisher-Yates Shuffle-algoritmen implementeras i blanda() fungera.

Jag har skapat en annan demo för att visa detta i åtgärd, men du kan också prova det själv med filerna som ingår i den här handledningens nedladdningsbara tillgångar.


4. Slutsats

Fisher-Yates Shuffle-algoritmen är ett av flera sätt att implementera shuffling inom dina applikationer. Det finns inget behov av att skapa nya arrayer, eftersom det gör shuffle på plats. Jag är en stor fan av denna shuffle-algoritmen, och kanske är du nu också.

Tack för att du läste och jag hoppas att du har hittat denna handledning användbar.