Map/vector of classes and objects??

I have a bunch of if-else statements for every dungeon function. How can i create a map using a struct as a key and my class as a value? or maybe even a vector? My teacher told me that i can simplify all my if else statements into less than 15 lines of code using the STL, and this is what i came up with. So far no luck :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
class Monsters
{
	public:
		int Damage;
		int PowerUp;
		int Monster_Strength;
		int hp;
		int lvl;
		int money;
		int defense;
};

  struct key
{
   int dungeon_lvl;
   int monster_lvl;

} maps;

//objects
Monsters Monster_Dungeon1;

map<key, Monsters> Cool;
Cool.insert(pair<key, Monsters>(key(maps.dungeon_lvl),Monsters(Monster_Dungeon1)));
//I tried something like this, but it didn't work.

 void Dungeon1()
	{
		srand ((unsigned)time(0));
		Monster_Dungeon1.lvl = rand() % 10 + 1;
	if (Monster_Dungeon1.lvl == 1)
	{
		cout << "A lvl 1 Monster has appeared!";
		Monster_Dungeon1.hp = 10;
		Monster_Dungeon1.Monster_Strength = 5;
		Monster_Dungeon1.defense = 0;
		Monster_Dungeon1.money = 5;
	}
	else if (Monster_Dungeon1.lvl == 2)
	{
		cout << "\nA lvl 2 Monster has appeared!";
		Monster_Dungeon1.hp = 10;
		Monster_Dungeon1.Monster_Strength = 5;
		Monster_Dungeon1.defense = 0;
		Monster_Dungeon1.money =10;
	}
	else if (Monster_Dungeon1.lvl == 3)
	{
		cout << "\nA lvl 3 Monster has appeared!";
		Monster_Dungeon1.hp = 15;
		Monster_Dungeon1.Monster_Strength = 5;
		Monster_Dungeon1.defense = 0;
		Monster_Dungeon1.money = 20;
	}
	else if (Monster_Dungeon1.lvl == 4)
	{
		cout << "\nA lvl 4 Monster has appeared!";
		Monster_Dungeon1.hp = 20;
		Monster_Dungeon1.Monster_Strength = 5;
		Monster_Dungeon1.defense = 0;
		Monster_Dungeon1.money = 25;
	}
	else if (Monster_Dungeon1.lvl == 5)
	{
		cout << "\nA lvl 5 Monster has appeared!";
		Monster_Dungeon1.hp = 25;
		Monster_Dungeon1.Monster_Strength = 7;
		Monster_Dungeon1.defense = 2;
		Monster_Dungeon1.money = 25;
	}
	else if (Monster_Dungeon1.lvl == 6)
	{
		cout << "\nA lvl 6 Monster has appeared!";
		Monster_Dungeon1.hp = 30;
		Monster_Dungeon1.Monster_Strength = 7;
		Monster_Dungeon1.defense = 4;
		Monster_Dungeon1.money = 25;
	}
	else if (Monster_Dungeon1.lvl == 7)
	{
		cout << "\nA lvl 7 Monster has appeared!";
		Monster_Dungeon1.hp = 35;
		Monster_Dungeon1.Monster_Strength = 7;
		Monster_Dungeon1.defense = 4;
		Monster_Dungeon1.money = 30;
	}
	else if (Monster_Dungeon1.lvl == 8)
	{
		cout << "\nA lvl 8 Monster has appeared!";
		Monster_Dungeon1.hp = 40;
		Monster_Dungeon1.Monster_Strength = 8;
		Monster_Dungeon1.defense = 4;
		Monster_Dungeon1.money = 35;
	}
	else if (Monster_Dungeon1.lvl == 9)
	{
		cout << "\nA vlvl 9 Monster has appeared!";
		Monster_Dungeon1.hp = 40;
		Monster_Dungeon1.Monster_Strength = 9;
		Monster_Dungeon1.defense = 5;
		Monster_Dungeon1.money = 35;
	}
	else if (Monster_Dungeon1.lvl == 10)
	{
		cout << "\nA lvl 10 Monster has appeared!";
		Monster_Dungeon1.hp = 45;
		Monster_Dungeon1.Monster_Strength = 10;
		Monster_Dungeon1.defense = 5;
		Monster_Dungeon1.money = 40;
	}
	else
		cout << "\nDUNGEON LEVEL 1 ERROR" << endl;
	}

I have 11 dungeons, but i only put one Dungeon, because its way too lengthy.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <map>

struct monster
{
    int Damage;
    int PowerUp;
    int Monster_Strength;
    int hp;
    int lvl;
    int money;
    int defense;
};

using key = std::pair<int,int> ; // dungeon_level,moster_level pair

// or typedef std::pair<int,int> key ; // C++98

