How to output a map from a class with operator overloading

Pages: 1234
1
2
3
4
void IncreaseStackSize(Item& item, int amount)
{
    mContainer[item] = item.IncreaseStackSize(amount);
}


.IncreaseStackSize() returns a void - so can't be used on the RHS of an assignment.

Do you mean:

1
2
3
4
5
6
7
8
9
10
11
static void IncreaseStackSize(Item& item, int amount) {
    item.IncreaseStackSize(amount);
}

static void DecreaseStackSize(Item& item, int amount) {
    item.DecreaseStackSize(amount);
}

static void SetStackSize(Item& item, int amount) {
    item.SetStackSize(amount);
}

Last edited on
and shouldn't L33 of main() be:

 
cout << "DEBUG: RIFLE AMMO RESERVE: " << Rifle.GetCurrentMagazineCount() << "\n\n";


???
Perhaps this for main()

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
	Container PlayerInventory("Player Inventory", 50, 0);

	Item NineMMAmmo("9mm Round", 1, 120, 9999);
	Item FiveFiveSixAmmo("5.56mm Round", 1, 600, 9999);
	Item ShotgunSlugAmmo("Shotgun Slug Round", 1, 50, 9999);

	cout << "5.56mm Ammo Stack Size: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

	Weapon Rifle("Rifle", 4, 1, 1, 30, 9999, 7, FiveFiveSixAmmo.GetCurrentStackSize());
	Weapon Handgun("Handgun", 2, 1, 1, 8, 9999, 8, NineMMAmmo.GetCurrentStackSize());
	Weapon Shotgun("Shotgun", 5, 1, 1, 8, 9999, 8, ShotgunSlugAmmo.GetCurrentStackSize());

	cout << "RIFLE RESERVE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n\n";

	PlayerInventory.AddItem(Rifle);
	PlayerInventory.AddItem(Handgun);
	PlayerInventory.AddItem(Shotgun);

	PlayerInventory.AddItem(ShotgunSlugAmmo);
	PlayerInventory.AddItem(NineMMAmmo);
	PlayerInventory.AddItem(FiveFiveSixAmmo);

	cout << "RIFLE RESERVE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n\n";
	cout << "HANDGUN RESERVE SIZE: " << Handgun.GetCurrentMagazineCount() << "\n\n";
	cout << "SHOTGUN RESERVE SIZE: " << Shotgun.GetCurrentMagazineCount() << "\n\n";

	int choice { 0 };
	int chooseItem { 0 };

	Rifle.Reload(FiveFiveSixAmmo);
	cout << "DEBUG: RIFLE AMMO RESERVE: " << Rifle.GetCurrentMagazineCount() << "\n\n";


which displays:


5.56mm Ammo Stack Size: 600

RIFLE RESERVE SIZE: 7

RIFLE RESERVE SIZE: 7

HANDGUN RESERVE SIZE: 8

SHOTGUN RESERVE SIZE: 8

DEBUG: STACK SIZE: 600

23

DEBUG: Weapon reloaded

DEBUG: RIFLE AMMO RESERVE: 30

Last edited on
@seeplus Ah yes i fixed the code for the debug stuff just now. as for the IncreaseStackSize, I changed it to this but still not working:

1
2
3
4
void IncreaseStackSize(Item& item, int amount)
{
    mContainer[item] = item.GetCurrentStackSize();
}


EDIT: I saw your edit and made the changes, however the main issue is when you open the inventory, the numbers for the 5.56 rounds do not decrease, they are at 600 to start and 23 are removed to reload the magazine so the number should read 577, im unsure why its not working.
Last edited on
Well when added an extra debug cout after reload:

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
Container PlayerInventory("Player Inventory", 50, 0);

	Item NineMMAmmo("9mm Round", 1, 120, 9999);
	Item FiveFiveSixAmmo("5.56mm Round", 1, 600, 9999);
	Item ShotgunSlugAmmo("Shotgun Slug Round", 1, 50, 9999);

	cout << "5.56mm Ammo Stack Size: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

	Weapon Rifle("Rifle", 4, 1, 1, 30, 9999, 7, FiveFiveSixAmmo.GetCurrentStackSize());
	Weapon Handgun("Handgun", 2, 1, 1, 8, 9999, 8, NineMMAmmo.GetCurrentStackSize());
	Weapon Shotgun("Shotgun", 5, 1, 1, 8, 9999, 8, ShotgunSlugAmmo.GetCurrentStackSize());

	cout << "RIFLE RESERVE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n\n";

	PlayerInventory.AddItem(Rifle);
	PlayerInventory.AddItem(Handgun);
	PlayerInventory.AddItem(Shotgun);

	PlayerInventory.AddItem(ShotgunSlugAmmo);
	PlayerInventory.AddItem(NineMMAmmo);
	PlayerInventory.AddItem(FiveFiveSixAmmo);

	cout << "RIFLE RESERVE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n\n";
	cout << "HANDGUN RESERVE SIZE: " << Handgun.GetCurrentMagazineCount() << "\n\n";
	cout << "SHOTGUN RESERVE SIZE: " << Shotgun.GetCurrentMagazineCount() << "\n\n";

	int choice { 0 };
	int chooseItem { 0 };

	Rifle.Reload(FiveFiveSixAmmo);
	cout << "DEBUG: RIFLE AMMO RESERVE: " << Rifle.GetCurrentMagazineCount() << "\n\n";
	cout << "5.56mm Ammo Stack Size: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";


I get:


5.56mm Ammo Stack Size: 600

RIFLE RESERVE SIZE: 7

RIFLE RESERVE SIZE: 7

HANDGUN RESERVE SIZE: 8

SHOTGUN RESERVE SIZE: 8

DEBUG: STACK SIZE: 600

23

DEBUG: Weapon reloaded

DEBUG: RIFLE AMMO RESERVE: 30

5.56mm Ammo Stack Size: 577


which shows that 600 has been reduced to 577 and Rifle increased from 7 to 30 - which is what I understand is what is expected?
Correct, I was just about to post the same updated code haha, however, if you play the game and choose option 3 to open the inventory, it will show the stack of 5.56mm rounds as still being 600, which is whats confusing me, it should update that code right? i mean its modifying and using the same variable, so im not quite understanding. I believe it may have something to do with the AddItem function in the Container class

Updated main

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
int main()
{
    Container PlayerInventory("Player Inventory", 50, 0);

    Item NineMMAmmo("9mm Round", 1, 120, 9999);
    Item FiveFiveSixAmmo("5.56mm Round", 1, 600, 9999);
    Item ShotgunSlugAmmo("Shotgun Slug Round", 1, 50, 9999);

    cout << "DEBUG 5.56MM AMMO CURRENT STACK SIZE: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

    Weapon Rifle("Rifle", 4, 1, 1, 30, 9999, 7, FiveFiveSixAmmo.GetCurrentStackSize());
    Weapon Handgun("Handgun", 2, 1, 1, 8, 9999, 8, NineMMAmmo.GetCurrentStackSize());
    Weapon Shotgun("Shotgun", 5, 1, 1, 7, 9999, 8, ShotgunSlugAmmo.GetCurrentStackSize());

    cout << "DEBUG: CURRENT RIFLE MAGAZINE COUNT: " << Rifle.GetCurrentMagazineCount() << "\n\n";

    PlayerInventory.AddItem(Rifle);
    PlayerInventory.AddItem(Handgun);
    PlayerInventory.AddItem(Shotgun);

    PlayerInventory.AddItem(ShotgunSlugAmmo);
    PlayerInventory.AddItem(NineMMAmmo);
    PlayerInventory.AddItem(FiveFiveSixAmmo);

    cout << "DEBUG: RIFLE MAGAZINE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n";
    cout << "DEBUG: HANDGUN MAGAZINE SIZE: " << Handgun.GetCurrentMagazineCount() << "\n";
    cout << "DEBUG: SHOTGUN MAGAZINE SIZE: " << Shotgun.GetCurrentMagazineCount() << "\n";

    int choice{ 0 };
    int chooseItem{ 0 };

    Rifle.Reload(FiveFiveSixAmmo);
    cout << "DEBUG: CURRENT RIFLE MAGAZINE COUNT: " << Rifle.GetCurrentMagazineCount() << "\n";
    cout << "DEBUG 5.56MM AMMO CURRENT STACK SIZE: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

    while (choice != 4)
    {
        cout << "===MAIN MENU===\n\n";

        cout << "1) Weapon Testing\n";
        cout << "2) Remove Item\n";
        cout << "3) Show Inventory\n";
        cout << "4) Quit\n";

        cout << ">";
        cin >> choice;
        string name{ "" };

        cout << '\n';

        switch (choice)
        {
            case 1:
                cout << "Which weapon would you like to test?\n\n";

                PlayerInventory.DisplayContents();

                cin >> chooseItem;

                break;

            case 2:
                cout << "Which item would you like to remove?\n\n";

                PlayerInventory.DisplayContents();

                getline(cin, name);

                break;

            case 3:

                PlayerInventory.DisplayContents();

                break;

            case 4:

                cout << "Goodbye!";
                return 0;

                break;

            default:
                cout << "You have made an invalid choice\n\n";
        }
    }
}
Last edited on
does this help? I mapified your small example that you posted for me. BTW your remove erase wouldn't work for me on g++ with strict compiler flags, but nevermind that. Try removing 9, which has multiple copies.

