Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Is there a way to use CSV files within a tile game?

This thread is locked; no one can reply to it. rss feed Print
 1   2   3 
Is there a way to use CSV files within a tile game?
bamccaig
Member #7,536
July 2006
avatar

torhu said:

You don't really need to do that. This will work:

if (stuff[linenum][tilenum] == '1')
    cout << "it's a one!\n";
else if (stuff[linenum][tilenum] == '0')
    cout << "it's a zero!\n";

It will work, but it's incredibly redundant. :P

You can do this instead:

char t = stuff[linenum][tilenum] - '0';

/*
 * t is now a single-byte integer in the range 0 - 9
 * (assuming the map only contains characters in the range '0' - '9')
 * (ignore that it's a character data type; it's still an integer).
 */

Rather than leave your map full of characters that don't mean anything to you, you could do this conversion when you read the map file and have integers from then on.

Of course, this only works for single-digits. If you have multiple digits then you need to do some multiplication to get your real number. The functions atoi and std::istringstream::operator>> already do this for you, so if your data can be that complex than using the standard libraries is worthwhile.

But I still think using a single, printable, ASCII character per tile is plenty sufficient. :) It also has the advantage that it can be semantic and allow you to better visualize the map in the file.

Ryan Rees-Williams
Member #13,825
December 2011

ahhhhhh confusion :P I think I may have just completely lost track of what people are telling me to try, could I just use white space and do a while loop like:

#SelectExpand
1int main() 2{ 3 ifstream in_stream; 4 ofstream out_stream; 5 int tile[10][100], current_x, state; 6 in_stream.open("map.txt"); 7 for (int current_y =0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 8 { 9 while (state != 9) 10 { 11 in_stream >> tile[current_x][current_y]; 12 if (tile[current_x][current_y] == 9) 13 { 14 state = 9; 15 } 16 current_x++; 17 } 18 } 19 in_stream.close(); 20}

while reading it will see a return as a white space right?

torhu
Member #2,727
September 2002
avatar

Something like that, sure. There's a missing parenthesis, by the way. ;)

Ryan Rees-Williams
Member #13,825
December 2011

where? I've been over the code a few times and I can't find where it is :P
with this it builds fine and then instantly crashes, hmm find that error time...

bamccaig
Member #7,536
July 2006
avatar

        while (state != 9)

                state = 9;

state should be local to the outer for-loop block and initialized each iteration. Why not just break instead? :-/

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Ryan Rees-Williams
Member #13,825
December 2011

thanks for pointing that out, I found where the crash occurs, if you test this out for yourself it doesn't reach the exit(1) is my code for reading from the instream right?

#SelectExpand
1int main() 2{ 3 ifstream in_stream; 4 ofstream out_stream; 5 int tile[10][100], current_x, state; 6 in_stream.open("map.txt"); 7 for (int current_y =0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 8 { 9 do 10 { 11 in_stream >> tile[current_x][current_y]; 12 exit(1); 13 if (tile[current_x][current_y] == 9) 14 { 15 state = 9; 16 current_x = 0; 17 } 18 current_x++; 19 } 20 while (state != 9); 21 } 22 in_stream.close(); 23}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Ryan Rees-Williams
Member #13,825
December 2011

if I put the exit(1) just before in_stream then it will exit safely, if I put it just after it crashes... really odd, there is nothing wrong with the code as the exact same code works with the same type of variable in another program, does ifstream often have trouble with loops? I did open the file outside the loop so could that be a potential cause?

torhu
Member #2,727
September 2002
avatar

You haven't initialized the current_x and state variables, they'll have random values. That's why it crashes.

The compiler should warn you about this, add -Wall to the command line if you are using gcc.

Ryan Rees-Williams
Member #13,825
December 2011

Thanks! and I'm using Code::Blocks with the GNU GCC Compiler, no idea how I would add that to the command line for software like this :P
fixed the crash but now I can only get it to read the second line of the map file, if I add a -1 or +1 to current_y then it will output a random number which is odd, very, very odd

#SelectExpand
1#include <iostream> 2#include <fstream> 3#include <cstdlib> 4 5using namespace std; 6 7int main() 8{ 9 ifstream in_stream; 10 ofstream out_stream; 11 int tile[10][100], current_x = 0, state; 12 in_stream.open("map.txt"); 13 for (int current_y = 0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 14 { 15 do 16 { 17 in_stream >> tile[current_y][current_x]; 18 if (tile[current_y][current_x] == 9) 19 { 20 state = 9; 21 current_x = 0; 22 } 23 current_x++; 24 } 25 while (state != 9); 26 } 27 current_x = 0; 28 in_stream.close(); 29 30 for (int current_y = 0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 31 { 32 do 33 { 34 cout << tile[current_y][current_x] << " "; 35 if (tile[current_y][current_x] == 9) 36 { 37 state = 9; 38 current_x = 0; 39 } 40 current_x++; 41 } 42 while (state != 9); 43 } 44}

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Menu->Project->Build Options->[Select Build Type]->Compiler Options->[Select 'Enable All Compiler Warnings']

OR

Menu->Settings->Compiler And Debugger->Global Compiler Settings->[Select 'Enable All Compiler Warnings']

As for why it only reads one line, it is because you never reset 'state' to a non 9 value. Further reason to use 'break;' instead.

Specter Phoenix
Member #1,425
July 2001
avatar

Proof he is using a bad compiler, if it is letting that compile without error he needs to get a new compiler. He is saying int main with no return 0; at the end. Only the older compilers allow that, the newer ones that hold to the standard return an error and won't compile without it.

bamccaig
Member #7,536
July 2006
avatar

It's not even a warning with -Wall. :o

bamccaig@castopulence.org:~$ cat | g++ -x c++ - && ./a.out
int main() { }
bamccaig@castopulence.org:~$ cat | g++ -Wall -x c++ - && ./a.out
int main() { }
bamccaig@castopulence.org:~$ 

C warns with -Wall though. :o

torhu
Member #2,727
September 2002
avatar

He's using C++, where return 0; at the end of main is implicit. And please don't derail the thread with stuff like this.

Specter Phoenix
Member #1,425
July 2001
avatar

bamccaig said:

It's not even a warning with -Wall.

Really? G++ won't even compile if I don't have return 0; at the end. Wait it was Ming in Windows I would get the error about main not returning an int. G++ in *nix compiles no complaints at all. Interesting (even with -Wall -Wextra).

torhu said:

And please don't derail the thread with stuff like this.

Me being an asshole is implicit. Scares me that you actually wasted your time saying that considering this forum is known for going off topic on almost every thread.

Ryan Rees-Williams
Member #13,825
December 2011

now don't argue :) off topic stuff can be fun as long as it doesn't take over the thread :P added -wall to my compiler so hopefully Ill be able to detect those kinds of problems in the future

#SelectExpand
1#include <iostream> 2#include <fstream> 3#include <cstdlib> 4 5using namespace std; 6 7int main() 8{ 9 ifstream in_stream; 10 ofstream out_stream; 11 int tile[10][100], current_x = 0, state; 12 in_stream.open("map.txt"); 13 for (int current_y = 0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 14 { 15 do 16 { 17 in_stream >> tile[current_y][current_x]; 18 if (tile[current_y][current_x] == 9) 19 { 20 state = 9; 21 current_x = 0; 22 } 23 current_x++; 24 } 25 while (state != 9); 26 state = 0; 27 } 28 current_x = 0; 29 in_stream.close(); 30 31 for (int current_y = 0; current_y < 10; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 32 { 33 do 34 { 35 cout << tile[current_y][current_x] << " "; 36 if (tile[current_y][current_x] == 9) 37 { 38 state = 9; 39 current_x = 0; 40 } 41 current_x++; 42 } 43 while (state != 9); 44 state = 0; 45 } 46}

it now reads the whole thing but it gets a tonne of random number data as well as the numbers stored in the file, kinda gives a nice Matrix effect though :D
EDIT
Derp, I only added the state = 0 to one of the loops, I feel a little dimwitted now, I keep on making small mistakes like that that completely balls my programs up ;)
Anyway thanks for the help, I now have a fully working tile engine, next step for me is to test it with graphics and if that goes smoothly put it into a header file, thanks again to everyone for their input and help!
My final code for reference:

#SelectExpand
1 2#include <iostream> 3#include <fstream> 4#include <cstdlib> 5 6using namespace std; 7 8int main() 9{ 10 ifstream in_stream; 11 ofstream out_stream; 12 in_stream.open("map.txt"); 13 14 int maphight; 15 16 in_stream >> maphight; 17 18 int tile[maphight][100], current_x = 0, state; 19 20 for (int current_y = 0; current_y < maphight; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 21 { 22 do 23 { 24 in_stream >> tile[current_y][current_x]; 25 if (tile[current_y][current_x] == 9) 26 { 27 state = 9; 28 current_x = 0; 29 } 30 current_x++; 31 } 32 while (state != 9); 33 state = 0; 34 } 35 current_x = 0; 36 in_stream.close(); 37 38 for (int current_y = 0; current_y < maphight; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 39 { 40 do 41 { 42 if (tile[current_y][current_x] != 9) 43 { 44 cout << tile[current_y][current_x] << " "; 45 } 46 if (tile[current_y][current_x] == 9) 47 { 48 state = 9; 49 current_x = 0; 50 } 51 current_x++; 52 } 53 while (state != 9); 54 state = 0; 55 cout << endl; 56 } 57}

gnolam
Member #2,030
March 2002
avatar

added -wall to my compiler

GCC's options are case sensitive. It's -Wall, not -wall (and you should always compile with it enabled).You should enable optimizations (-O2) as well, as it helps catch even more bad practices.

Quote:

int tile[maphight][100], current_x = 0, state;

You're not initializing state.
(Also: it's spelled "height", not "hight")

if (tile[current_y][current_x] == 9)

If tile[current_y][current_x] isn't equal to 9 in time, you'll run past the end of your array and Bad ThingsTM will happen.

Quote:

state = 9;

Now what is that supposed to mean? A state of 9? Don't use magic numbers. Code should be self-documenting.

Oh, and if an operation can fail (e.g. opening map.txt), check to see if it does. Always.

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

Ryan Rees-Williams
Member #13,825
December 2011

I'm using CodeBlocks, its a check box for my compiler options so don't worry about my spelling ;) changed it to state = 0; and I used state = 9 because it was easy to remember at the time, I could easily change it to a bool if it is more readable to other programmers? and I'm looking for a function to check if a file is open right now :)

Dario ff
Member #10,065
August 2008
avatar

Why don't you just break the loop instead of juggling with state=0 and state=9? :P

EDIT: Giving it another read, I'm not sure what that code is actually doing.

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Ryan Rees-Williams
Member #13,825
December 2011

it's reading integers from a txt file and loading them into a 2D array for use as a map in a game, it's a little messy I know but it's a first attempt (I have given up on the CSV stuff for now, as the more people tried to help me the more confused I got, nothing wrong with the advice it was just me being inexperienced)
if you wan't a look at the what the code is like right now ill include t:

#SelectExpand
1#include <iostream> 2#include <fstream> 3#include <cstdlib> 4#include <allegro.h> 5#include "allegrofunctions.h" 6 7using namespace std; 8 9int main() 10{ 11 setupallegro(640,480,32,false); 12 BITMAP *buffer = create_bitmap(640,480); 13 BITMAP *maptile = load_bitmap("map.bmp",NULL); 14 15 ifstream in_stream; 16 ofstream out_stream; 17 in_stream.open("map.txt"); 18 19 int maphight; 20 21 in_stream >> maphight; 22 23 int tile[maphight][100], current_x = 0; 24 bool statetile = false; 25 26 for (int current_y = 0; current_y < maphight; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 27 { 28 do 29 { 30 in_stream >> tile[current_y][current_x]; 31 if (tile[current_y][current_x] == 9) 32 { 33 statetile = true; 34 current_x = -1; 35 } 36 current_x++; 37 } 38 while (statetile != true); 39 statetile = false; 40 } 41 current_x = 0; 42 in_stream.close(); 43 44 for (int current_y = 0; current_y < maphight; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 45 { 46 do 47 { 48 masked_blit(maptile,buffer,tile[current_y][current_x]*32,0,current_x*32,current_y*32,32,32); 49 if (tile[current_y][current_x] == 9) 50 { 51 statetile = true; 52 current_x = -1; 53 } 54 current_x++; 55 } 56 while (statetile != true); 57 statetile = false; 58 } 59 60 while (!key[KEY_ESC]) 61 { 62 blit(buffer,screen,0,0,0,0,640,480); 63 } 64 65 return 0; 66} 67END_OF_MAIN();

the image I load is a simple 64*32 bitmap if you want to test the code yourself

Dario ff
Member #10,065
August 2008
avatar

What I meant is, can't this:

#SelectExpand
1 for (int current_y = 0; current_y < maphight; current_y++) /*10 being the highest possible map size, could change through reading how high the map is from the file*/ 2 { 3 do 4 { 5 in_stream >> tile[current_y][current_x]; 6 if (tile[current_y][current_x] == 9) 7 { 8 statetile = true; 9 current_x = -1; 10 } 11 current_x++; 12 } 13 while (statetile != true); 14 statetile = false; 15 }

...be replaced by this? You seem to handle for loops alright, so I don't see why not.

    for (int current_y = 0; current_y < maphight; current_y++)
    {
        for (int current_x = 0; current_x < 100; current_x++) // 100 seems to be your hardcoded limit, should probably be replaced by mapwidth later
        {
            in_stream >> tile[current_y][current_x];
            if (tile[current_y][current_x] == 9) break;
        }
    }

???

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Ryan Rees-Williams
Member #13,825
December 2011

never tried break before, ill give it a whirl and see if it works with my code :)
EDIT
Yup! it worked! thanks for that tip :D

