In C# the concept of Multidimension arrays are pretty cool. But I don't understand when to use them. Like in what type of applications does this concept is used.
Imagine you want to program a chess game. How would you represent the board with an unidimensional array?
Not to sound trite but you use multidimensional arrays when you have multidimensional data.
Matrices are a common example but it could just as easily be a game board (eg Chess) or as the data model for an N-dimensional maze or a tally or anything really.
While I am sure others can provide many different examples, I work with robots and one of the many task robots perform is palletizing, placing item in a row and column formation on a pallet. Each location on the pallet is a set 2 or even 3 dimension indexes of an array.
locationArrayt[ row , column]
We also use them for multilingual applications. An array of strings represent the different error messages, the second index is the language.
message[errorNumber, language]
This snippet of Java might enlighten you... it reads a file into a two-dimensional array. It's part of my MazeOfBolton solution (google it).
/**
* Reads the file into a char[rows][cols] matrix.
* @param String filename - the name of the file to read
* @return a two-dimensional array of chars containing file contents.
*/
private static char[][] readMatrix(String filename) throws IOException {
BufferedReader input = null;
try {
input = new BufferedReader(new FileReader(filename));
List<String> lines = new ArrayList<String>();
String line = null;
while ( (line = input.readLine()) != null ) {
lines.add(line);
}
int rows = lines.size();
char[][] matrix = new char[rows][];
for (int i=0; i<rows; i++) {
matrix[i] = lines.get(i).toCharArray();
}
return matrix;
} finally {
if(input!=null)input.close();
}
}
EDIT: I should say why I used a matrix... especially as I had to built a List to get the array... Huh? Why not just use the List? The short answer is speed.
Accessing an array (of however many dimensions) is implemented (under the hood) as "index arithmetic" (aka pointer arithmetic), so not only is it accessing an array element O(1), it's fast O(1)... much much faster than the equivalent arrayList.get(int index) (when you do so a couple-of-million times)... and in the (admitedly artificial) world of algorithm racing, speed is everything.
Cheers. Keith.
As a side point, you can either use multidimensional arrays (int[,]) or jagged arrays (int[][]). The former can be initialized in one step, but requires a larger contiguous block of memory and is slower to access, whereas the latter is more memory-friendly as the sub-arrays can be spread over the address space, each sub-array can be a different length, and all single-dimensional arrays (SZarrays) have special optimizations in the CLR. However, you do need to initialize each dimension separately with jagged arrays:
int[][] jagged = new int[5][];
for (int i=0; i<jagged.Length; i++)
{
jagged[i] = new int[10]; // length can be different for each sub-array, if needed
}
multidimensional arrays are initialized all at once
int[,] mArray = new int[5,10];
A good example of a 2 dimensional array would be a bitmap image. Imagine each pixel in the picture taking up one block of the Pixel[1024][768] array. So to find out what colour the pixel in the top left hand corner of the screen was you would look at Pixel[0][0].
3 dimensional arrays require more visualisation, but a classic example would be modelling points in space.
I used a 2 dimensional array in a quick and dirty Hold 'Em simulator I wrote to represent decisions preflop, it looked a bit like this;
_Open = new char[][]
{ // 2 3 4 5 6 7 8 9 T J Q K A
new char [] {'P', 'F', 'F', 'F', 'F','F','F','F','F','F','F','P','P'}, // 2
new char [] {'F', 'P', 'F', 'F', 'F','F','F','F','F','F','F','P','P'}, // 3
new char [] {'F', 'F', 'P', 'F', 'F','F','F','F','F','F','F','P','P'}, // 4
new char [] {'F', 'F', 'F', 'P', 'F','F','F','F','F','F','F','P','P'}, // 5
new char [] {'F', 'F', 'F', 'F', 'P','F','F','F','F','F','F','P','P'}, // 6
new char [] {'F', 'F', 'F', 'F', 'F','P','F','F','P','F','F','P','P'}, // 7
new char [] {'F', 'F', 'F', 'F', 'F','F','P','P','P','P','F','P','P'}, // 8
new char [] {'F', 'F', 'F', 'F', 'F','F','F','P','P','P','P','P','P'}, // 9
new char [] {'F', 'F', 'F', 'F', 'F','F','F','F','P','P','P','P','P'}, // T
new char [] {'F', 'F', 'F', 'F', 'F','F','F','F','F','P','P','P','P'}, // J
new char [] {'F', 'F', 'F', 'F', 'F','F','F','P','P','P','P','P','P'}, // Q
new char [] {'P', 'P', 'P', 'P', 'P','P','P','P','P','P','P','P','P'}, // K
new char [] {'P', 'P', 'P', 'P', 'P','P','P','P','P','P','P','P','P'} // A
};
Using 0 to represent 2 and 12 to represent Ace. So if the simulator detected Ace, King it would check _Open[12][11] see 'P' (meaning 'push' or 'all-in') and act accordingly