Wednesday, October 15, 2008

XNA Sidebar - Converting a single index into multiple

I was playing around with some coding ideas and thought about this. Say you have a 5x5 grid defined in a multidimensional array int[5,5] and then you create an array of object that will be placed in that grid. Say you want to refer to those grid entries as 0-24 rather than [0,0][0,1]...[4,3][4,4] a neat way to do it is with a little integer math. Division in integers is whole number division and we use the modulus operator to get remainder. So if we know the width of our grid (in this case 5), we can say

int x = 7;
int wid = 5;
grid[x/wid][x%wid];

would give us

grid[1][2]

which if we line things up

0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24


we see that the index 7 is the second row, 3rd column, which in 0 based notation is 1,2. You may have already known this, but I thought it was pretty handy.

1 comment:

archimedes22 said...

This works for Wid x Wid grid, but stops working when the grid is not "square" (or when its "jagged").

Alternate approach #1:
j
0 1 2 3 4
====================
0|| [0] 1 2 3 4
i 1|| [5] 6 7 8 9
2|| [10] 11 12 13 14

Wid = 5

Notice: [0][5][10]~(i*wid)

So: (i * wid) + j = k
(where "k" is 0-14)

and: i = (k-j)/wid
j = k - (i* wid)

check: @k = 4, (i,j) = (0,4)
(0*5)+4 = 4 (correct)

Alternate approach #2 (jagged array):

j
0 1 2 3 4
=================
0|| [0] 1 2 3 4{x=-1}
i 1|| [5] 6 7 8 {x=4}
2|| [9] 10 11 {x=8}

except for the first row,
set "x" to be the value of the last entry of the previous row ..

for the first row, it will work if we assume x = -1 ..

Notice: x+1 = [value]
check: -1+1 = [0]
4+1 = [5]
8+1 = [9]

In other words, the final entry of the previous row is always 1 less than the first entry of the next row (this is true for non-jagged arrays also).

This relationship of "x" takes the place of (i* wid) used above in approach #1.

So: (x+1) + j = k

check: @k = 10, (i,j) = (2,1), x = 8
(8+1)+1 = 10 (correct)

This equation of approach #2 works for non-jagged arrays also, but the equation for approach #1 incorporates _both_ "i" and "j", which some might prefer.