Back with another question concerning my RPG. I had the idea to do a multi-dimensional array to represent a map, with each element in the array being it's own square, Depending on where you are, you can move in any of the 4 directions, unless you are on an edge. Also, I wanted to have specific squares represent towns and such.

The only problem is I'm not very good with arrays. I can initialize it, but that's about it. I just need some suggestions to get me going in the right direction.

Recommended Answers

All 31 Replies

You could create a class that handles the boundaries of your multi-dimension array.

My question is this -- are you planning on having only 2 dimensions for the map or 3 in the event that you want to do some kind of map-switch?

My question is this -- are you planning on having only 2 dimensions for the map or 3 in the event that you want to do some kind of map-switch?

Just 2, a chessboard with special squares (only bigger of course)

er, now that I think about it though, is it possible to have like dungeons or something that have their own specific map layouts?

Just 2, a chessboard with special squares (only bigger of course)

er, now that I think about it though, is it possible to have like dungeons or something that have their own specific map layouts?

Of course. It's your multi-dimension array, you can set it up any way you like.

You're going to want to do this the easy way... and when I mean the easy way I mean having your map already built in a .txt file then read the characters into a 2D char array...

#ifndef MAPXSIZE
#define MAPXSIZE 8
#endif
#ifndef MAPYSIZE
#define MAPYSIZE 8
#endif

typedef char MapArray[MAPXSIZE][MAPYSIZE] = {0};

MapArray firstMap, dungeon1Map, dungeon2Map; //... however many maps that you may need

//code to fill map with chars from .txt file

Why would you want to fill up the array with chars though?

Why would you want to fill up the array with chars though?

You're trying to display your map on the screen correct?

Doing so with characters is your best bet unless you're using Windows API and you're forming an application.

You'll have to give me more details on your program - I'm thinking that you're making a text-based RPG to be seen in the Console screen, so the first thing that came to mind were pre-placed characters from a text file.

a char will hold a single character, which is just an 8-bit int.

what information are you trying to contain in any 'square'?

this doesnt seem very meaningful, to have one char value in any square...

You'll have to give me more details on your program - I'm thinking that you're making a text-based RPG to be seen in the Console screen, so the first thing that came to mind were pre-placed characters from a text file.

Oh I see. Well my original intent was to start with just a basic coordinate system, with no visible map displayed on the screen. As you move, it would display what square you moved to by outputting your coordinates. And the last feature I wanted was to have certain squares be represented by towns (and eventually dungeons), so for now I want to keep it simple until I've learned more in C++.

---|---|---|---
---|---|---|---
---|---|---|---
---|x | t |---

x <- you are here. Then you're given the option to move north, east or west.
t <- town here. Step on this square and you'll get to do town things like store/inn.

Doing so with characters is your best bet unless you're using Windows API and you're forming an application.

this doesnt make any sense. what's any of this got to do with Windows API?

you've got an 8x8 matrix of single characters... what meaningful information can you have in such a thing?

you should make an 8x8 matrix of a structure that describes every important aspect of any board position.

Oh I see. Well my original intent was to start with just a basic coordinate system, with no visible map displayed on the screen. As you move, it would display what square you moved to by outputting your coordinates. And the last feature I wanted was to have certain squares be represented by towns (and eventually dungeons), so for now I want to keep it simple until I've learned more in C++.

---|---|---|---
---|---|---|---
---|---|---|---
---|x | t |---

x <- you are here. Then you're given the option to move north, east or west.
t <- town here. Step on this square and you'll get to do town things like store/inn.

Then you just want to display the numbers and maybe display the numbers of the valid locations to move to next?

In that case I really don't think you need arrays or file i/o. You just need to have predefined coordinates for places.

Then you just want to display the numbers and maybe display the numbers of the valid locations to move to next?

In that case I really don't think you need arrays or file i/o. You just need to have predefined coordinates for places.

