• Advertisement

Archived

This topic is now archived and is closed to further replies.

multidimensional arrays

This topic is 5838 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How do I make multidimensioned arrays? I know how to do 1 dimension
  
//make an array that is array[sizex][sizey]

int* array = new int[sizex];

//now how make the sizey part?


//and when done, delete

delete [] array;
  

Share this post


Link to post
Share on other sites
Advertisement
quote:
Original post by Jason Zelos
A 3 dimensional array.

      
int* array = new int[sizex][sizey][sizez];



You might like to consider checking this code.

--

It is against the law to stare at the mayor of Paris.


Edited by - SabreMan on February 25, 2002 3:54:00 PM

Share this post


Link to post
Share on other sites
you could

  
// the linear 2d array


int *array = new int[sizex*sizey];
// access by doing

array[x+y*sizex];
delete [] array;

//

// for a planar multidimensional array

//

int **array = (int**)(new int[sizey]);
for(i=0; i<sizey; i++)
array[i] = new int[sizex];

// access by

array[y][x];

// deletion

for(i=0; i<sizey; i++)
delete [] array[i];
delete [] array;


// the c way

// linear 2d array

int *array = (int*)malloc(sizex*sizey);

//deletion

free(array);

// planar 2d array

int **array = (int**)(malloc(sizey));
for(i=0; i<sizey; i++)
array[i] = (int*)(malloc(sizex));

// access by

array[y][x];

// deletion

for(i=0; i<sizey; i++)
free(array[i]);
free(array);



saberman, how would you do such a thing, since you obviously know (by your comment about the code being wrong). since either one is a mulitdimensional array. there may be a better way to allocate planar arrays in c++, i am not sure since i rarly use planar arrays and tend to use c methods of allocation (except for objects).

Share this post


Link to post
Share on other sites
I knew the syntax was illegal.

Dynamically allocating multi-dimensional arrays actually takes quite a lot of explanation, so I'm going to defer to someone who's already written up a perfectly good explanation, Marshall Cline...

How do I allocate multidimensional arrays using new?

Pointers and arrays are evil!

Do these links help?




Edited by - SabreMan on February 26, 2002 7:14:36 AM

Share this post


Link to post
Share on other sites
So, is this right?
    
vector< vector<int> > array;

Because I want to use a multidimensioned container of tiles

struct tile{
int id;
int walk;
};

But don't understand how. If the above is right I think I would do

for(i = 0; i < map_width; i++) {
for(j = 0; j < map_height; j++) {
//initialize each tile so I have an

//array of tiles WIDTHxHEIGHT

tile tmp;
tmp.id = 0;
tmp.walk = 1;
map[i].push_back(tmp);
}
}

Do you have any links where I can learn about STL? I don't know anything about it. [/source]

Edited by - evilclown on February 26, 2002 3:33:06 PM

Share this post


Link to post
Share on other sites
Something like this...
  
int ***number_cube = new (int**)[5];
for(int i = 0; i < 5; ++i) {
number_cube[i] = new (int*)[5];
for(int j = 0; j < 5; ++j) {
number_cube[i][j] = new int[5];
}
}

...

for(int i = 0; i < 5; ++i) {
for(int j = 0; j < 5; ++j) {
delete[] number_cube[i][j];
}
delete[] number_cube[i];
}
delete[] number_cube;

Share this post


Link to post
Share on other sites
I''d do it like this using C style syntax.

  
struct tile {
int id;
int walk;
};


tile TileMap[map_width][map_height];


for(i = 0; i < map_width; i++) {
for(j = 0; j < map_height; j++) {
TileMap[i][j].id = 0;
TileMap[i][j].walk = 1;
}
}



I think this is a more conventional way of doing it, if not easier to think about.

I''m going to have to talk to my eyes about reading posts all the way through before replying .

,Jay

Share this post


Link to post
Share on other sites
Jason Zelos, I can''t do that because the map will be a global variable. Each new map loaded could be a different size. If it''s global, I can''t change the dimensions without using new.

I want to be able to use a container if possible so I don''t have to worry about new and delete.

Share this post


Link to post
Share on other sites
why use stl? this is a simple memory allocation problem of a struct. just

  

map = (tile*)malloc(width*height);
// and access like

map[x*y*width].blah= 42;

// free by

free(map);



i dont see what is so complex about this. need it in a container so you dont have to worry about deletion? face it, if you are dynamically loading maps, your load() function should free the previous map.