This is probably NOT the way to go. Having arbitrary keys (here, 1-N) is of little value, and in this example, no value at all. The point of a map is to use the keys, and infinitely moreso for unordered map. I wonder if a deque would make you happy? Or a list? The map is fine too, its just a bit weird to not really use the keys, and worse, my remove by data segment searches twice (one you see, and one you don't, as erase by key has to navigate to that key).


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
#include <iostream>
#include <vector>
#include <map>
using std::vector;
using std::cout;
using std::cin;

int main()
{
    //vector<int> vect;
	std::map<int,int> vect;
	int dx{1};

    vect[dx++] = 5;
    vect[dx++] = 3;
    vect[dx++] = 9;
    vect[dx++] = 23;
    vect[dx++] = 40;
	vect[dx++] = 9;
	vect[dx++] = 9;
	vect[dx++] = 42;

    int choice{ 0 };   

    for (auto& i : vect)
    {
        cout << i.first << ") " << i.second << '\n';
    }

    cout << "\nRemove what element?\n\n";

    cout << ">";
    cin >> choice;
	
	//removed by key is too easy, probably not what you want to see:
	/*
	vect.erase(choice);    
	*/
	
	//remove by data.  Note that removal invalidates the iterators, so you have to start over.
	//there is probably a slick way to do this using one of algorithms, but for now
	//ONLY using what <map> provides as if those did not exist, rolling it out by hand:
	bool found1{};
	do
	{
		found1 = false;
		for (auto& i : vect)
		{
			if(i.second == choice)
			{
				vect.erase(i.first);    
				found1 = true;
				break;
			}
		}
	} while(found1);
	
	for (auto& i : vect)
    {
        cout << i.first << " :  " << i.second << '\n';
    }
	
}
Last edited on
The issue is that you have 2 classes - Container and Item which both contain details of the item and the amount. When you change the amount for an Item you don't change the amount stored in Container!
This will display what is expected, but is really a 'kludge' as it uses a set of pointers for Container.

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <utility>
#include <set>

using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::map;
using std::pair;
using std::set;
//using std::iterator;
using std::make_pair;

class Character
{
public:
	Character(const string& name, int health) : mName(name), mHealth(health) {}

	string GetName() const {
		return mName;
	}
	int GetHealth() const {
		return mHealth;
	}

private:
	string mName { "Character Name" };
	int mHealth { 100 };
};

class Item
{
public:
	Item(const string& name, int slotsUsed, int currentStackSize, const int maxStackSize) : mName(name), mSlotsUsed(slotsUsed), mCurrentStackSize(currentStackSize), mMaxStackSize(maxStackSize) {}
	Item() = default;

	string GetName() const {
		return mName;
	}
	int GetCurrentStackSize() const {
		return mCurrentStackSize;
	}
	int GetMaxStackSize() const {
		return mMaxStackSize;
	}
	int GetSlotsUsed() const {
		return mSlotsUsed;
	}

	void IncreaseStackSize(int amount) {
		mCurrentStackSize += amount;
	}

	void DecreaseStackSize(int amount) {
		mCurrentStackSize -= amount;
	}

	void SetStackSize(int amount) {
		mCurrentStackSize = amount;
	}

private:
	string mName { "Weapon Name" };
	int mSlotsUsed { 0 }; //Space taken up in container
	int mCurrentStackSize { 0 };
	const int mMaxStackSize { 0 }; //Max stack size for all items.
};

bool operator< (const Item& lhs, const Item& rhs) {
	return lhs.GetName() < rhs.GetName();
}

std::ostream& operator<< (std::ostream& os, const Item& item) {
	os << item.GetName();
	return os;
}

//Should create a projectile weapon class and a melee weapon class that inherit from Weapon.

class Weapon : public Item
{
public:
	Weapon
	(
		const string& name,
		int size,
		int currentStackSize,
		const int maxStackSize,
		const int magazineMaxSize,
		const int ammoReserveMaxSize,
		int magazine,
		int ammoReserve)
		: Item { name, size, currentStackSize, maxStackSize },
		mMagazineMaxCapacity(magazineMaxSize),
		mMagazine(magazine) {}

	int GetMagazineMaxSize() const {
		return mMagazineMaxCapacity;
	}
	int GetCurrentMagazineCount() const {
		return mMagazine;
	}

//This may need some revision but I believe its working correctly.
	void Reload(Item& item) {
		//ISSUE - Need to figure out how to subtract ammo from reserve. as of right now
		//When checking inventory, the ammo stays the same even though i subtracted some.

		cout << "DEBUG: STACK SIZE: " << item.GetCurrentStackSize() << "\n\n";
		if (item.GetCurrentStackSize() > 0) {
			int ammoNeeded = mMagazineMaxCapacity - mMagazine;
			cout << ammoNeeded << "\n\n";

			if (item.GetCurrentStackSize() >= ammoNeeded) {
				cout << "DEBUG: Weapon reloaded\n\n";
				item.DecreaseStackSize(ammoNeeded);
				mMagazine = mMagazineMaxCapacity;
			} else {
				mMagazine += item.GetCurrentStackSize();
				item.SetStackSize(0);
			}
		} else {
			cout << "You have no ammo left!\n\n";
		}

		//cout << "DEBUG: STACK SIZE: " << item.GetCurrentStackSize() << "\n\n";
	}

	void Fire() {
		//For this we need to make sure the magazine has enough ammo in it to fire first, then if it does
		//allow it to fire, then once the ammo reaches 0, then reload.

		if (mMagazine > 0) {
			mMagazine--;
			cout << mMagazine << " rounds left\n\n";
		} else {
			cout << "Out of ammo, Reload!\n";
		}

	}

private:
	const int mMagazineMaxCapacity { 0 };
	int mMagazine { 0 };
};

class Container
{
public:
	Container(const string& name, int containerSize, int amountStored) : mName(name), mContainerSize(containerSize), mAmountStored(amountStored) {}

	void AddItem(Item& item) {
		if (item.GetCurrentStackSize() <= item.GetMaxStackSize()) {
			if (item.GetSlotsUsed() > mContainerSize) {
				cout << "You do not have enough room in your inventory for " << item.GetName() << "\n\n";
			} else {
				//mContainer.insert(pair<Item*, int>(&item, item.GetCurrentStackSize()));
				mContainer.insert(&item);
			}
		} else if (item.GetCurrentStackSize() > item.GetMaxStackSize()) {
			cout << "Cannot pick up item " << item.GetName() << " as it has exceeded the max stack size...\n";
			//mContainer.insert(pair<Item*, int>(&item, item.GetMaxStackSize()));
			mContainer.insert(&item);
			mContainerSize -= item.GetSlotsUsed();
		}
	}

	void RemoveItem(const Item& item) {
		mContainer.erase((Item*) & item);
	}

	int GetContainerSize() const {
		return mContainerSize;
	}
	int GetAmountStored() const {
		return mAmountStored;
	}

	/*
	static void IncreaseStackSize(Item& item, int amount) {
		item.IncreaseStackSize(amount);
		//mContainer[(Item*) &item] = item.GetCurrentStackSize();
	}

	static void DecreaseStackSize(Item& item, int amount) {
		item.DecreaseStackSize(amount);
		//mContainer[&item] = item.GetCurrentStackSize();
	}

	static void SetStackSize(Item& item, int amount) {
		item.SetStackSize(amount);
		//mContainer[&item] = item.GetCurrentStackSize();
	}
	*/

	void DisplayContents() {
		int enumerate { 1 };

		cout << "Inventory Slots Left: " << mContainerSize << "\n\n";

		if (mContainer.empty()) {
			cout << "Inventory is empty\n\n";
		} else if (mContainer.size() > 0) {
			for (const auto& i : mContainer) {
				cout << enumerate++ << ") " << i->GetName() << " x " << i->GetCurrentStackSize() << "\n";
			}
		}
		cout << '\n';
	}

	int GetSize() const {
		return mContainer.size();
	}

private:
	string mName { "Container Name" };
	int mContainerSize { 0 };
	int mAmountStored { 0 };
	//map<Item*, int> mContainer;
	set<Item*> mContainer;
};


which outputs:


DEBUG 5.56MM AMMO CURRENT STACK SIZE: 600

DEBUG: CURRENT RIFLE MAGAZINE COUNT: 7

DEBUG: RIFLE MAGAZINE SIZE: 7
DEBUG: HANDGUN MAGAZINE SIZE: 8
DEBUG: SHOTGUN MAGAZINE SIZE: 8
DEBUG: STACK SIZE: 600

23

DEBUG: Weapon reloaded

DEBUG: CURRENT RIFLE MAGAZINE COUNT: 30
DEBUG 5.56MM AMMO CURRENT STACK SIZE: 577

===MAIN MENU===

1) Weapon Testing
2) Remove Item
3) Show Inventory
4) Quit
>3

Inventory Slots Left: 50

1) 5.56mm Round x 577
2) 9mm Round x 120
3) Rifle x 1
4) Shotgun x 1
5) Handgun x 1
6) Shotgun Slug Round x 50


But a redesign is probably required.
As a 'quick' first change, consider:

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <utility>
#include <set>

using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::map;
using std::pair;
using std::set;
//using std::iterator;
using std::make_pair;

class Character
{
public:
	Character(const string& name, int health) : mName(name), mHealth(health) {}

	string GetName() const {
		return mName;
	}

	int GetHealth() const {
		return mHealth;
	}

private:
	string mName { "Character Name" };
	int mHealth { 100 };
};

class Item
{
public:
	Item(const string& name, int slotsUsed, int currentStackSize, const int maxStackSize) : mName(name), mSlotsUsed(slotsUsed), mCurrentStackSize(currentStackSize), mMaxStackSize(maxStackSize) {}
	Item() = default;

	virtual void Reload(Item&) {
		std::cout << "Cannot reload\n";
	}

	virtual int GetCurrentMagazineCount() const {
		return -1;
	}

	string GetName() const {
		return mName;
	}

	int GetCurrentStackSize() const {
		return mCurrentStackSize;
	}

	int GetMaxStackSize() const {
		return mMaxStackSize;
	}