Yeah... actually now that I think about it, that sounds like it would work. I could do if(x=7, y=2){ type statements to represent towns, and increment/decrement x/y coordinates depending on which direction you pick.

I'm just not sure what the most efficient way to define the borders is, to make sure that the x/y coordinates won't get higher or lower than I want them to.

this doesnt make any sense. what's any of this got to do with Windows API?

you've got an 8x8 matrix of single characters... what meaningful information can you have in such a thing?

you should make an 8x8 matrix of a structure that describes every important aspect of any board position.

True. You can have a struct that holds the x and y information of the board.

Unfortunately I wasn't given enough information at the start other than the fact that the original poster wanted a map in a text-based RPG and wanted the characters capable of moving around in the array without going out of the bounds.

My first suggestion was a restricted array (or class) that would not allow the user to go out of bounds.

I also assumed that the original poster wanted to visually understand what was going on and had enough C++ experience to use file I/O and represent the map as a set of characters.

Yeah... actually now that I think about it, that sounds like it would work. I could do if(x=7, y=2){ type statements to represent towns, and increment/decrement x/y coordinates depending on which direction you pick.

I'm just not sure what the most efficient way to define the borders is, to make sure that the x/y coordinates won't get higher or lower than I want them to.

You don't need a 2D array of chars or anything else, just an array of structs and a starting-location for your character.

You'll probably also want to make a switch statement (or if statements) that handles the possible moves for the character.

typedef struct Location
{
      int x, y;
      Location(int col, int row) : x(col), y(row){}
};

Location Inn(4, 3), TrainingArea(2, 2), Gate(0, 4);

Okay, I think I get it now, the only question I have is what does the : x(col), y(row) - on part mean?

Okay, I think I get it now, the only question I have is what does the : x(col), y(row) - on part mean?

Pre-initialization - because the assignment operator causes a copy of the object to be made during the assignment, which can cause the program to do more work than it should.

Pre-initializing is considered good programming practice.

#include <iostream>

using namespace std;

	typedef struct Location
	{
		int x, y;
  		Location(int col, int row) : x(col), y(row){}
	};

Location Start(2,2);

int main(){
    cout<< Location.start;
	cin.get();
	}

I'm doing something wrong =\

#include <iostream>

using namespace std;

	typedef struct Location
	{
		int x, y;
  		Location(int col, int row) : x(col), y(row){}
	};

Location Start(2,2);

int main(){
    cout<< Location.start;
	cin.get();
	}

I'm doing something wrong =\

Location is just a typedef for Locations. You can use the word Location to create coordinate objects, for example--

Location Inn(3, 4); //creates a location struct named Inn with x set to 3 and y to 4

Furthermore, the variable/function "start" doesn't exist in Location, and you cannot call Location in that way since its just a definition for anything that is that type.

In your above example, Start IS a location struct, so you can call upon its coordinates in this way--

cout << Start.x << ", " << Start.y << endl;

Aha! I see now, it's just as if I were using a variable in a class, except with the structure name. And the typedef struct Location is making a structure that has x,y coordinates.

With that said, it sounds like it will be simple enough to make a switch that lets you choose which direction you go, with an if inside it that checks if it is on the border or not.

Now the problem I'm having is how do I use a struct like Location Inn like you described above to give you different options depending on your location in the grid? I'm able to move around my grid from 1-10 in both the x/y directions, but that's all I've got so far.

Now the problem I'm having is how do I use a struct like Location Inn like you described above to give you different options depending on your location in the grid? I'm able to move around my grid from 1-10 in both the x/y directions, but that's all I've got so far.

You should have an if statement that takes into account many cases while you are moving (I'm assuming you're moving in a loop).

while(true /*or whichever condition you use to keep movement going*/)
{
       //...
       if(currentX == Start.x && currentY == Start.y)
       {
               //do something
       }       


       //...

}

Assuming that you want to do it the fairly easy way.

So that's the easy way. Is there a better, more efficient way, or is this what would actually be accepted as good coding?

So that's the easy way. Is there a better, more efficient way, or is this what would actually be accepted as good coding?

There is, and I've been working on a good example for some time now.

Consider the following code, where I store created Location objects in an array then reference each of them. Notice the new name-parameter I gave them. This will help reduce the amount of code you write in your movement loop, but it will increase the code in your Location structs--

#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

typedef struct SomeStruct
{ 
       private:
              string name;
               
       public:
              int x, y;
              
              SomeStruct(const char *arg, int xLoc, int yLoc)
              : name(arg), x(xLoc), y(yLoc){}
              
              void doSomething()
              {
                   if(name == "ok")
                   {
                          cout << "Ok!" << endl;         
                   }
                   else if(name == "inn")
                   {
                          cout << "I'm an inn!" << endl;
                   }
                   else if(name == "start")
                   {
                          cout << "Starting!" << endl;
                   }
                   /*
                   else if...
                   */
                   else//final case
                   {
                        
                   }
                  
              }
}Location;

#ifndef LOCATIONS
#define LOCATIONS 2
#endif

Location Inn("inn", 2, 4), Start("start", 0, 4); 

Location loc[] = {  Inn,  Start  };


int main(int argc, char *argv[])
{
     int currentX = 2, currentY = 4; //notice that these are the inn's cooridnates

     //inside your movement-loop...

     for(int i = 0; i < LOCATIONS; i++)
     {
           if(loc[i].x == currentX && loc[i].y == currentY)
              loc[i].doSomething();
     }
     
    
     cin.get();
     return 0;
}

--There's also another way of doing this, but it involves mid-first-quarter C++ knowledge.

commented: Had to wait 24 hours +1

Wow, I actually understood the majority of that code.

Things I didn't:

#
}Location;

#ifndef LOCATIONS
#define LOCATIONS 2
#endif

This part: Why do you have Location; outside the SomeStruct braces? Also the #indef part, I've seen it before but I'm not entirely sure what it means.

Also the part within the for loop. I think I understand the part within the if braces, but I just don't understand the increment part in the for arguments.

Wow, I actually understood the majority of that code.

Things I didn't:

#
}Location;