if you insist on using stl, then do a search on google or gamedev, maybe even get a book.

you should consider "map" to be a part your map loading class. while you would probally want to leave the map varible public, you could just add functions that do the stuff you need (ie check for collision, load, unload, etc.)

Share this post


Link to post
Share on other sites
evilcrap''s short multi-dereferencing tutorial

when you work with pointers, after the first dimension, you need to dereference every pointer to get to its value.

1D, a vector
      
char* pC = new char[length];
cout << pC[x]; //output each char



2D, a Map
        
char** Map = new char*[width];
for(int x = 0; x < width; x++)
Map[x] = new char[height];

cout << Map[x][y];



3d, a Cube
      
char*** pMap = new char**[depth]; //create a series of Map pointers

for(z = 0; z < depth; z++){
pMap = new char*[width];
for(x = 0; x < width; x++)
pMap[z][x] = new char[height];
}

cout << pMap[z][x][y];

------
if you examine a vector(1D array), then youll notice that the pointer itself is the first element of the array.
           
cout << pChar; //pChar is an address, itll print till it finds a NULL

cout << *pChar; //pChar is a char, itll print pChar[0]


so, guess at below some.
   
cout << ***pMap; // ? pMap[0][0][0], it is an address

cout << (**pMap)[y]; // ? pMap[0][0][y], it is an address

cout << (*pMap)[x][y]; // ? pMap[0][x][y], it is a char

cout << pMap[z][x][y]; // ? pMap[z][x][y], it is a char



-note that (*pMap)[y] != *pMap[y]

-although you could simulate any number of dimensions in a single vector, there is a performance cost of having to multiply alot.

-dereferencing is alot faster than multiplying... therefore, if you want your code to be readible and fast, you should use pointers.

Share this post


Link to post
Share on other sites
Think of it this way. A dynamically allocated 2d-array is an arroy of pointers. Each pointer points to an array, which is itself a pointer. Hence, your "outermost" layer is an array of pointers to pointers. For a cube, you would need pointers to pointers to pointers, each of which would point to a pointer to a pointer, each of which would point to a pointer to a block of memory.

It may seem comfusing, but I''m sure you''ll get to understand it pretty quickly.

An alternative to using multidimensional arrays is to use a 1-dimensional array as a direct address table. This is the simplest form of a technique called hashing. Basically, it takes multiple parameters, and creates a single number from them, which is an array index. A straightforward way to do this in 2d is "the way you read." If you number each array "slot" starting at the top left corner, and going across each row, working from top to bottom, then you get a simple pattern. An often-used function that determines the array index that corresponds to an x, y coordinate is (x + y * width). I''m sure you can extend this technique to three dimensions.

Share this post


Link to post
Share on other sites
why do ppl confuse things so? you can have a multi dimensional array WITHOUT using arrays of arrays.

there are two types, many ppl seem to ignore this fact. citing c/c++ books that state mulitdimensional arrays must be arrays of arrays (ie 2d array must be decalred "int **blah or int blah[y][x]") this just is not so.

a small tutorial that explains the difference between planar and linear memory and when to use each.

planar mulit dimensional arrays. these is how most ppl seem to think of them, and how evil crap explains it. basically you are creating arrays of pointers to other arrays. see my previous examples or evilcrap''s examples.

access: need to dereference at each level, the [] operator simplfies this.

pros:
easy access using [][][] for nice reading of code.
each row can have a different number of elements to save ram
since memory is not contigous, its more likly all the alloocs will work.

cons:
complex and messy (de)allocation, order does matter
multiple dereferences will slow access slightly (not much)

useful for command histories, consoles buffer (ie quake), or anything else that you dont need the same sized rows.

**********

linear mulit dimensional arrays. this is a standard array that is accessed in a multi dimensional way. these is how video buffers are ussually treated (linear ones anyway). access is done via mathmatics.

ie [x+y*width] for a 2d array, this can be expanded to 3d arrays as well like [x+y*width+z*width*height]. so you get the idea of how to expand to higher dimensions. basically each dimension you add, requires you to multiple by the previous dimensions size.

pros:
easy (de)allocation. just a single new/malloc
contigous memory, may be useful for quick copies with memcpy


cons:
more complex access, which gets harder to read as the dimensions get higher. this naturally can be simplified with some clever macors, but may not be elegant at all.
very large arrays may not be able to be allocated since it requires a single contigous block.
all rows will be the same size

uses:
maps, video buffers, and anything that contigous memory or easy allocation is perffered.

i am sure there are more pros/cons/uses for each style of multi dimensional array. its up to you to measure which type to use (you should try to understand both, since they are both useful).

Share this post


Link to post
Share on other sites
a person - arrays of arrays are faster for random access. I''ll admit that random access to array elements is rarely needed, though.

Share this post


Link to post
Share on other sites
quote:
Original post by a person
why do ppl confuse things so? you can have a multi dimensional array WITHOUT using arrays of arrays.


Yes. This is one of the very things that it says in the links I provided. It would be nice to encapsulate the array within a class and provide some natural ways of accessing it but, other than that, I don't see any reason to try and get too clever about it.

--
Cats cannot taste sweets.

Edited by - SabreMan on February 27, 2002 5:32:53 AM

Share this post


Link to post
Share on other sites
I was asking all these questions because I am making a tile based game. The multi dimensioned array was for the map. For the graphics part, I wanted to be able to have an array to load surfaces in. That way, when the game is running I can load multiple surfaces, and blit them by knowing the index.

Is this right? I don't know what function removes a value in a vector. (Is there STL documentation somewhere that says?) I thought for freesurface I could use just use if(surfaces.at(index)) but I don't know what at() does.

    
#include <string>
#include <iostream>
#include <vector>
#include "SDL.h"

class graphics {
public:
graphics();
~graphics();

int LoadSurface(std::string);
void FreeSurface(int);
private:

vector<SDL_Surface*> surfaces;
};

graphics::graphics() {
//initialize graphics

}

graphics::~graphics() {
//destroy graphics

while(surfaces.size() > 0) {
FreeSurface(surfaces.size());
}
}

int graphics::LoadSurface(std::string filename) {
//add a surface to surfaces

SDL_Surface *surface;
surface = SDL_LoadBMP(filename);
if(surface == NULL) {
cerr << "Unable to load " << filename << endl << SDL_GetError() << endl;
return -1;
}
surfaces.push_back(surface);
SDL_FreeSurface(surface);
return surfaces.size();
}

void graphics::FreeSurface(int index) {
//remove a surface from surfaces

if(index >= surfaces.size() || index < 0) {
return;
}
SDL_FreeSurface(surfaces[index]);
//delete surfaces[index]

}



Edited by - evilclown on February 27, 2002 10:05:42 AM

Share this post


Link to post
Share on other sites
quote:
Original post by evilclown
Is this right? I don't know what function removes a value in a vector. (Is there STL documentation somewhere that says?) I thought for freesurface I could use just use if(surfaces.at(index)) but I don't know what at() does.


You need to use erase() and remove(), however vectors are not really designed for regularly removing and inserting elements, if that's what you are doing. Sounds like you really need that STL documentation. You could try the following sites...

Dinkumware

SGI


The at() function performs bounded access to a vector element. It will return the element at the position you pass, throwing an exception if you request something out of range. If you know the index, you might prefer to use operator[]. Check out those web links and come back if you are unsure.

--
Cats cannot taste sweets.

Edited by - SabreMan on February 27, 2002 11:07:26 AM

Share this post


Link to post
Share on other sites
I'm trying to find out what I need, but the site is kinda confusing. I thought I wanted to be able to delete entries from the middle of a container, but maybe that would cause problems later on. Because if I have 1 as the index for a surface, and if I remove surface 0, surface 1 would move down to surface 0, 2 down to 1 so it would use the wrong texture. Maybe I should use something like perl's associative arrays? ( $arrayname["key"] = value ). Or do you know of something else that would work better?

One other thing, what does constant and linear time mean?
quote:
linear time insertion and removal of elements at the beginning or in the middle
If I can't remove elements in the middle, what does this mean?

Does an assosiative array seem like the right choice?


Edited by - evilclown on February 27, 2002 12:09:45 PM

Share this post


Link to post
Share on other sites
actually, using a single vector can be faster than a pointer array.
however, the loop must not be done with multiplication in it.
  
for(int x = 0; x < width; x++){
int offset = 0;
for(int y = 0; y < height; y++)
vector[offset+ y] = 5; // [x*height + y]

offset+=height;
}

Share this post


Link to post
Share on other sites

  • Advertisement