Una soluzione è quella di leggere la cella successiva e copiarla prima di
tornare indietro a leggere la seconda cella. Ma visto che non è consentito
l'utilizzo del metodo per teletrasportare il buggle in una specifica
posizione (setPos()
e simili), questo approccio sarebbe
faticoso da implementare.
Il modo più semplice è quello di salvare la sequenza di colori che costituisce l'intero pattern in un [!java|scala]vettore[/!][!python]a lista[/!]. Ma prima di poterlo fare dobbiamo imparare un po' di quello che c'è da sapere su[!java|scala]i vettori[/!][!python]lle liste[/!].
[!java|scala]Un vettore[/!][!python]Una lista[/!] è una sequenza ordinata di
variabili unite insieme. È in qualche modo simile ad una ripiano dove ogni
scaffale può contenere un valore separato. Ogni variabile della sequenza
viene identificata dalla sua posizione e può contenere un valore
specifico. [!java|scala]Tutte le celle del vettore devono ospitare valori
dello stesso tipo perché in [!thelang] i vettori sono omogenei. È possibile
aggirare questa restrizione utilizzando il tipo di dato
[!java]Object[/!][!scala]Any[/!]
che può contenere
[!java]quasi[/!] ogni altro tipo di dato. [!java]I tipi primitivi che
abbiamo visto fin ora (int, boolean, double, char, ...) non possono essere
memorizzati in un "Object" (Ndt Oggetto) variabile, ma le loro oggettificate
controparti (Integer, Boolean, Double, Char, Boolean, etc) possono.[/!]
Continua comunque ad essere una buona pratica quella di rendere il tipo di
un vettore il più specifico possibile, e cioé se pianificate di memorizzare
solo dei numeri interi in un vettore, create un vettore di interi, non un
[!java]Object[/!][!scala]Any[/!].[/!] [!python]Le liste possono contenere
mix di tipi di dato differenti, come valori interi in alcune celle e colori
nelle atre.[/!]
T è il nome del[!java|scala] vettore[/!][!python]la lista[/!], [!java|python]T[0][/!][!scala]T(0)[/!] È il nome della prima cella, [!java|python]T[1][/!][!scala]T(1)[/!] quello della seconda, [!java|python]T[2][/!][!scala]T(2)[/!] quello della terza, ... Eh sì, la prima cella è numerata [!java|python]T[0][/!][!scala]T(0)[/!] mentre l'ultima di un[!java|scala] vettore[/!][!python]a lista[/!] di dimensione N è [!java|python]T[N-1][/!][!scala]T(N-1)[/!]. Potrebbe sembrare strano contare iniziando da 0 e non da 1 come si fa solitamente ma alcune ragioni storiche hanno reso questa pratica inevitabile.
Possiamo utilizzare una variabile intera chiamata i per accedere alla
cella attraverso [!java|python]T[i][/!][!scala]T(i)[/!]: quando il valore di
i sarà 0, allora [!java|python]T[i][/!][!scala]T(i)[/!] accederà a
[!java|python]T[0][/!][!scala]T(0)[/!] mentre se il valore di i è 10,
allora [!java|python]T[i][/!][!scala]T(i)[/!] accederà a
[!java|python]T[10][/!][!scala]T(10)[/!]. La variabile i viene
chiamata indice di T.
[!java|python]T[i][/!][!scala]T(i)[/!]
può essere usato alla
stregua di una qualsiasi altra variabile. Possiamo assegnargli un nuovo
valore:
[!java|python]T[i][/!][!scala]T(i)[/!] = 78[!java];[/!]
Possiamo recuperane ed usare il suo valore:
x = [!java|python]T[i][/!][!scala]T(i)[/!][!java];[/!]
Possiamo testare il suo valore:
if ([!java|python]T[i][/!][!scala]T(i)[/!] > 0) [!scala|java]{[/!][!python]:[/!] [!java|scala]//[/!][!python]#[/!] instruzioni... [!java|scala]}[/!]
È molto semplice scorrere l'inter[!scala|java]o vettore[/!][!python]a lista[/!], per esempio per inizializzare ogni cella:
[!java]for (int i = 0; i<T.length; i++) {[/!][!python]for i in range(len(T)):[/!][!scala]for (i <- 0 to T.length-1) {[/!] [!java|python]T[i][/!][!scala]T(i)[/!] = 3[!java];[/!] [!java|scala]}[/!]
[!java|scala]The notation T.length
retrieves the length of the
array T,[/!] [!python]The function len()
retrieves the length
of the list T,[/!] allowing to build a classical for loop easily.
[!python]Actually, the len()
function is much more generic and
can be used to retrieve the length of many objects. Applied to strings for
example, it returns the amount of chars in this string.[/!] [!scala]Don't
forget to start at 0
and stop at T.length-1
instead of 1
to T.length
however.[/!]
Se volete iterare solo sui valori di T senza tenere traccia dell'indice, potete semplicemente scrivere:
[!java]for (int i: T) {[/!][!scala]for (i <- T) {[/!][!python]for i in T:[/!] azioni()[!java];[/!] [!java|scala]}[/!]
[!java]Questo costrutto in Java è chiamato extended loop (Ndt non so
tradurlo, è un ciclo for each). La variabile i prende tutti i valori
del vettore posizionato a destra dei due punti (:), uno alla volta.[/!]
[!python|scala]Quello che accade è molto simile a ciò che accadeva nel
costrutto precedente. Semplicemente [!python]range(n)[/!][!scala]i to
j[/!]
ritorna una serie di numeri interi che il costrutto for
utilizza per ripetersi. Attualmente [!thelang] offre modi più eleganti di
scorrere [!python]una lista[/!][!scala]un vettore[/!] ed altri tipi di
collezioni di dati ma questo sarà l'argomento di un'altra serie di esercizi
a parte (che peraltro devono ancora essere scritti in PLM).[/!]
Se già conosci il contenuto della tua lista puoi assegnarli subito tutti i valori direttamente. Semplicemente metteteli fra parentesi quadrate e separateli con una virgola come nell'esempio seguente.
L = [1, 3, 5, 7, 9]
# L è ora una lista di 5 valori, tutti loro sono interi
In alternativa potreste voler creare una lista vuota ed aggiungerle separatamente ogni valore.
L2 = [] # L2 è ora una lista vuota L2.append(1) L2.append(3) L2.append(5) L2.append(7) L2.append(9) # adesso il suo contenuto è lo stesso di L[/!] [!java|scala]
To declare a variable named T that can store an array of integers, one should write:
[!java]int[] T;[/!][!scala]var T:Array[Int][/!]
[!java]int
significa che gli elementi del vettore sono di tipo
intero; []
significa che stiamo parlando di un vettore e
T
è il nome della variabile. Per motivi storici è possibile
anche scrivere int T[]
(con le [] dopo il nome della variabile)
ma questo è meno leggibile e andrebbe evitato.[/!] [!scala]La notazione
[Int]
specializza il tipo del vettore (che sarebbe generico)
specificando che ogni sua cella contiene un intero. Similmente un vettore di
booleani si scriverà Array[Boolean]
.[/!]
Dichiarare una variabile T
fa semplicemente posto ad un vettore
riservandogli il nome T
per usi successivi ma non gli
riserva dello spazio di memoria per contenere le sue celle. Il vettore non è
ancora stato inizializzato: esso non ha nessun valore. Che potrebbe mai
voler dire [!java]T[4][/!][!scala]T(4)[/!]
se non abbiamo
ancora stabilito che il vettore è lungo 5 celle?
Prima di tutto dobbiamo dare un valore a T
:
[!java]T = new int[10];[/!][!scala]var T = new Array[Int](10)[/!]
new
significa che noi vogliamo creare qualcosa e
[!java]int[10][/!][!scala]Array[Int](10)[/!]
significa che
quello che vogliamo creare è un vettore di 10 valori interi. Di consegueza
in memoria viene creato un vettore di 10 celle di interi e la variabile
T
ci referenzierà ad esso.
La dimensione del vettore sarà fissa e non potrà essere cambiata dopo la sua
creazione. Potremo conoscere la dimensione di T
consultando la
variabile T.length
.
While allocating, you can specify the size with a variable:
[!java]int[] T = new int[i];[/!][!scala]var T = new
Array[Int](i);[/!]
In this case, the array's size will be set to the
value of i
when new
gets called. The size
of the array still cannot be modified: even if the variable i
changes afterward, the size remains to the value given when it was
allocated. [!java]Also, it is forbidden to write something like int
T[10];
when declaring the variable. You are required to use the
new
instruction to allocate it, as in int[] T = new
int[10];
[/!]
Se siete già a conoscenza del contenuto del vostro vettore potete dichiarare, allocare ed inizializzare tutto contemporaneamente, in un sol colpo:
[!java]int[] T = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };[/!][!scala]var T = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)[/!]
Per conoscere la dimensione del vettore da allocare il compilatore conta i valori fornitigli. Questo codice è equivalente ad:
[!java]int[] T = new int[10]; T[0] = 1; T[1] = 2; ... T[9] = 10;[/!][!scala]var T = new Array[Int](10); T(0) = 1 T(1) = 2 ... T(9) = 10[/!]
Che è anche equivalente a:
[!java]int[] T = new int[10]; for (int i=0; i<T.length; i++) { T[i] = i+1; }[/!][!scala]var T = new Array[Int](10); for (i <- 0 to T.length-1) { T(i) = i+1 }[/!][/!]
È perfettamente valido passare [!python]una lista[/!][!java|scala]un vettore[/!] come parametro di un metodo. Il metodo può quindi utilizzare questo parametro come se fosse stato definito localmente:
[!java]boolean haPrima42(int[] vettore) { return array[0] == 42; }[/!][!python]def haPrima42(lista): return lista[0] == 42[/!][!scala]def haPrima42(vettore:Array[Int]):Boolean = { return vettore(0) == 42 }[/!]
Anche dalla parte del chiamante del metodo la cosa è molto semplice:
[!java]int[] etichetta = new int[10];[/!][!scala]var etichetta = new Array[Int] (10)[/!][!python]etichetta = [1, 3, 5, 7, 9][/!] [!java|scala]// Valore di inizializzazione omesso [/!]if (haPrima42(etichetta))[!java|scala] {[/!][!python]:[/!] [!java|scala]//[/!][!python]#[/!] fai qualcosa [!java|scala]}[/!][!java]
Se cerchi di allocare ed inizializzare il vettore in un colpo solo la cosa si fa' un po più complicata perché il compilatore dovrà conoscere il tipo dei parametri che stai creando. Per poterlo fare utilizza questo (brutto) costrutto:
if (haPrima42( new int[] {1, 3, 5, 7, 9} ) {
// fai qualcosa
}
[/!]
I metodi possono anche ritornare [!java|scala]vettori[/!][!python]liste[/!] come risultati senza nessuna complicazione. Quì mostrato c'è un metodo che ritorna [!java|scala]un vettore[/!][!python]una lista[/!] della dimensione richiesta e riempito di 42.
[!java]int[] riempiDi42(int dimensione) { int[] ris = new int[dimensione]; for (int i=0; i<dimensione; i++) ris[i] = 42; return ris; }[/!][!scala]def riempiDi42(dimensione:Int):Array[Int] = { var ris = new Array[int] (dimensione) for (i <- 0 to dimensione -1) { ris(i) = 42; } return ris; }[/!][!python]def riempiDi42(dimensione): ris = [] for i in range(dimensione): ris.append(42) return ris[/!]
Finalmente! Dopo questa lunga spiegazione possiamo ritornare al nostro esercizio.
La tua missione è abbastanza semplice. Il tuo codice dovrà memorizzare il
patter di colori osservati nella prima colonna in [!java|scala]un
vettore[/!][!python]una lista[/!]. [!python]Il modo più facile è quello di
creare una lista vuota e dopo usare il metodo append()
per
inserirci i colori uno dopo l'altro nell'ordine in cui li leggi (con
getGroundColor()
).[/!] [!java|scala]Per poterlo fare devi
dichiarare ed allocare un vettore di Color
. Ma fai attenzione,
ci sono diversi mondi di diverse dimensioni, usa la funzione
getWorldHeight()
per venire a conoscenza dell'altezza del mondo
corrente. Quando il vettore sarà allocato, riempilo leggendo il colore sul
pavimento in ogni locazione (con getGroundColor()
).[/!]
Quando sarai riuscito a leggere ed a salvare il pattern della prima colonna
dovrai riapplicarlo su tutte le altre, per esempio eseguendo il metodo che
hai scritto a questo scopo un numero di volte pari al valore di ritorno di
getWorldHeight()
. (Ndt potrebbe essere utile sapere che esiste
anche il metodo getWorldWidth() che ci dice la lunghezza del mondo)