#ifndef LOCATIONS
#define LOCATIONS 2
#endif

This part: Why do you have Location; outside the SomeStruct braces? Also the #indef part, I've seen it before but I'm not entirely sure what it means.

Also the part within the for loop. I think I understand the part within the if braces, but I just don't understand the increment part in the for arguments.

SomeStruct is just a typedef for objects of its kind. It's like how int is a type-definition for ints.

When you say int x, you are declaring that x is a reference-variable for int objects (well, to an extent. ints are really primitive types and not objects, but they have good enough similarities for this example). The same applies for Location - it's just a shorter, and a more understandable name for "SomeStruct" and performs the same way a SomeStruct object would.

The preprocessor directives are pretty self explanatory. You can define a macro with a value or with actual code or anything and anytime your project is built/compiled and that exact word is found in the code, it will replace the word with the code/value that it is associated with. Example...

#define DBL double

DBL x = 2.2;

Whats really happening is DBL is being replaced by the keyword double during compile time, and it is interpreted like this-- double x = 2.2; #ifndef means "If not defined, then..." - basically if the preprocessor definition LOCATIONS was not defined, then--

#define LOCATIONS 2

--define it to be replaced for 2 whenever the compiler runs into the word LOCATIONS. The endif was necessary to "close" the definition because, like stated earlier, you can lump chunks of code into definitions. Even this would be legal--

#ifndef MYMAIN
#define MYMAIN
int main()
{
    cout << "MYMAIN wasn't defined but now is" << endl;
    cin.get();
    return 0;
}
#else
#undef MYMAIN
#define MYMAIN
int main()
{
    cout << "MYMAIN was previously defined but was redefined" << endl;
    cin.get();
    return 0;
}
#endif

--as for the for loop, the syntax for a for loop is this--