Dario ff
Member #10,065
August 2008
avatar

Now do it with mapwidth as well so you can get rid of the silly '9' magic limit and not have a hardcoded limit of 100. :P

TranslatorHack 2010, a human translation chain in a.cc.
My games: [GiftCraft] - [Blocky Rhythm[SH2011]] - [Elven Revolution] - [Dune Smasher!]

Ryan Rees-Williams
Member #13,825
December 2011

TaDaaa!:

#SelectExpand
1#include <iostream> 2#include <fstream> 3#include <cstdlib> 4#include <allegro.h> 5#include "allegrofunctions.h" 6 7using namespace std; 8 9int main() 10{ 11 setupallegro(640,480,32,false); 12 BITMAP *buffer = create_bitmap(640,480); 13 BITMAP *maptile = load_bitmap("map.bmp",NULL); 14 15 ifstream in_stream; 16 ofstream out_stream; 17 in_stream.open("map.txt"); 18 19 int maphight, mapwidth; 20 21 in_stream >> maphight; 22 in_stream >> mapwidth; 23 24 int tile[maphight][mapwidth], current_x = 0; 25 bool statetile = false; 26 27 for (int current_y = 0; current_y < maphight; current_y++) 28 { 29 for (int current_x = 0; current_x < mapwidth; current_x++) // 100 seems to be your hardcoded limit, should probably be replaced by mapwidth later 30 { 31 in_stream >> tile[current_y][current_x]; 32 } 33 } 34 35 current_x = 0; 36 in_stream.close(); 37 38 for (int current_y = 0; current_y < maphight; current_y++) 39 { 40 for (int current_x = 0; current_x < mapwidth; current_x++) // 100 seems to be your hardcoded limit, should probably be replaced by mapwidth later 41 { 42 masked_blit(maptile,buffer,tile[current_y][current_x]*32,0,current_x*32,current_y*32,32,32); 43 } 44 } 45 46 while (!key[KEY_ESC]) 47 { 48 blit(buffer,screen,0,0,0,0,640,480); 49 } 50 51 return 0; 52} 53END_OF_MAIN();

now my map file looks like this:

10
17
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

a lot cleaner :) if only there was a way of reading how many values there is on one line of the file, then I could get rid of the two values at the start of the file

 1   2   3 


Go to: