Jump to content
  • Advertisement
Sign in to follow this  
JDUK

[c++]Can you make a 2D array and then set its size at runtime?

This topic is 4636 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

I want to create a 2D array to hold my level map then set its dimensions when load_level(filename) is called at runtime. Is this possible? or do i need a vector? cheers.

Share this post


Link to post
Share on other sites
Advertisement
Yes. Here is a quick code sample to get you started. What you are looking for is dynamic memory allocation. I could explain it to you but you will find much better ressources online no doubt.



int main() {
int width = 0;
int height = 0;
Room* level;

std::cin >> width
std::cin >> height;
level = new Room[width][height];

//Do stuff.

//Do not forget this.
delete [] level;
}




Good luck [smile]

Edit: Using a vector is a very good idea too.

Share this post


Link to post
Share on other sites
Quote:
Original post by jfclavette
Yes. Here is a quick code sample to get you started. What you are looking for is dynamic memory allocation. I could explain it to you but you will find much better ressources online no doubt.


*** Source Snippet Removed ***

Good luck [smile]

Edit: Using a vector is a very good idea too.

It is especially good when you consider that your code doesn't work.

While a vector of vectors is a good starting point, boost::multi_array is a bit better, in my opinion. The vector approach suffers from the very real issue that each row can have a different length. Further, it ensures your array is spread all over the heap, destroying spacial locality. boost::multi_array solves both of those problems, as well as adding a bunch of nice functionality [like the ability to use 1-based indexing, as well as declaring arrays in both row major and column major forms]. It isn't always neccessary to solve them, of course, and the syntax is relatively tricky compared to the vector approaches, but its good to have an alternative in mind.

CM

Share this post


Link to post
Share on other sites
Also, a slightly simpler implementation of a straight rectangular array can be had by using a one-dimensional array and calculating offsets manually.

rect_array[x][y] <=> linear_array[x + rect_array.width * y]

This can natually be accomplished within a vector to give you the benefits of automatic memory management and bounds checking if either are important to you. This is basically what boost::multi_array does for you, albeit simplified considerably, so it solves the same problems and offers the same advantages if you want to code them yourself.

CM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:

Also, a slightly simpler implementation of a straight rectangular array can be had by using a one-dimensional array and calculating offsets manually.



rect_array[x][y] linear_array[x + rect_array.width * y]


This can natually be accomplished within a vector to give you the benefits of automatic memory management and bounds checking if either are important to you. This is basically what boost::multi_array does for you, albeit simplified considerably, so it solves the same problems and offers the same advantages if you want to code them yourself.

CM


I concur. If that's too complex for you to understand here's a starting point..

This is for an array of ints... making this a template might be better.

This just points to an array you've made elsewhere and assumes the size is correct. You can make it more useful fairly easily. I just want to keep it simple to show Conner's method in action, which would probably be my choice.

class MultiArray
{
public:
MultiArray(int *some_array, unsigned int w)
{
linear_array=some_array;
width=w;
}

GetElement(unsigned int x, unsigned int y)
{
return linear_array[x + width * y];
}
private:
int *linear_array;
unsigned int width;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Conner McCloud

It is especially good when you consider that your code doesn't work.

While a vector of vectors is a good starting point, boost::multi_array is a bit better, in my opinion. The vector approach suffers from the very real issue that each row can have a different length. Further, it ensures your array is spread all over the heap, destroying spacial locality. boost::multi_array solves both of those problems, as well as adding a bunch of nice functionality [like the ability to use 1-based indexing, as well as declaring arrays in both row major and column major forms]. It isn't always neccessary to solve them, of course, and the syntax is relatively tricky compared to the vector approaches, but its good to have an alternative in mind.

CM


Thanks thats a GREAT reply :¬)
Learning the why's and why not's of each aprouch is very helpful.

As far as im aware cacheing is a very important speed boost to a system, and spacial locality is a big factor in that. Does the effect you mentioned regarding vectors impact this in a big way?
Are vectors a poor choice for games programming becuase of this?

Thanks again.

James.

Share this post


Link to post
Share on other sites
Quote:
Original post by JDUK
As far as im aware cacheing is a very important speed boost to a system, and spacial locality is a big factor in that. Does the effect you mentioned regarding vectors impact this in a big way?

It can do although it depends on a lot of factors. Note that this isn't limited to vectors. A C-style malloced array of malloced arrays suffers exactly the same problem.
Quote:
Are vectors a poor choice for games programming becuase of this?

No. vectors are a very good choice for games programming. However, using a vector of vectors to represent a rectangular 2D array is a bad choice, because the rows/columns of a rectangular 2D array are not separate entities, which is what a vector of vectors represents. Unfortunately there is no container that models rectangular arrays in the SC++L. You could use Boost.MultiArray as already mentioned, or for a lighter weight but less general solution you can simply wrap a one-dimensional vector with a two-dimensional interface, something like:
#include <iostream>
#include <vector>

template < typename Type >
class TwoDeeArray
{

private:

class RowProxy;

public:

TwoDeeArray()
:
width_(0),
height_(0)
{
}

TwoDeeArray(unsigned int width, unsigned int height)
:
width_(width),
height_(height),
data_(width * height)
{
}

TwoDeeArray(unsigned int width, unsigned int height, Type const & initialiser)
:
width_(width),
height_(height),
data_(width * height, initialiser)
{
}

RowProxy operator[](unsigned int index)
{
return RowProxy(data_, index * width_);
}

RowProxy const operator[](unsigned int index) const
{
return RowProxy(data_, index * width_);
}

private:

class RowProxy
{

public:

RowProxy(std::vector< Type > & data, int offset)
:
data_(data),
offset_(offset)
{
}

Type & operator[](unsigned int index)
{
return data_[index + offset_];
}

Type const & operator[](unsigned int index) const
{
return data_[index + offset_];
}

private:

std::vector< Type > & data_;
int const offset_;

};

unsigned int width_;
unsigned int height_;
std::vector< Type > data_;

};

int main()
{
TwoDeeArray< char > board(3, 3, ' ');
board[2][1] = 'X';
board[0][0] = 'O';
std::cout << " | | \n";
std::cout << ' ' << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " \n";
std::cout << " | | \n";
std::cout << "---+---+---\n";
std::cout << " | | \n";
std::cout << ' ' << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " \n";
std::cout << " | | \n";
std::cout << "---+---+---\n";
std::cout << " | | \n";
std::cout << ' ' << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " \n";
std::cout << " | | \n";
}

Enigma

Share this post


Link to post
Share on other sites
The standard template library (like std::vector, std::list, etc) was written by people who are much smarter then you or I. The library was designed for speed and efficiency, perfect for game development use. What you have to do is evaluate which structure is best for your use.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!