	int GetSlotsUsed() const {
		return mSlotsUsed;
	}

	void IncreaseStackSize(int amount) {
		mCurrentStackSize += amount;
	}

	void DecreaseStackSize(int amount) {
		mCurrentStackSize -= amount;
	}

	void SetStackSize(int amount) {
		mCurrentStackSize = amount;
	}

private:
	string mName { "Weapon Name" };
	int mSlotsUsed { 0 }; //Space taken up in container
	int mCurrentStackSize { 0 };
	const int mMaxStackSize { 0 }; //Max stack size for all items.
};

bool operator< (const Item& lhs, const Item& rhs) {
	return lhs.GetName() < rhs.GetName();
}

std::ostream& operator<< (std::ostream& os, const Item& item) {
	os << item.GetName();
	return os;
}

//Should create a projectile weapon class and a melee weapon class that inherit from Weapon.

class Weapon : public Item
{
public:
	Weapon
	(
		const string& name,
		int size,
		int currentStackSize,
		const int maxStackSize,
		const int magazineMaxSize,
		const int ammoReserveMaxSize,
		int magazine,
		int ammoReserve)
		: Item { name, size, currentStackSize, maxStackSize },
		mMagazineMaxCapacity(magazineMaxSize),
		mMagazine(magazine) {}

	int GetMagazineMaxSize() const {
		return mMagazineMaxCapacity;
	}

	int GetCurrentMagazineCount() const override {
		return mMagazine;
	}

//This may need some revision but I believe its working correctly.
	void Reload(Item& item) override {
		cout << "DEBUG: STACK SIZE: " << item.GetCurrentStackSize() << "\n\n";

		if (item.GetCurrentStackSize() > 0) {
			int ammoNeeded = mMagazineMaxCapacity - mMagazine;

			cout << ammoNeeded << "\n\n";

			if (item.GetCurrentStackSize() >= ammoNeeded) {
				cout << "DEBUG: Weapon reloaded\n\n";
				item.DecreaseStackSize(ammoNeeded);
				mMagazine = mMagazineMaxCapacity;
			} else {
				mMagazine += item.GetCurrentStackSize();
				item.SetStackSize(0);
			}
		} else {
			cout << "You have no ammo left!\n\n";
		}
	}

	void Fire() {
		//For this we need to make sure the magazine has enough ammo in it to fire first, then if it does
		//allow it to fire, then once the ammo reaches 0, then reload.

		if (mMagazine > 0) {
			mMagazine--;
			cout << mMagazine << " rounds left\n\n";
		} else {
			cout << "Out of ammo, Reload!\n";
		}

	}

private:
	const int mMagazineMaxCapacity { 0 };
	int mMagazine { 0 };
};

class Container
{
public:
	Container(const string& name, int containerSize, int amountStored) : mName(name), mContainerSize(containerSize), mAmountStored(amountStored) {}

	void AddItem(Item& item) {
		if (item.GetCurrentStackSize() <= item.GetMaxStackSize()) {
			if (item.GetSlotsUsed() > mContainerSize) {
				cout << "You do not have enough room in your inventory for " << item.GetName() << "\n\n";
			} else {
				mContainer.insert(&item);
			}
		} else {
			cout << "Cannot pick up item " << item.GetName() << " as it has exceeded the max stack size...\n";
			mContainer.insert(&item);
			mContainerSize -= item.GetSlotsUsed();
		}
	}

	void RemoveItem(const Item& item) {
		mContainer.erase((Item*) & item);
	}

	int GetContainerSize() const {
		return mContainerSize;
	}

	int GetAmountStored() const {
		return mAmountStored;
	}

	Item* GetItem(const string& name) const {
		for (const auto& i : mContainer)
			if (i->GetName() == name)
				return i;

		return {};
	}

	void DisplayContents() {
		int enumerate { 1 };

		cout << "Inventory Slots Left: " << mContainerSize << "\n\n";

		if (mContainer.empty()) {
			cout << "Inventory is empty\n\n";
		} else if (mContainer.size() > 0) {
			for (const auto& i : mContainer) {
				cout << enumerate++ << ") " << i->GetName() << " x " << i->GetCurrentStackSize();

				if (const auto mag { i->GetCurrentMagazineCount() }; mag >= 0)
					std::cout << " (magazine count: " << mag << ')';

				std::cout << '\n';
			}
		}
		cout << '\n';
	}

	int GetSize() const {
		return mContainer.size();
	}

private:
	string mName { "Container Name" };
	int mContainerSize { 0 };
	int mAmountStored { 0 };
	set<Item*> mContainer;
};

