Macklin
Macklin

Reputation: 150

Filling an array or struct by file in C++

I'm writing a simple 2D game in C++ (a language that is still quite new to me) using DirectX that involves a grid of 26x26 tiles sorted in a Cartesian-like manner - with the origin being the top leftmost space at 0,0. Each tile needs to contain the values:

These values will be stored in a text file stage_n.txt (228 lines long) which is formatted like the following:

2 2 1
3 2 1
6 2 1
7 2 1
10 2 1
11 2 1
...

Each set of tile values are separated by a new line, while each value is separated by a space. The first value is tileX, the second value is tileY, the third value is tileType. All tiles are initially assumed to have a tileState of 8.

These values will be looped through to draw the stage at the start of the game, and will be changed often in the code.Note that only tiles that are occupied are listed in the file. Tiles that are empty are not listed.

My first thought was to use a multidimensional array tileMap[25][25][1] like the following:

tileMap[0] = 0 (X value) // All tiles on line X0
    tileMap[0][0] = 0 (Y value) // First tile on line 0 (at Y0)
        tileMap [0][0][0] // Tile type
        tileMap [0][0][1] // Tile state
    tileMap[0][1] = 1 (Y value) // Second tile on line 0 (at Y1)
        tileMap [0][1][0] // Tile type
        tileMap [0][1][1] // Tile state
    ... through to 25 (the last tile on line 0)
tileMap[1] = 1 (X value) // All tiles on line X1
    tileMap[1][0] = 0 (Y value)
        ...
    tileMap[1][0] = 1 (Y value)
        ...
    ...
... through to 25 (the last line)

But I was also considering using a structure:

struct tileData{
    int tileX;
    int tileY;
    int tileType;
    int tileState;
} tile[676]; // 676 is the total amount of tiles.

Going back to my question; in this situation, would it be more efficient to use a struct or an array? How would I go about initializing/filling the easier option using data in the above text file? I've tried to imitate many examples online (that have used ifstream), but none of them have seemed to work.

This question has probably been answered a lot, but I just can't get my head around how to do it. I hope this makes enough sense. Thanks!

EDIT: Additionally, where should I place my text file if I'm using VS2013?

Upvotes: 1

Views: 997

Answers (3)

pm100
pm100

Reputation: 50200

i would use a 2d array of Tile objects (or std::vector or std::array, always preferred to naked arrays)

struct Tile
{
    int tileType;
    int tileState;
}
Tile grid[25][25];

dont put the X/Y of the tile in the struct. This knowledge is implicitly encoded in its position in the array

Upvotes: 1

cpp-progger
cpp-progger

Reputation: 406

I think there is no difference in performance between an array and a struct. But there is a difference in better code - use the struct tilData and write a istream-operator for it.

std::istream& operator>>( std::istream& in, tileData& td )
{
    if( in >> td.tileX >> td.tileY >> td.tileType )
        td.tileState = 8;
    return in;
}

You can read it in this way:

size_t n = 0;
for( ; file >> tile[n]; ++n )
    ;
if( file.eof() ) // check whether End Of File is reached
{
    cout << "Ok " << n << "Tiles read\n";
}

Upvotes: 0

Joseph Mansfield
Joseph Mansfield

Reputation: 110728

I doubt there would be any different in performance, since both accessing an array and accessing a member of a struct just involve accessing some baked-in offset from some address. If it really matters because you've discovered this code to be a bottleneck, then you'll need to do some performance measures. I can almost guarantee that the compiled code will be identical in either case.

Anyway, it looks to me like it would be most appropriate to use a struct. While all the members of the struct are the same type, they do not have the same meaning. It's certainly possible that they could have different types. A struct nicely groups together these different yet related values.

Reading into your 1D array should be as simple as:

std::ifstream file("stage_n.txt");
int i = 0;
while (file >> tile[i].tileX
            >> tile[i].tileY
            >> tile[i].tileType) {
   tile[i].tileState = 0;
   ++i;
}

There's no reason you can't have a 2D array of structs, though. That would better represent your grid. In that case, you would just need to keep track of an x and y position as you read from the file (instead of i).

The file reading code above doesn't do much in the way of error checking. If you want to be precise, you should consider what exactly should be valid. For example, the above code would still accept the data even if it were all on one line. If you want to read the file on a line-by-line basis, you'll need to use std::getline and then parse each line.

Upvotes: 2

Related Questions