Returning an element from an array

Started by
23 comments, last by Toshio 11 years, 9 months ago
Hi there. I hope someone could help me solve this problem.

I suspect this is not the way to do it, but here's the code:


int tile[210][210];


int Map::getTile(int a, int b)
{
return tile[a];
}


When I want to return the element in a different class, it returns 0.

Also, I can't make my tilemap (tile[a]) bigger than 212 * 212. The game crashes just after it launches.
Thanks for your help.
Advertisement
If you want the tile to be connected to an instance of the Map class, you need to place the definition of tile inside the class { } body where you define Map. Just sticking it out in no-man's-land makes it a global variable, so every copy of Map will access the same variable.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

In addition to what ApochPiQ mentioned, you should use an std::vector if you're going to have a large amount of data, because you're putting too much data on the stack which is why it crashes. This is called a Stack Overflow, apparently (I never knew what it was called until just now wink.png).

Using a std::vector puts the data on the heap instead, which won't crash your program with the amount of data you are using.
(Note: Just because std::vectors are resizable, doesn't mean you have to use that. They are good as for constant sized arrays also. Infact, the new C++ standard even introduced a new type of container: A non-resizable vector. laugh.png)

This code should give you a good boost-start:
#include <vector>

class Map
{
public:
Map(int width, int height) : width(width), height(height)
{
//Resize the vector to be the size we want (width * height).
this->tiles.resize((width * height), 0); //Initialize each tile to 0.
}

int Map::GetTile(int x, int y)
{
int index = _GetIndex(x,y);

//Make sure this is a valid index.
if(_IsValid(index))
{
return this->tiles[index];
}

return 0;
}

void Map::SetTile(int x, int y, int tileID)
{
int index = _GetIndex(x,y);

//Make sure this is a valid index.
if(_IsValid(index))
{
this->tiles[index] = tileID;
}
}

private:
int width, height;
std::vector<int> tiles;

//Converts from a two-dimensional x,y to a one-dimensional index into our vector.
int _GetIndex(int x, int y)
{
return (y * this->width) + x;
}

//Makes sure that we aren't going out of bounds, which will crash the program.
bool _IsValid(int index)
{
if(index < this->tiles.size())
return true;

return false;
}
};

int main()
{
const int NOTHING = 0;
const int GRASS = 1;
const int DIRT = 2;
const int DIFFERENT_DIRT = 3;
//...
const int WATER = 211;
const int LAVA = 300;

Map map(20, 20); //I want a map that's 20 by 20 tiles.

Map largeMap(2000, 5000); //I also want a map that's 2000 by 5000 tiles.

largeMap.SetTile(50, 100, DIRT) //Access tile X:50, Y:100, and set it to DIRT.

if(largeMap.GetTile(playerTileX, playerTileY) == LAVA)
{
//...damage the player.
}
}


If you have any questions about how it works, don't hesitate to ask.
Wow, thanks, I can make the map any size I want. :)

But, I create the map and do all of this inside my Map class. And when again I want to get the tile in the Player class, it returns 0.
Could you please post the code how the Map instance is passed to the Player? I have the suspicion you are creating a new (uninitialized) Map instance in your Player class.

class Player
{
Map m;
public:
Player();
void Init();
//...
}


I set the width and the height inside the Map class.
Are you sure you want every player to have her own map? Because that's what you are doing right now. What you want to do, is pass a reference to your map to the player, like this:


class Player
{
Map& m;
public:
Player(Map& map)
: m(map) { ... old constructor code ... }
};
in main:
set up the map as you did before, then when creating the player:
Player player(map); // or largeMap


This way you only have one map for all players, all referencing the same data. If you do it the way you did, you create an empty map for every player, and one in your main, which you never use.

But, I create the map and do all of this inside my Map class. And when again I want to get the tile in the Player class, it returns 0.


Could you show a complete example of code? We need to see what your entire Map class looks like, and your entire Player class, if we're to figure out why your Player class is not interacting with the Map class properly. Also show where your Map or Player is created.
I think SOAL and rnlf are correct, you need every player to have a reference not create its own (though personally I would use a pointer but its all the same)

Make the player class have a reference to a M

Are you sure you want every player to have her own map? Because that's what you are doing right now. What you want to do, is pass a reference to your map to the player, like this:


class Player
{
Map& m;
public:
Player(Map& map)
: m(map) { ... old constructor code ... }
};
in main:
set up the map as you did before, then when creating the player:
Player player(map); // or largeMap


This way you only have one map for all players, all referencing the same data. If you do it the way you did, you create an empty map for every player, and one in your main, which you never use.



this is pefect, should easily solve the issue



also SOAL you forgot to include a check inside the isValid function if it is less than 0. I don't know if std::vector does that check or not.
Always improve, never quit.

also SOAL you forgot to include a check inside the isValid function if it is less than 0. I don't know if std::vector does that check or not.

Oops, you're right. biggrin.png

The function should be:
bool _IsValid(int index)
{
if(index < this->tiles.size() && index > 0)
return true;

return false;
}


If it was my own code, I'd just make 'index' be unsigned or a size_t.

This topic is closed to new replies.

Advertisement