std::map< key, monster > look_up ;
Sorry, but since i am a beginner i really don't understand. Do i create a map object like this?

look_up[1,1] = Monster_Dungeon1; ?

since the key uses two ints, the key should be like
[1,1]
or something right? and then ill need to use the object of my class monster which is

= Monster_Dungeon1
But, i know i am doing something wrong, please help!
The key is a pair std::pair<int,int>
http://en.cppreference.com/w/cpp/utility/pair

You can create a key with std::make_pair()
http://en.cppreference.com/w/cpp/utility/pair/make_pair

To insert an entry into std::map< key, monster > look_up ;
1
2
3
4
monster this_monster = { /* .... */ } ;
int dungeon_level = 3 ;
int monster_level = 5 ;
look_up[ std::make_pair( dungeon_level, monster_level ) ] = this_monster ; 
Im stilll kind of fuzzy over maps. Sorry for all the trouble i might be causing you :( But thanks a bunch for taking your time out to help me! i really appreciate it!
I have a question though. I still don't understand how to print out the pairs? Will i have to make a for loop to initialize the map? and what goes in the places i put comments in?
1
2
3
4
5
6
7
using key = pair<int,int>;//dungeon_level,moster_level pair
map< key, Monsters > look_up ;
Monsters Monster_Dungeon1 = {/*what goes here?*/ } ;
int dungeon_level = 3 ;
int monster_level = 5 ;
look_up[make_pair( dungeon_level, monster_level ) ] = Monster_Dungeon1;
cout << key.first;//Is this how you would print it? 
> Monsters Monster_Dungeon1 = {/*what goes here?*/ } ;

To initialize a monster, specify the values of the member variables Damage, PowerUp etc. in order of declaration. For instance:

Monsters Monster_Dungeon1 = { 23 /*Damage*/, 2/*PowerUp*/ /* etc...*/ } ;


> I still don't understand how to print out the pairs?
> cout << key.first;//Is this how you would print it?

To print out a pair, print out both the values in it. For instance:

std::cout << '(' << key.first << ',' << key.second << ')' ;


> Will i have to make a for loop to initialize the map?

You could use a for loop to insert key value pairs into it. For example:
look_up[ std::make_pair( dungeon_level, monster_level ) ] = Monster_Dungeon1 ;

In C++11, you can also initialize it this way:

1
2
3
4
5
6
std::map< key, monster > look_up = 
{
     { { 1, 1 } /* key */, { 23, 2, 5, 8, 19, 7 } /* monster 1,1*/ }, 
     { { 1, 2 } /* key */, { 5, 7, 15, 2, 8, 15 } /* monster 1,2*/ },
      // etc... 
};

I would recommend a switch instead of all the if/else
1
2
3
4
5
6
7
switch(Monster_Dungeon1.lvl )
{
    case 1: /*...*/ break;
    case 2: /*...*/ break;
    /...
    default: /*...*/break //if you have a case that is none of the others
}
Ok JLBorges, i tried what you did but these are the errors im getting.
1
2
3
4
5
6
7
8
9
10
11
12
13
	using key = pair<int,int>;//dungeon_level,moster_level pair
	map< key, Monsters > look_up ;
	Monsters Monster_Dungeon1 = { 5, 10, 15, 20, 25, 30} ;
	int dungeon_level = 3 ;
	int monster_level = 5 ;
	look_up[make_pair( dungeon_level, monster_level ) ] = Monster_Dungeon1;

	map< key, Monsters > look_up = 
	{
     { { 1, 1 } /* key */, { 23, 2, 5, 8, 19, 7 } /* monster 1,1*/ }, 
     { { 1, 2 } /* key */, { 5, 7, 15, 2, 8, 15 } /* monster 1,2*/ },
	};//Error Initialization is not allowed for object type
	cout << '(' << key.first << ',' << key.second << ')' ;//Error type name is not allowed 

And giblit, i cant do a switch because i have way too many if else statements. The problem is that i don't want it to be that long, which is why i thought maps where a good idea, but its too complicated :(
> Error Initialization is not allowed for object type

For that construct, you need a C++11 compiler (if you are using GCC, compile with -std=c+11)


> Error type name is not allowed

Use the actual key, not the name of the type.


Things would be easier if you write a couple of overloaded operators to print out the key and the monster.

This is C++11:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <map>

struct monster
{
    int Damage;
    int PowerUp;
    int Monster_Strength;
    int hp;
    int lvl;
    int money;
    int defense;
};


using key = std::pair<int,int> ; // dungeon_level,moster_level pair

// or typedef std::pair<int,int> key ; // C++98

std::map< key, monster > look_up =
{
 { { 1, 1 } /* key */, { 23, 2, 5, 8, 19, 7, 9 } /* monster 1,1*/ },
 { { 1, 2 } /* key */, { 5, 7, 15, 2, 8, 15, 6 } /* monster 1,2*/ },
 { { 3, 5 } /* key */, { 1, 3, 11, 9, 17, 6, 1 } /* monster 3,5*/ },
};

#include <iostream>

std::ostream& operator << ( std::ostream& stm, const key& k )
{ return stm << '(' << k.first << ',' << k.second << ')' ; }

std::ostream& operator << ( std::ostream& stm, const monster& m )
{
    return stm << "monster{" << m.Damage << ',' << m.PowerUp << ',' << m.Monster_Strength
                << ',' << m.hp << ',' << m.lvl << ',' << m.money << ',' << m.money << '}' ;
}

int main()
{
    key k = { 1, 2 } ;
    std::cout  << k << '\n' ;

    for( const auto& p : look_up )
        std::cout << "key: " << p.first << " => data: " << p.second << '\n' ;
}

http://ideone.com/1vrWgY

Equivalent C+98 code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <map>

struct monster
{
    int Damage;
    int PowerUp;
    int Monster_Strength;
    int hp;
    int lvl;
    int money;
    int defense;
};

typedef std::pair<int,int> key ; // dungeon_level,moster_level pair

std::map< key, monster > look_up ;
#include <iostream>

std::ostream& operator << ( std::ostream& stm, const key& k )
{ return stm << '(' << k.first << ',' << k.second << ')' ; }

std::ostream& operator << ( std::ostream& stm, const monster& m )
{
    return stm << "monster{" << m.Damage << ',' << m.PowerUp << ',' << m.Monster_Strength
                << ',' << m.hp << ',' << m.lvl << ',' << m.money << ',' << m.money << '}' ;
}

int main()
{
    // initialize look_up
    {
         monster m11 = { 23, 2, 5, 8, 19, 7, 9 } ; /* monster 1,1*/
         look_up[ key(1,1) ] = m11 ;

         monster m12 = { 5, 7, 15, 2, 8, 15, 6 } ; /* monster 1,2*/
         look_up[ key(1,2) ] = m12 ;

         monster m35 = { 1, 3, 11, 9, 17, 6, 1 } ; /* monster 3,5*/
         look_up[ key(3,5) ] = m35 ;
    }

    key k( 1, 2 ) ;
    std::cout  << k << '\n' ;

    typedef std::map< key, monster >::iterator iterator_t ;
    for( iterator_t iter = look_up.begin() ; iter != look_up.end() ; ++iter )
        std::cout << "key: " << iter->first << " => data: " << iter->second << '\n' ;
}

http://ideone.com/K26REN
Last edited on
OMG THANK YOU!!!!!!
It works perfectly but only if its declared within my source.cpp. If i move it out to my other .cpp file thats connected with my header where my monster struct is declared, it stops working.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

//MyFunctions.h
#pragma once

struct Monsters
{
	public:
		int Damage;
		int PowerUp;
		int Monster_Strength;
		int hp;
		int lvl;
		int money;
		int defense;
};


1
2
3
4
5
6
7
8
9
10
11
//MyFunctions.cpp
#include <iostream>
#include <map>
#include "MyFunctions.h"

using namespace std;

{
   This is where i want to put the code, because it looks ugly having it in my main .cpp file.
 I properly included the headers and everything. It just keeps saying redefinition of everything.
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

//Source.cpp
typedef pair<int,int> key ; // dungeon_level,moster_level pair
 
map< key, Monsters > look_up ;
 
ostream& operator << ( ostream& stm, const key& k )
{ return stm << '(' << k.first << ',' << k.second << ')' ; }
 
ostream& operator << ( ostream& stm, const Monsters& m )
{
    return stm << "monster{" << m.Damage << ',' << m.PowerUp << ',' << m.Monster_Strength
                << ',' << m.hp << ',' << m.lvl << ',' << m.money << ',' << m.money << '}' ;
}


int main()
{

	 // initialize look_up
    {
         Monsters m11 = { 23, 2, 5, 8, 19, 7, 9 } ; /* monster 1,1*/
         look_up[ key(1,1) ] = m11 ;
 
         Monsters m12 = { 5, 7, 15, 2, 8, 15, 6 } ;
         look_up[ key(1,2) ] = m12 ;
 
         Monsters m13 = { 1, 3, 11, 9, 17, 6, 1 } ; 
         look_up[ key(1,3) ] = m13 ;

		 Monsters m14 = { 1, 3, 11, 9, 17, 6, 1 } ; 
         look_up[ key(1,4) ] = m14 ;

		 Monsters m15 = { 1, 3, 11, 9, 17, 6, 1 } ; 
         look_up[ key(1,5) ] = m15 ;

		 Monsters m16 = { 1, 3, 11, 9, 17, 6, 1 } ;
         look_up[ key(1,6) ] = m16 ;

		 Monsters m17 = { 1, 3, 11, 9, 17, 6, 1 } ; 
         look_up[ key(1,7) ] = m17 ;

		 Monsters m18 = { 1, 3, 11, 9, 17, 6, 1 } ; 
         look_up[ key(1,8) ] = m18 ;

		 Monsters m19 = { 1, 3, 11, 9, 17, 6, 1 } ;
         look_up[ key(1,9) ] = m19 ;

		 Monsters m110 = { 1, 3, 11, 9, 17, 6, 1 } ;
         look_up[ key(1,10) ] = m110 ;

		 Monsters m111 = { 1, 3, 11, 9, 17, 6, 1 } ;
         look_up[ key(1,11) ] = m111 ;
    }
 
	
    //key k(1,8);
    //cout  << k << '\n' ;
 
    typedef map< key, Monsters >::iterator iterator_t ;
        for( iterator_t iter = look_up.begin() ; iter != look_up.end() ; ++iter ){
            cout << "key: " << iter->first << " => data: " << iter->second << '\n' ;
			cout << iter -> first;
		}


I also wanna be able to do this, but it's not working either.
1
2
3
4
 if( Monsters m11 = { 23, 2, 5, 8, 19, 7, 9 })
Enterbattle();
else
cout << "Error";
> also wanna be able to do this, but it's not working either.
> if( Monsters m11 = { 23, 2, 5, 8, 19, 7, 9 })

I presume you wanted to do this:
if( Monsters m11 == Monsters{ 23, 2, 5, 8, 19, 7, 9 }) // compare two monster objects for equality

To be able to do that, the == operator for comparing two monster objects must be defined. We can do it this way in C++11:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

struct Monsters
{
	public:
		int Damage;
		int PowerUp;
		int Monster_Strength;
		int hp;
		int lvl;
		int money;
		int defense;
};

#include <tuple>

bool operator== ( const Monsters& a, const Monsters& b ) // C++11
{
    static const auto to_tuple = [] ( const Monsters& m )
    {
        return std::make_tuple( m.Damage, m.PowerUp, m.Monster_Strength, m.hp,
                                m.lvl, m.money, m.money, m.defense ) ;
    };
    return to_tuple(a) == to_tuple(b) ;
}

// principle of least surprise
bool operator!= ( const Monsters& a, const Monsters& b ) { return !(a==b) ; }

int main()
{
    Monsters m11 = { 23, 2, 5, 8, 19, 7, 9 } ;
    if( m11 == Monsters{ 23, 2, 5, 8, 19, 7, 9 } ) std::cout << "ok\n" ; // C++11
    if( m11 != Monsters{ 23, 2, 5, -9, 19, 7, 9 } ) std::cout << "ok\n" ; // C++11
}

http://ideone.com/TVLPeD

In C++98, we have to do a bit more; write a constructor for the class Monsters.

For instance (only the first three members of are shown in the snippet):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

struct Monsters
{
    int Damage;
    int PowerUp;
    int Monster_Strength;

    // remaining members elided for brevity

    Monsters( int d, int p, int ms ) : Damage(d), PowerUp(p), Monster_Strength(ms) {}
};

bool operator== ( const Monsters& a, const Monsters& b ) // C++11
{
    return a.Damage == b.Damage && a.PowerUp == b.PowerUp &&
           a.Monster_Strength == b.Monster_Strength ;
}

bool operator!= ( const Monsters& a, const Monsters& b ) { return !(a==b) ; }

int main()
{
    Monsters m11( 23, 2, 5 ) ; // *** note this - () instead of {}
    if( m11 == Monsters( 23, 2, 5 ) ) std::cout << "ok\n" ;
    if( m11 != Monsters( 23, -6, 5 ) ) std::cout << "ok\n" ;
}

http://ideone.com/7ZG1Cp
Last edited on
> If i move it out to my other .cpp file
> thats connected with my header where my monster struct is declared, it stops working.

First read this: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=188

Then, in your header file, declare the map and the overloaded operators:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// MyFunctions.h
#pragma once

struct Monsters
{
	public:
		int Damage;
		int PowerUp;
		int Monster_Strength;
		int hp;
		int lvl;
		int money;
		int defense;
};

typedef pair<int,int> key ; // dungeon_level,moster_level pair


// declarations 

extern map< key, Monsters > look_up ; // note the use of extern 
 
ostream& operator << ( ostream& stm, const key& k ) ;
 
ostream& operator << ( ostream& stm, const Monsters& m ) ;

bool operator== ( const Monsters& a, const Monsters& b ) ;

bool operator!= ( const Monsters& a, const Monsters& b ) ;


And then define them in MyFunctions.cpp
Yes! it worked like a charm! Thank you sooooo much!!
Topic archived. No new replies allowed.