int main() {
	Container PlayerInventory("Player Inventory", 50, 0);

	Item NineMMAmmo("9mm Round", 1, 120, 9999);
	Item FiveFiveSixAmmo("5.56mm Round", 1, 600, 9999);
	Item ShotgunSlugAmmo("Shotgun Slug Round", 1, 50, 9999);

	cout << "DEBUG 5.56MM AMMO CURRENT STACK SIZE: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

	Weapon Rifle("Rifle", 4, 1, 1, 30, 9999, 7, FiveFiveSixAmmo.GetCurrentStackSize());
	Weapon Handgun("Handgun", 2, 1, 1, 8, 9999, 8, NineMMAmmo.GetCurrentStackSize());
	Weapon Shotgun("Shotgun", 5, 1, 1, 7, 9999, 8, ShotgunSlugAmmo.GetCurrentStackSize());

	cout << "DEBUG: CURRENT RIFLE MAGAZINE COUNT: " << Rifle.GetCurrentMagazineCount() << "\n\n";

	PlayerInventory.AddItem(Rifle);
	PlayerInventory.AddItem(Handgun);
	PlayerInventory.AddItem(Shotgun);

	PlayerInventory.AddItem(ShotgunSlugAmmo);
	PlayerInventory.AddItem(NineMMAmmo);
	PlayerInventory.AddItem(FiveFiveSixAmmo);

	cout << "DEBUG: RIFLE MAGAZINE SIZE: " << Rifle.GetCurrentMagazineCount() << "\n";
	cout << "DEBUG: HANDGUN MAGAZINE SIZE: " << Handgun.GetCurrentMagazineCount() << "\n";
	cout << "DEBUG: SHOTGUN MAGAZINE SIZE: " << Shotgun.GetCurrentMagazineCount() << "\n";

	int choice { 0 };
	int chooseItem { 0 };

	PlayerInventory.GetItem("Rifle")->Reload(FiveFiveSixAmmo);

	cout << "DEBUG: CURRENT RIFLE MAGAZINE COUNT: " << Rifle.GetCurrentMagazineCount() << "\n";
	cout << "DEBUG 5.56MM AMMO CURRENT STACK SIZE: " << FiveFiveSixAmmo.GetCurrentStackSize() << "\n\n";

	while (choice != 4) {
		cout << "===MAIN MENU===\n\n";

		cout << "1) Weapon Testing\n";
		cout << "2) Remove Item\n";
		cout << "3) Show Inventory\n";
		cout << "4) Quit\n";

		cout << ">";
		cin >> choice;
		string name { "" };

		cout << '\n';

		switch (choice) {
			case 1:
				cout << "Which weapon would you like to test?\n\n";

				PlayerInventory.DisplayContents();

				cin >> chooseItem;

				break;

			case 2:
				cout << "Which item would you like to remove?\n\n";

				PlayerInventory.DisplayContents();

				getline(cin, name);

				break;

			case 3:

				PlayerInventory.DisplayContents();

				break;

			case 4:

				cout << "Goodbye!";
				return 0;

				break;

			default:
				cout << "You have made an invalid choice\n\n";
		}
	}
}

Last edited on

DEBUG 5.56MM AMMO CURRENT STACK SIZE: 600

DEBUG: CURRENT RIFLE MAGAZINE COUNT: 7

DEBUG: RIFLE MAGAZINE SIZE: 7
DEBUG: HANDGUN MAGAZINE SIZE: 8
DEBUG: SHOTGUN MAGAZINE SIZE: 8
DEBUG: STACK SIZE: 600

23

DEBUG: Weapon reloaded

DEBUG: CURRENT RIFLE MAGAZINE COUNT: 30
DEBUG 5.56MM AMMO CURRENT STACK SIZE: 577

===MAIN MENU===

1) Weapon Testing
2) Remove Item
3) Show Inventory
4) Quit
>3

Inventory Slots Left: 50

1) Rifle x 1 (magazine count: 30)
2) Shotgun x 1 (magazine count: 8)
3) Handgun x 1 (magazine count: 8)
4) 5.56mm Round x 577
5) Shotgun Slug Round x 50
6) 9mm Round x 120


Where changes are made through Container.

Also, shouldn't weapon know which ammunition it takes? So instead of the weapon constructor taking ammunition count, it takes an ammunition item.
Last edited on
Hmm, ok thank you for the help. I think i may just re write it, Id like to do it without having to do a kludgey kind of way.

Also, shouldn't weapon know which ammunition it takes? So instead of the weapon constructor taking ammunition count, it takes an ammunition item.


I honestly didnt even think of that, but I will keep it in mind for the next time i write it. I think i will erase everything and write it again. As for the constructor taking an ammunition item, how would that look?

Once my code gets to this size it gets hard for me to keep track of stuff and its harder for me to make things work properly.
yes, the bigger things get, the more design and care you need. No offense but a raw coder in the first class can write 1 page assignment with no real troubles :)

the classroom tries to tell you things but a lot of these ideas don't make sense until you DO try a bigger program.

