One solution is to read the next cell, and go copy it in position before
coming back to read the second cell. But since it is forbidden to use the
methods to teleport the buggle to a specific position (setPos()
and similar), this approach will be a pain to implement.
The simplest is to store the sequence of colors that constitute the whole pattern in an [!java|scala]array[/!][!python]list[/!]. But before we can do so, we should learn a bit what [!java|scala]arrays[/!][!python]lists[/!] are.
[!java|scala]An array[/!][!python]A list[/!] is an ordered sequence of variables that go together.
It is somehow similar to a shelve where each level can store a separate value. Each
variable of the sequence is identified by its position, and can store
a specific value. [!java|scala]All cells of the array must store values of the same
type because arrays are homogeneous in [!thelang]. It is possible to trick this
restriction by using the datatype [!java]Object[/!][!scala]Any[/!]
that can contain [!java]almost[/!] any other datatype. [!java]Primitive types such
as the ones we saw so far (int, boolean, double, char, etc) cannot be stored in an
Object variable, but their objectified counter-part (Integer, Boolean, Double,
Char, Boolean, etc) can.[/!] It is however a good practice to make the type of an array
as specific as possible, i.e., if you plan to store some integers in your array, make it an
array of integers, not of [!java]Object[/!][!scala]Any[/!].[/!]
[!python]Lists can even mix values of differing types, such as integer values in some cells and colors in other cells.[/!]
T is the [!java|scala]array[/!][!python]list[/!]'s name, [!java|python]T[0][/!][!scala]T(0)[/!] is the name of the first cell, [!java|python]T[1][/!][!scala]T(1)[/!] the name of the second cell, [!java|python]T[2][/!][!scala]T(2)[/!] the third one, etc. And yes, the first cell is numbered [!java|python]T[0][/!][!scala]T(0)[/!] while the last one of [!java|scala]an array[/!][!python]a list[/!] of size N is [!java|python]T[N-1][/!][!scala]T(N-1)[/!]. It may seem funny to count starting from 0 and not from 1 as usual, but some historical reasons make it unavoidable here.
We can use an integer variable i to access with [!java|python]T[i][/!][!scala]T(i)[/!] to the
cells: when the value of i is 0, then [!java|python]T[i][/!][!scala]T(i)[/!] accesses
[!java|python]T[0][/!][!scala]T(0)[/!];
when the value of i is 10, then [!java|python]T[i][/!][!scala]T(i)[/!] accesses
[!java|python]T[10][/!][!scala]T(10)[/!].
i is said to be the index in T.
[!java|python]T[i][/!][!scala]T(i)[/!]
can be used just like any
variable. We can set a new value:
[!java|python]T[i][/!][!scala]T(i)[/!] = 78[!java];[/!]
We can retrieve and use its value:
x = [!java|python]T[i][/!][!scala]T(i)[/!][!java];[/!]
We can test this value:
if ([!java|python]T[i][/!][!scala]T(i)[/!] > 0) [!scala|java]{[/!][!python]:[/!] [!java|scala]//[/!][!python]#[/!] instructions... [!java|scala]}[/!]
It is very easy to traverse the whole [!scala|java]array[/!][!python]list[/!], for example to initialize each cells.
[!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.[/!]
If you just want to iterate over the values of T without keeping track of their index, you can simply write:
[!java]for (int i: T) {[/!][!scala]for (i <- T) {[/!][!python]for i in T:[/!] action()[!java];[/!] [!java|scala]}[/!]
[!java]This construct is called an extended loop in Java. The variable i takes all values
of the set located to the right of the colon (:), one after the other.[/!]
[!python|scala]This is actually very similar to the previous construct.
Simply, [!python]range(n)[/!][!scala]i to j[/!]
returns a set of integers over which the
for construct iterates.
Actually, [!thelang] offers much more elegant ways to traverse [!python]lists[/!][!scala]arrays[/!] and
other data collections, but this should be the topic of a specific set of exercises (that are still to be
written in PLM).[/!]
If you know beforehand the content of your list, you can affect these values all together. Just put them between square braces and separated by commas as follows:
L = [1, 3, 5, 7, 9]
# L is now an array of 5 values, all of them being integers
Otherwise, you probably want to create an empty list and then append each values separately to the list:
L2 = [] # L2 is now an empty list L2.append(1) L2.append(3) L2.append(5) L2.append(7) L2.append(9) # Its content is now the same as L previously[/!] [!java|scala]
To declare a variable named T that can store arrays of integers, one should write:
[!java]int[] T;[/!][!scala]var T:Array[Int][/!]
[!java]int
means that the elements of the array are of type integer;
[]
means that we are speaking of an array and T
is the name of the variable.
For historical reasons, this can also be written as int T[]
(with the [] after the variable name),
but this is less readable and should probably be avoided.[/!]
[!scala]The [Int]
notation specializes the Array type (that is generic), specifying that each cell
of this array is an integer. An array of booleans would simply by written Array[Boolean]
.[/!]
Declaring a variable T
that stores an array only reserve the name T
for
later use, but not the memory area to store the cells. The array is not initialized yet: it does not have any
value. What would [!java]T[4][/!][!scala]T(4)[/!]
mean if we didn't say that the array is
5 cells long?
First and foremost, we have to give a value to T
:
[!java]T = new int[10];[/!][!scala]var T = new Array[Int](10)[/!]
new
means that we want to create something, and
[!java]int[10][/!][!scala]Array[Int](10)[/!]
means that it is an array of 10 integer values.
In return, an array of 10 integer cells is created in memory, and the T
variable
references this array.
The size of an array is fixed and cannot be changed after the creation of
the array. The size of a T
array can be retrieve by consulting the
variable 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];
[/!]
If you know beforehand the content of your array, you can declare, allocate and initialize it in one shoot:
[!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)[/!]
To know the size of the array to allocate, the compiler counts the provided values. This code is equivalent to:
[!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[/!]
It is also equivalent to:
[!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 }[/!][/!]
It is perfectly OK to pass [!python]a list[/!][!java|scala]an array[/!] to a method as a parameter. This method can then use this parameter as if it were defined locally:
[!java]boolean has42First(int[] array) { return array[0] == 42; }[/!][!python]def has42First(list): return list[0] == 42[/!][!scala]def has42First(array:Array[Int]):Boolean = { return array(0) == 42 }[/!]
On the caller side, that also very simple:
[!java]int[] tab = new int[10];[/!][!scala]var tab = new Array[Int] (10)[/!][!python]tab = [1, 3, 5, 7, 9][/!] [!java|scala]// Values initialization omitted [/!]if (has42First(tab))[!java|scala] {[/!][!python]:[/!] [!java|scala]//[/!][!python]#[/!] do something [!java|scala]}[/!][!java]
If you want to allocate and initialize the array in one shoot, that's a bit more complicated as the compiler has to know the type of the parameter you are creating. For that, use the following (ugly) construct:
if (has42First( new int[] {1, 3, 5, 7, 9} ) {
// do something
}
[/!]
Methods can also return [!java|scala]arrays[/!][!python]lists[/!] as result without any complication. Here is a method that returns [!java|scala]an array[/!][!python]a list[/!] of the requested size, filled with 42s.
[!java]int[] fill42(int size) { int[] res = new int[size]; for (int i=0; i<size; i++) res[i] = 42; return res; }[/!][!scala]def fill42(size:Int):Array[Int] = { var res = new Array[int] (size) for (i <- 0 to size -1) { res(i) = 42; } return res; }[/!][!python]def fill42(size): res = [] for i in range(size): res.append(42) return res[/!]
At least! After this long explanation, we can come back to the exercise.
Your mission is rather simple actually.
Your code should save the color pattern observed on the first row into [!java|scala]an array[/!][!python]a list[/!].
[!python]The easiest is to create an empty list, and then append()
the colors one after the others as
you read them (with getGroundColor()
).[/!]
[!java|scala]For that, you should declare and allocate an array of Color
. Beware, there is several
worlds, of differing size; use getWorldHeight()
to retrieve the size of the current world.
Once the array allocated, fill it by reading the ground color in each locations (with getGroundColor()
).[/!]
Once you managed to read and save the pattern on the first row, you have to reapply the
pattern on every rows, for example by executing getWorldHeight()
times
a method written specifically for this.