multidimensional arrays...

BlitzMax Forums/BlitzMax Programming/multidimensional arrays...

Russell(Posted 2005) [#1]
I know I can do this for single dimensional arrays as a shortcut:
Global arr:Int[] = [22,38,4,5,77] ' Very handy

But is this correct for multidimensional arrays:
' Two dimensional array
Global arr:Int[][] = [[2,3],[3,5]]

The reason I ask is because in in the source code for Bob's Bad Day (included as a sample program), there's what appears to be a 2 dimensional definition, but with too many elements:
Global myMap[][] = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,0,0,1,0,0,0,0,0,0,0,1],[1,0,1,0,1,1,1,0,1,1,1,0,1,1,1],[1,0,1,0,0,0,0,0,0,0,1,0,0,0,1],[1,0,0,0,1,1,1,1,1,1,1,1,1,0,1],[1,1,1,0,0,0,0,1,0,0,0,0,0,0,1],[1,0,0,0,1,1,0,1,0,1,1,1,1,0,1],[1,0,1,1,1,1,0,1,0,0,0,0,1,1,1],[1,0,1,0,0,0,0,0,0,1,1,0,0,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,1,0,1],[1,0,0,0,0,1,0,0,0,0,0,0,0,0,1],[1,1,1,1,0,1,0,1,1,1,1,0,1,0,1],[1,0,0,0,0,1,0,0,0,0,1,0,1,0,1],[1,0,1,1,1,1,0,1,1,1,1,0,1,0,1],[1,0,0,0,0,0,0,0,0,0,1,0,1,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]

Can someone explain what's happening here?

Thanks,
Russell