for(initializer; loop contuing condition; increment/decrement)
{
    //for-loop block
}

--It's pretty straightforward. Once the "block" that was currently read has finished then it will be repeated and the right-most argument in the for loop (the increment/decrement) will be incremented or decremented depending on the syntax.

In my example, you don't see a block. That's because I only wanted the for loop to examine 1 line of code. If you forget to leave the block out and do something like this--

for(int i = 0; i < 3; i++)
    someArray[i].whatever();
    someArray2[i].yattaYatta();

--you'll get a syntax error because the local variable i doesn't exist outside of the block that it was defined, and since there are no blocks in this for loop the invisible "block" is around the first line someArray.whatever() and does not reach someArray2.yattaYatta().

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

	typedef struct SomeStruct
	{
		
        private:
        	string name;
  		
    
   	    public:
       	    int x, y;
       	    SomeStruct(const char *arg, int xLoc, int yLoc) : name(arg), x(xLoc), y(yLoc){}
	
       void doSomething(){
       		if(name== "ok"){
       			cout<<"Okay!";}
       		else if(name== "inn"){
       			cout<<"You're at an inn." << endl;}
   			else if(name== "start"){
   			 	cout<<"Start!" << endl;}
      			
    			
	    }
}Location;

#ifndef LOCATIONS
#define LOCATIONS 2
#endif

Location Inn("inn", 2, 4), Start("start", 0, 4);

Location loc[] = { Inn, Start};



int main(){
	for(;;)
    	{
    	
    	int currentX= 2, currentY=4;
    		
      
      
      int direction;
      		cout<<"What direction do you want to go?";
   			cin>> direction;
   			
   			switch(direction){
   				case 1:
   					if(currentX == 10){
   						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;}
					else{
        			currentX= currentX++;
   					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			break;
 					}
 					
 				 case 2:
      				if(currentX ==1){
          				cout<<"\nYou cannot go any farther in that direction."<< endl;
          				break;}
      				else{
     					currentX= currentX--;
     					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        				break;}
        				
        				
  				case 3:
					if(currentY== 10){
						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;}
					else{
        			currentY= currentY++;
   					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			break;}
        			
     			case 4:
					if(currentY==1){
						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;}
					else{
        			currentY= currentY--;
   					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			break;}
          
            
              
                  }
        
         for(int i = 0; i < LOCATIONS; i++)
         	{
          		if(loc[i].x == currentX && loc[i].y == currentY)
          		loc[i].doSomething();
          
           
            
         }
     }
     cin.get();
 }

I'm not exactly sure where you expected me to but the for() loop, but that's my current/not working source code

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

	typedef struct SomeStruct
	{
		
        private:
        	string name;
  		
    
   	    public:
       	    int x, y;
       	    SomeStruct(const char *arg, int xLoc, int yLoc) : name(arg), x(xLoc), y(yLoc){}
	
       void doSomething(){
       		if(name== "ok"){
       			cout<<"Okay!";}
       		else if(name== "inn"){
       			cout<<"You're at an inn." << endl;}
   			else if(name== "start"){
   			 	cout<<"Start!" << endl;}
      			
    			
	    }
}Location;

#ifndef LOCATIONS
#define LOCATIONS 2
#endif

Location Inn("inn", 2, 4), Start("start", 0, 4);

Location loc[] = { Inn, Start};



