Skapa två dimensionella matriser i Ruby

click fraud protection

Följande artikel är en del av en serie. För mer artiklar i den här serien, se Kloning av spelet 2048 i Ruby. För den fullständiga och slutliga koden, se värdet.

Nu när vi vet hur algoritmen kommer att fungera är det dags att tänka på de data denna algoritm kommer att fungera på. Det finns två huvudval här: en lägenhet array av något slag, eller en tvådimensionell matris. Var och en har sina fördelar, men innan vi fattar ett beslut måste vi ta hänsyn till något.

Torkade pussel

En vanlig teknik för att arbeta med rutbaserade pussel där du måste leta efter mönster som detta är att skriva ett version av algoritmen som fungerar på pusslet från vänster till höger och sedan rotera hela pusslet runt fyra gånger. På detta sätt måste algoritmen bara skrivas en gång och den måste bara fungera från vänster till höger. Detta dramatiskt minskar komplexiteten och storleken av den svåraste delen av detta projekt.

Eftersom vi kommer att arbeta med pusslet från vänster till höger är det vettigt att ha raderna representerade av matriser. När du gör en tvådimensionell matris i

instagram viewer
Rubin (eller mer exakt, hur du vill att den ska adresseras och vad data faktiskt betyder), måste du bestämma om du vill en stapel rader (där varje rad i rutnätet representeras av en matris) eller en stapel kolumner (där varje kolumn är en matris). Eftersom vi arbetar med rader väljer vi rader.

Hur denna 2D-array roteras, kommer vi till efter att vi faktiskt konstruerat en sådan matris.

Konstruera två dimensionella matriser

Metoden Array.new kan ta ett argument som definierar storleken på den matris som du vill ha. Till exempel, Array.new (5) kommer att skapa en matris med 5 noll objekt. Det andra argumentet ger dig ett standardvärde, så Array.new (5, 0) ger dig matrisen [0,0,0,0,0]. Så hur skapar du en tvådimensionell matris?

Fel sätt, och hur jag ser människor som försöker ofta är att säga Array.new (4, Array.new (4, 0)). Med andra ord, en matris med 4 rader, varje rad är en matris med fyra nollor. Och detta verkar fungera till en början. Kör emellertid följande kod:

Det ser enkelt ut. Gör en 4x4-serie med nollor, ställ in det övre vänstra elementet till 1. Men skriv ut det så får vi ...

Den ställde hela den första kolumnen till 1, vad ger? När vi gjorde matriserna kommer det inre mest samtalet till Array.new kallas först och gör en enda rad. En enda referens till denna rad dupliceras sedan fyra gånger för att fylla den yttersta matrisen. Varje rad refererar sedan till samma matris. Ändra en, ändra dem alla.

Istället måste vi använda tredje sätt att skapa en matris i Ruby. I stället för att överföra ett värde till Array.new-metoden passerar vi ett block. Blocket körs varje gång Array.new-metoden behöver ett nytt värde. Så om du skulle säga Array.new (5) {gets.chomp}, Ruby stannar och ber om inmatning 5 gånger. Så allt vi behöver göra är bara att skapa en ny grupp i detta block. Så vi slutar med Array.new (4) {Array.new (4,0)}. Låt oss testa det testfallet igen.

Och det gör precis som du kan förvänta dig.

Så även om Ruby inte har stöd för tvådimensionella matriser, kan vi fortfarande göra det vi behöver. Kom bara ihåg att den översta nivån rymmer referenser till undermatriserna, och varje deluppsättning bör hänvisa till en annan uppsättning värden.

Vad denna grupp representerar är upp till dig. I vårt fall läggs denna matris ut som rader. Det första indexet är raden som vi indexerar, från topp till botten. För att indexera den översta raden i pusslet använder vi a [0], för att indexera nästa rad nedåt använder vi a [1]. För att indexera en specifik kakel i den andra raden använder vi a [1] [n]. Men om vi hade bestämt oss för kolumner... skulle det vara samma sak. Ruby har ingen aning om vad vi gör med denna data, och eftersom det inte tekniskt stöder tvådimensionella matriser är det vi gör här en hack. Få åtkomst till det bara genom konvention och allt kommer att hålla samman. Glöm vad uppgifterna under ska göra och allt kan falla isär snabbt.

instagram story viewer