xlsior(Posted 2005) [#2]
Not just a multi-dimensional array: an array of arrays.

Each subarray can actually have different dimensions and number of fields, but they can be grouped together this way.


Tom(Posted 2005) [#3]
It's still 2 dimensional, I think the amount of elements is maybe confusing you. In your line above, myMap = an array of size 16*15 ( a[16][15] ), so each of the slots a[16] holds an array of [15] numbers

a:Int[][] = [[1,2,3],[4,5,6],[7,8,9]]
                  |   |         |
a[0][2] = 3-------^   |         |
a[1][0] = 4-----------^         |
a[2][1] = 8---------------------^


Get it? :)


PowerPC603(Posted 2005) [#4]
Local a:Int[][] = [[1,2,3],[4,5],[6,7,8,9]]

For i = 0 To (a.length - 1)
	For j = 0 To (a[i].length- 1)
		Print a[i][j]
	Next

	Print
Next

Here you see that subarrays really can have different amounts of indexes.

With this code, the first index of a[] has 3 values, as stated with the number of blocks ([...]) inside the whole block.
You see that there are 3 blocks, where the first block has 3 elements, block 2 has 2 elements and block 3 has 4 elements.

So the first (main) array has 3 indexes: a[0], a[1] and a[2].

The subindexes for each mainindex are counted by the number of elements inside each block.
So, at mainindex 0 (a[0]), there are 3 subindexes, because there are 3 elements to be stored ([1,2,3]).
At mainindex 1 (a[1]), there are only 2 subindexes.
At mainindex 2 (a[2]), there are 4 subindexes.

After this declaration (first line of code), you have this setup:
a[0][0] = 1
a[0][1] = 2
a[0][2] = 3

a[1][0] = 4
a[1][1] = 5

a[2][0] = 6
a[2][1] = 7
a[2][2] = 8
a[2][3] = 9

Here you see clearly the each mainindex has different amounts of subindexes.

But can anyone explain why
Local a:Int[][] = [[1,2,3],[4,5],[6,7,8,9]]

works and
a:Int[][] = [[1,2,3],[4,5],[6,7,8,9]]

throws up the error: "Expecting expression but encountered '='"?


Russell(Posted 2005) [#5]
@Tom: Yeah, multidimensional arrays are not explained very well in the manual so I had to do some experiments. I finally figured it out (the shortcut method). Allowing different numbers of elements like in PowerPC603's example threw me a bit at first.

I discovered that no warnings or error messages are given if not all of the elements are given values. (I assume that they are initialized to NULL in this case - Could be wrong. I'll check it out.). This confused the heck out of me, I have to say. This seems to depart quite a bit from other BASICs.

A three dimensional array can be created like this:
Global Arr:Int[][][] = [ ..
		       [ [1,2],[3,4],[5,6],[7,8] ], ..
		       [ [9,10],[11,12],[13,14],[15,16] ] ..
    		       ]
' Is equal to:
Global Arr:Int[2][4][2]

Arr[0][0][0] = 1
Arr[0][0][1] = 2
Arr[0][1][0] = 3

' and so on...

(Thank God for the line extension characters ".."!). And yeah, any of them can be left out (un-initialized). It's weird, but I understand it now (I think).

Thanks everyone,
Russell


Russell(Posted 2005) [#6]
Ok, so if I have an array like this:
Global Arr:Int[][] = [[1,2,3],[4,5]]

...it works. But is there a way to add that 3rd element to the second index after-the-fact? Just wondering. Turns out they are not NULL or maybe they are, but BM won't compile if I reference a 'ghost' element:
If Arr[1][2] = NULL Then Print "Null!"

...will generate an error.

Is it possible?

Russell


Yan(Posted 2005) [#7]
I think you do it like this...
local arr:Int[][] = [[1,2,3], [4,5]]

arr[1] = arr[1][..3]

arr[1][2] = 6
I must admit, I get a bit confused with the syntax of all this arrays of arrays stuff too.

[edit]Just tried it and it seems to work okay....Yipee ;o)[/edit]


PowerPC603(Posted 2005) [#8]
You can also do it like this:
Local arr:Int[][] = [[1,2,3], [4,5]]

arr[1] = arr[1][..(arr[1].length + 1)] ' Add a new element to the second index (subarray)

arr[1][2] = 6


This way you don't have to worry about the number of indexes inside the subarray (second index).
This really is some sort of "add new element" method.


Muttley(Posted 2005) [#9]
Anyone know why I can't do this:
Global mapArray:Int[20][15]

It just returns a "Compile Error:Expression of type 'Int Array' cannot be invoked"

Must admit, arrays are confusing the hell out of me too. :(

Muttley


Russell(Posted 2005) [#10]
@Squating Neville: Thanks, but how did you figure that out? Is there a section of the manual I don't know about or are you and Mark neighbors ;) I've noticed a lot of this "inside information" stuff going on in recent months. Is there some club I need to join? ;)

@PowerPC603: Can you explain your example? It is as clear as mud to me! It looks like it is utilizing slices (which I haven't investigated yet). Is that correct?

@Muttley: Where did you place this statement (not that it should matter), in the main loop? I can't see anything wrong with it, but I did discover that if you have like 20 dimensions it will go looney and also, if you name a variable "b?" (or any variable with a '?' in it) the program will immediately stop. No error. Just full stop.

Thanks for the replies all,
Russell

p.s. This should be in the manual!


TeaVirus(Posted 2005) [#11]
Thanks for the info everyone, I think I'm getting the hang of this also. I seem to be having a little trouble with a 2D array of 2D arrays. The following...
Strict

Local array[,][,]
array=New [10,10]

For Local y=0 Until 10
	For Local x=0 Until 10
		array[x,y]=New [10,10]
	Next
Next

For Local y=0 Until 10
	For Local x=0 Until 10
		For Local yy=0 Until 10
			For Local xx=0 Until 10
				array[x,y][xx,yy]=Rnd(255)
			Next
		Next
	Next
Next


seems to compile and run OK but when the executable closes it crashes. Does this work properly for anyone?


PowerPC603(Posted 2005) [#12]
Local arr:Int[][] = [[1,2,3], [4,5]]

arr[1] = arr[1][..(arr[1].length + 1)] ' Add a new element to the second index (subarray)

arr[1][2] = 6

Yep, the second line uses slices to resize the array.

When using arrays of arrays, BMax uses the first index as a pointer to other arrays (the second index), that's my guess.
So the first line states that there is an array "arr", that holds pointers to two other arrays (as there are 2 blocks defined), where the first array holds 3 elements and the second holds 2 elements.
That's why there can be subarrays of a different size for each index of the main array (arr).

arr[1] = arr[1][..(arr[1].length + 1)]

The second line works like this:
At index arr[1], there's a pointer to an array of size 2 (the array which holds the values 4 and 5).
So, the .length method returns "2" (because that array has 2 elements).
We want to resize the array, so it can hold 1 more element, so we do "arr[1].length + 1", which gives us "3".
The slicing resizes the array with this new value 3, so that the new array has 3 elements inside it.

The last line places a new value (6) inside this new index, that we've just created by resizing the array.


Russell(Posted 2005) [#13]
Thanks for the explanation all!

@Tea Virus: I think you're missing something in the third line 'array = New [10,10]'. Still learning this myself, so I could be wrong. Try defining the whole size of the array in one step like this, instead:
Local array:Int[10,10][10,10]

Let us (well, me!) know if that helps.
Russell


TeaVirus(Posted 2005) [#14]
Russell,
Thanks, but when I try that I get "Expression of type Int Array can't be invoked".

Strict

Local array:int[,][,]
array=New [10,10]

For Local y=0 Until 10
	For Local x=0 Until 10
		array[x,y]=New [10,10]
	Next
Next

Just trying to initialize the array like this the executable seems to just sit there with the CPU utilization at 100%. It eventually needs to be manually stopped. Seems like something like this should work if you can have a 2D array of 1D arrays but maybe not. I'll keep trying and post if I find a solution.