int main()
{
    int currentX= 2, currentY=4; //placed the coordinates outside of the for loop block
	for(;;)
	{
    	
    	
    		
      
      
      int direction;
      		cout<<"What direction do you want to go?";
   			cin>> direction;
   			
   			switch(direction)
            {
   				case 1:
   					if(currentX == 10){
   						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;}
					else{
        			currentX++; //changed
   					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			break;
 					}
 					
 				 case 2:
      				if(currentX ==1)
                    {
          				cout<<"\nYou cannot go any farther in that direction."<< endl;
          				break;
                    }
      				else
                    {
     					currentX--;//changed
     					cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        				break;
                    }
  				case 3:
					if(currentY== 10)
                    {
						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;
                    }
					else
                    {
        			    currentY++;//changed
   					   cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			    break;
                    }
        			
     			case 4:
					if(currentY==1)
                    {
						cout<<"\nYou cannot go any farther that that direction."<< endl;
   						break;
                    }
					else
                    {
        			   currentY--;//changed
	                   cout<<"\nYour coordinates are " << currentX <<"," << currentY <<"." << endl;
        			   break;
                    }
          
            
              
                  }
        
              for(int i = 0; i < LOCATIONS; i++)
       	      {
          		if(loc[i].x == currentX && loc[i].y == currentY)
          		loc[i].doSomething();
              }
     }
     cin.get();
 }

Should work now.

Fair warning, the statements (and others alike)--

currentX = currentX++;

Will always equal whatever the value was, because this implies that you want to assign the value of currentX to currentX then increment currentX, but unfortunately the currentX on the left gains a copy of the value on the right and doesn't increment the copied value. It's a very subtle thing, and I hardly noticed it nor did I expect it to make that kind of result, but it did.

Should work now.

Yep, it does, thank you. As far as I'm concerned there's no way in HELL I would have come up with that on my own.

Again though the one thing I'm trying to puzzle out the specifics of:

for(int i = 0; i < LOCATIONS; i++)
         {
          if(loc[i].x == currentX && loc[i].y == currentY)
          	loc[i].doSomething();
          }

The reasons I'm confused are the i < LOCATIONS and the loc stuff. What part of the array is loc accessing? Where do you get the value for LOCATIONS? And why does i even need to be incremented? Sorry to ask the same general question as before, I just want to make sure I'm actually understanding this.

Yep, it does, thank you. As far as I'm concerned there's no way in HELL I would have come up with that on my own.

Again though the one thing I'm trying to puzzle out the specifics of:

for(int i = 0; i < LOCATIONS; i++)
         {
          if(loc[i].x == currentX && loc[i].y == currentY)
          	loc[i].doSomething();
          }

The reasons I'm confused are the i < LOCATIONS and the loc stuff. What part of the array is loc accessing? Where do you get the value for LOCATIONS? And why does i even need to be incremented? Sorry to ask the same general question as before, I just want to make sure I'm actually understanding this.

Remember, LOCATIONS is a macro that is defined by the preprocessor definition #define LOCATIONS 2 so any time the compiler sees LOCATIONS it really is 2.

The loc variable is the array defined here--

Location loc[] = { Inn, Start};

--and Inn is located at indice 0 of the array and Start is at indice 1.

Notice that although the size of the array is 2, we never get to 2. The reason is because of how elements are accessed in the array. You can only access from 0- to- (n-1) indices where n is the size.

In the for loop, I'm iterating through the loc array by incrementing i.--

for(int i = 0; i < LOCATIONS; i++)
       	      {
          		if(loc[i].x == currentX && loc[i].y == currentY)
          		loc[i].doSomething();
              }

--if I didn't increment i, for example--

for(int i = 0; i < LOCATIONS;)
       	      {
          		if(loc[i].x == currentX && loc[i].y == currentY)
          		loc[i].doSomething();
              }

--it would result in an infinite loop because i always meets the condition of being less than LOCATIONS (since i was initialized to zero at the start of the loop and the condition to keep the loop going is i < LOCATIONS or 0 < 2 and i never increments).

Edit: Furthermore, if I didn't increment i, I would only be accessing loc[0] when really I'd like to iterate through all of the element to see if I'm 'at that location'.

OH! I get it now! What it's doing is it's going through all the elements in the array, and checking each of their coordinates against the current coordinates. It increments to move onto the next object in the array, and if none of them match, the loop breaks and it returns to the top. =)

Does that mean that I need to change the value of LOCATIONS to however many special squares I want? Like for different towns, etc.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.