would look roughly like
ammo mak_9x18; //make some specific ammo
item makarov{mak_9x18}; //gun uses specific ammo type

where the weapon constructor is
item(ammo &a)//etc
and the default constructor can set it to 9mm or some invalid value.

its just like the above
Item ShotgunSlugAmmo("Shotgun Slug Round", 1, 50, 9999);
except the ammo details would be passed in an ammo object instead of by each value.

note that many weapons accept more than one ammo, for example 38/357/9mm are the same bullet and all work in some revolver, and nato 556 is 223, and so on, and there are 5 or 6 different 9mms (the standard glock etc use 9x19). 45 and 410 shotgun are another example.

Last edited on
Ok, so im going to try to either re write or modify this program and come back at some later time and HOPEFULLY i'll have a better program. I think its actually a good idea to keep rewriting this until its coded properly. I mean im not trying to get a job in programming or anything, i just want to learn enough to be able to code a 2D game in SFML without running into too many snags.
Ok so im re-writing the program and i already think im doing something wrong here. So i did what was suggested and added item to the constructor if weapon, but instead of outputting the weapon name it outputs the ammo name. I think I know why it does that, its because i added the Item to the constructor of the weapon class. and i made it so only Items can be added to the vector, however weapons are technically items themselves and im now confused as to how to proceed.

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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <utility>

using std::string;
using std::vector;
using std::cout;
using std::cin;
using std::map;
using std::pair;
using std::iterator;
using std::make_pair;

class Character
{
    public:
        Character
        (
            const string& name, 
            int health
        ): 
            mName(name), 
            mHealth(health)
        {}

    private:
        string mName{ "Character Name" };
        int mHealth{ 100 };
};

class Item
{
    public:
        Item
        (
            const string& name,
            int stackSize,
            int maxStackSize
        ): 
            mName(name)
        {}

        Item() = default;

        string GetName() const { return mName; }

    private:
        string mName{ "Item Name" };
        int mStackSize{ 0 };
        const int mMaxStackSize{ 0 };
};


class Weapon : public Item
{
    public:
        Weapon
        (
            const string& name, 
            int damage,
            Item& ammo
        ):  
            Item{ ammo },
            mName(name), 
            mDamage(damage)
        {}

        string GetName() const { return mName; }
        int GetDamage() const { return mDamage; }

    private:
        string mName{ "Weapon Name" };
        int mDamage{ 0 };
};

class Container
{
    public:
        Container
        (
            const string& name,
            int storageSlots,
            const int maxStorageSlots
        ): 
            mName(name), 
            mStorageSlots(storageSlots),
            mMaxStorageSlots(maxStorageSlots)
        {}

        string GetName() const { return mName; }
        int GetStorageSlots() const { return mStorageSlots; }
        int GetMaxStorageSlots() const { return mMaxStorageSlots; }

        void Insert(Item& item)
        {
            mContainer.push_back(item);
        }

        void Remove(Item& item)
        {

        }

        void Open()
        {
            for (auto& i : mContainer)
            {
                cout << i.GetName() << '\n';
            }
        }

    private:
        string mName{ "Container Name" };
        int mStorageSlots{ 0 };
        const int mMaxStorageSlots{ 0 };
        vector<Item> mContainer;
};

int main()
{
    Item Ammo9MM("9mm Round", 50, 9999);
    Item Ammo556("5.56mm Round", 600, 9999);

    Weapon Glock17("Glock 17", 34, Ammo9MM);
    Weapon G36("G36", 70, Ammo556);

    Container PlayerInventory("Inventory", 30, 100);

    PlayerInventory.Insert(Glock17);
    PlayerInventory.Insert(G36);

    PlayerInventory.Open();
}


output

9mm Round
5.56mm Round
Last edited on
It looks like you didn't get the gist of inheritance right. In Item you have member mName and in Weapon too. Which one to take?

What you do with Weapon is that you add mDamage. That's it. So it looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Weapon : public Item
{
    public:
        Weapon
        (
            const string& name, 
            int damage,
            const Item& ammo
        ):  
            Item{ ammo },
            mName(name), 
            mDamage(damage)
        {}

        string GetName() const { return mName; }
        int GetDamage() const { return mDamage; }

    private:
        string mName{ "Weapon Name" };
        int mDamage{ 0 };
};
Plus you should add a virtual destructor for the base class Item:

https://www.tutorialspoint.com/virtual-destructor-in-cplusplus
https://www.learncpp.com/cpp-tutorial/virtual-destructors-virtual-assignment-and-overriding-virtualization/

