Il seguente articolo fa parte di una serie. Per altri articoli di questa serie, vedi Cloning the Game 2048 in Ruby. Per il codice completo e finale, vedere l'essenza.
Ora che sappiamo come funzionerà l'algoritmo, è tempo di pensare ai dati su cui lavorerà l'algoritmo. Ci sono due scelte principali qui: un appartamento Vettore di qualche tipo, o una matrice bidimensionale. Ognuno ha i suoi vantaggi, ma prima di prendere una decisione, dobbiamo prendere in considerazione qualcosa.
Puzzle DRY
Una tecnica comune nel lavorare con puzzle basati su griglia in cui devi cercare schemi come questo è scriverne uno versione dell'algoritmo che funziona sul puzzle da sinistra a destra e quindi ruota l'intero puzzle di quattro volte. In questo modo, l'algoritmo deve essere scritto solo una volta e deve funzionare solo da sinistra a destra. Questo riduce drasticamente la complessità e le dimensioni della parte più difficile di questo progetto.
Dal momento che lavoreremo sul puzzle da sinistra a destra, ha senso avere le file rappresentate da array. Quando si crea un array bidimensionale
Rubino (o, più precisamente, come vuoi che vengano indirizzati e cosa significhino effettivamente i dati), devi decidere se vuoi una pila di righe (in cui ogni riga della griglia è rappresentata da un array) o una pila di colonne (in cui ogni colonna è un array). Poiché stiamo lavorando con le righe, sceglieremo le righe.Come viene ruotato questo array 2D, vedremo dopo aver effettivamente costruito un tale array.
Costruzione di matrici bidimensionali
Il metodo Array.new può accettare un argomento che definisce le dimensioni dell'array desiderato. Per esempio, Array.new (5) creerà un array di 5 oggetti nulli. Il secondo argomento fornisce un valore predefinito, quindi Array.new (5, 0) ti darà l'array [0,0,0,0,0]. Quindi, come si crea un array bidimensionale?
Il modo sbagliato e il modo in cui vedo le persone provarci spesso è dire Array.new (4, Array.new (4, 0)). In altre parole, una matrice di 4 righe, ciascuna delle quali è una matrice di 4 zero. E questo sembra funzionare all'inizio. Tuttavia, eseguire il codice seguente:
Sembra semplice Crea un array 4x4 di zero, imposta l'elemento in alto a sinistra su 1. Ma stampalo e otteniamo ...
Imposta l'intera prima colonna su 1, cosa dà? Quando abbiamo creato gli array, la chiamata più interna ad Array.new viene chiamata per prima, formando un'unica riga. Un singolo riferimento a questa riga viene quindi duplicato 4 volte per riempire l'array più esterno. Ogni riga fa quindi riferimento allo stesso array. Cambia uno, cambiali tutti.
Invece, dobbiamo usare il terzo modo di creare un array in Ruby. Invece di passare un valore al metodo Array.new, passiamo un blocco. Il blocco viene eseguito ogni volta che il metodo Array.new richiede un nuovo valore. Quindi se dovessi dirlo Array.new (5) {gets.chomp}, Ruby si fermerà e chiederà input 5 volte. Quindi tutto ciò che dobbiamo fare è semplicemente creare un nuovo array all'interno di questo blocco. Quindi finiamo con Array.new (4) {Array.new (4,0)}. Ora proviamo di nuovo quel test.
E fa esattamente come ti aspetteresti.
Quindi, anche se Ruby non supporta gli array bidimensionali, possiamo ancora fare ciò di cui abbiamo bisogno. Basta ricordare che l'array di livello superiore contiene Riferimenti agli array secondari e ciascun array secondario dovrebbe fare riferimento a un array di valori diverso.
Ciò che questa matrice rappresenta dipende da te. Nel nostro caso, questo array è strutturato come righe. Il primo indice è la riga che stiamo indicizzando, dall'alto verso il basso. Per indicizzare la riga superiore del puzzle, usiamo a [0], per indicizzare la riga successiva in basso che usiamo un [1]. Per indicizzare un riquadro specifico nella seconda riga, utilizziamo un [1] [n]. Tuttavia, se avessimo deciso sulle colonne... sarebbe la stessa cosa. Ruby non ha idea di cosa stiamo facendo con questi dati e dal momento che non supporta tecnicamente array bidimensionali, quello che stiamo facendo qui è un hack. Accedilo solo per convenzione e tutto andrà insieme. Dimentica ciò che i dati sottostanti dovrebbero fare e tutto può andare in pezzi molto velocemente.