What you are trying to do on line 126 is something different. It is called composition. In that case you need to add an Item member within you Weapon class.
Wow pretty interesting discussion!
I'd like to suggest that you should start on some Win32 courses if you want to design a 2D game (3D is also similar):
https://docs.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows
https://docs.microsoft.com/en-us/windows/uwp/gaming/tutorial--setting-up-the-games-infrastructure
Still it's important to get some general knowledge about C++ classes, Which isn't hard but requires time to understand. I've got no free English course URLs on that, but surely they're all over the Internet.
Another suggestion is that you can learn some algorithms and data structures which provide you stronger abilities on solving tasks like managing game objects and containers. In your case, it's obvious that map's of little use, whereas vector or deque would certainly be better.
I did what you're doing before, and although I'm not doing any jobs relating to programming, I believe these tasks are fundemental requirements to imporve your logical programming skills.
If you have any question, please PM or just put it on this thread. I'll reply soon.
Last edited on
To write something of real use, map is designed for a set of objects which requires fast query on keys (O(logn)) but slower on values (O(n)). Vector is designed to store things quickly (O(1) vs map's O(logn)) but takes lots of time to query an object (O(n) vs map's O(logn)), their speeds are all dependent on how their storage are made. So, in your case, since there's no use of the key-query of map, and no insertion, random deletion or auto-sorting, a vector would be best.
I think its actually a good idea to keep rewriting this until its coded properly


Part of the issue is that you're doing 'design by code' as opposed to 'design before code'. You seem to 'have an idea' and then start coding from it. Get into a 'mess' and then try to either change the code or do a re-write. I'd suggest that you first get the OO class's design first. Once you have a 'workable' design then you start coding. Code in small 'chunks' and compile and test frequently. Don't start more coding until you're got working what you're coded so far. If when coding you still run into a problem (it happens!), then take a step back and re-visit the design to see why you're having the problem. Don't be tempted to just 'change the class(s)' to suit the coding 'on the hoof'. Writing a program like this for the first time is probably the most complex program written.

How far through learning C++ have you got? Have you covered polymorphism and Abstract Class and virtual functions? As a first 'simple' design, I'd have Item as an abstract class with say Weapon class and Bullet class derived from it. Weapon class could also have a ref to the appropriate Bullet class.

Character could then have a vector of Item detailing what each character has. You probably don't need the Container class as these functions (eg Display) would be a function of Character (eg displayItems() ).

But as you design the game and start to specify required class member functions (eg Weapon reload etc) then you'll start to see what data needs to be held. Don't store the same data in more than 1 place. If you start to, then the design is probably wrong. Common data (such as a name) is stored in the base class with only derived class specific data stored in the derived classes.

Just learning a programming language is one part of programming. Program design is also extremely important - the more so the more 'complicated' the program. This area nowadays IMO seems not to have the emphasis it used to when programming is taught.

How are you learning C++? Is this the first computer language or have you used others before?

For OO design, UML (Unified Modelling Language) is often used. For an introduction to UML I suggest 'Applying UML and Patterns - An introduction to Object-Oriented Analysis and Design and Interactive Development' by Craig Larman
https://www.amazon.co.uk/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=tmm_hrd_swatch_0
(check out a used version for a cheap price!)

There is also the 'infamous' book 'Design Patterns' by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides (known as the 'Gang Of 4' [GoF] book). Which IMO is a 'must read' - although the C++ examples are now somewhat out-of-date.
https://www.amazon.co.uk/Design-patterns-elements-reusable-object-oriented/dp/0201633612/ref=sr_1_1

Have fun!
Last edited on
art of the issue is that you're doing 'design by code' as opposed to 'design before code'. You seem to 'have an idea' and then start coding from it. Get into a 'mess' and then try to either change the code or do a re-write.


Yeah thats exactly what I do haha, id like to plan it out, but most of the time im not creating anything serious im just programming just for fun.

How far through learning C++ have you got? Have you covered polymorphism and Abstract Class and virtual functions?


I kind of jump around learning stuff, my knowledge is kinda all over in some spots, and when i hit a roadblock i usually dont code for months on end then come back to it and forget what i learned. I used to know how to do inheritance and polymorphism, I spent some time learning it, then didnt program for almost 7 months and forgot most of it.


How are you learning C++? Is this the first computer language or have you used others before?


Yeah C++ is my first computer language. I dabbled in Lua, Ruby, C# and Java a little bit but not long at all, i dont remember how to program in any of those or even the syntax for them. I learn mostly by just watching youtube, thats how I first learned.

These are the actual videos I watched when i first started.

https://www.youtube.com/watch?v=tvC1WCdV1XU&list=PLAE85DE8440AA6B83

I then bought some courses on Udemy, and I have 6 C++ programming books recommended by people on here, although i haven't read through them yet.

I have experience in planning out designs using design documents, I do that a lot for game ideas, i write big design documents that plan out all aspects of the game, and I could do the same for programming if i had the right tools. Whats a good UML program that I can use?

It's been years since I started learning and I really want to become proficient at it, and I really want to achieve my goal of making a game. It's been so long and the fact that I'm still struggling with the basics is disheartening.
Last edited on
Pages: 1234