-
Which container to do what I need?
Sorry for this long post but I don't know how to explain it in a shorter form.
What container allows fast finding of a specific item -and- also allows scanning by using iterators that can be incremented in a "for" loop? My data:
Code:
Number of players: 4
BetInfo for each player:
---------------------------
Passline: betAmount, coordX, coordY
No Pass : betAmount, coordX, coordy
Field : betAmount, coordX, coordY
Place4 : betAmount, coordX, coordY
Place5 : betAmount, coordX, coordY
--- continues for about 50 different bets ---
QUESTION 1:
When dice is rolled, the diceSum dictates which bet amount I need to access. For instance, if the diceSum is a 2 on the first roll, the Passline bet loses for all 4 players so I need to access the Passline betAmount for each player to see of a bet was made (betAmount > 0). Then handle it.
(Player1 > Passline > betAmount), then
(Player2 > Passline > betAmount), then
(Player3 > Passline > betAmount), then
(Player4 > Passline > betAmount)
Which container will provide fast access to the betAmount for each player? Note that I have to do also do this for other bets like NoPass bets, Field bets, oneRoll2 bets, anyCrap bets, Horn bets and World bets to pay each player.
----------
QUESTION 2:
When a shooter 7's out, I need to pay some bets then zero all bets on the table for all 4 players. When I zero all bets on the table for 4 players, I would like to do it using iterators like in a "for" loop. So the container needs to be able to do this also. Which container can do #1 above and #2?
----------
Hope my explanation is clear enough. I think I need to use a 3 dimensional array to hold all of the BetInfo.
50 rows will be for each bet. (approximate)
3 columns will be for betAmount, coordX, coordY.
4 layers will be for the 4 players.
Code:
enum {Passline, NoPass, Field, Place4, Place5, ...etc.}; (bet-name)
enum {BetAmount, CoordX, CoordY}; (bet-data)
enum {Player1, Player2, Player3, Player4}; (player-number)
int betInfo[bet-name][bet-data][player-number]
But is there a better container to use to hold all of the betInfo, yet do what I need?
Thanks,
Raptor
-
Re: Which container to do what I need?
almost all containers allow you to iterate over the items. So this is probably a moot requirement. What cannot always be guaranteed is specific ordering or indexed access.
"Fast finding" would mean you need a std::map or something like this.
If iterating (statistically over half the items) in the container is enough speed to qualify for "fast finding", then any container will do. and you can use the std::find() algorithm to do the searching.
-
Re: Which container to do what I need?
Quote:
Originally Posted by
OReubens
"Fast finding" would mean you need a std::map or something like this.
I can envision using a std::map for one player. In that case, the key could be the bet name like "Passline", "NoPass", "Field", etc. The mapped value could be a pointer to a struct which contains the "betAmount", "coordX" and "coordY" integer values.
How would I set up the map for 4 players where I can iterate through the 4 players in a loop?
Thanks,
Raptor (coding my first C++ program)
-
Re: Which container to do what I need?
Try forgetting that pointers exists when using STL containers. The containers are capable of handling new/delete for you so you neither have to worry about memory leaks nor invalid pointers. In this case declaring your map as
Code:
#include <map>
std::map< 'key', 'Some struct' > betInfo;
would probably meet what you need.
See http://cplusplus.com/reference/stl/map/
-
Re: Which container to do what I need?
Quote:
Originally Posted by
raptor88
The mapped value could be a pointer to a struct which contains the "betAmount", "coordX" and "coordY" integer values.
As S_M_A stated, you should be striving to use either value semantics (no pointers), or if pointers are needed, smart pointers.
Code:
#include <map>
#include <string>
#include <iostream>
struct SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
};
typedef std::map<std::string, SomeStruct> StringToStructMap;
using namespace std;
int main()
{
StringToStructMap sMap;
sMap.insert(make_pair("Joe", SomeStruct()));
sMap.insert(make_pair("Bob", SomeStruct(1,2,3)));
sMap.insert(make_pair("Sam", SomeStruct(4,5,6)));
StringToStructMap::iterator it = sMap.begin();
while (it != sMap.end() )
{
cout << it->first << " -> (" << it->second.x << "," << it->second.y << "," << it->second.z << ")\n";
++it;
}
}
There is no pointer usage in the code above.
Regards,
Paul McKenzie
-
Re: Which container to do what I need?
Quote:
Originally Posted by
S_M_A
Try forgetting that pointers exists when using STL containers. The containers are capable of handling new/delete for you so you neither have to worry about memory leaks nor invalid pointers. In this case declaring your map as
Code:
#include <map>
std::map< 'key', 'Some struct' > betInfo;
would probably meet what you need.
See
http://cplusplus.com/reference/stl/map/
Thanks much for your help,
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
As S_M_A stated, you should be striving to use either value semantics (no pointers), or if pointers are needed, smart pointers.
Code:
#include <map>
#include <string>
#include <iostream>
struct SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
};
typedef std::map<std::string, SomeStruct> StringToStructMap;
using namespace std;
int main()
{
StringToStructMap sMap;
sMap.insert(make_pair("Joe", SomeStruct()));
sMap.insert(make_pair("Bob", SomeStruct(1,2,3)));
sMap.insert(make_pair("Sam", SomeStruct(4,5,6)));
StringToStructMap::iterator it = sMap.begin();
while (it != sMap.end() )
{
cout << it->first << " -> (" << it->second.x << "," << it->second.y << "." << it->second.z << ")\n";
++it;
}
}
There is no pointer usage in the code above.
Regards,
Paul McKenzie
That is really helpful Paul. I'll try to figure out how to use that for 4 players. Maybe an array to hold the maps.
Thanks!
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
struct SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
};
typedef std::map<std::string, SomeStruct> StringToStructMap;
using namespace std;
int main()
{
StringToStructMap sMap;
sMap.insert(make_pair("Joe", SomeStruct()));
sMap.insert(make_pair("Bob", SomeStruct(1,2,3)));
sMap.insert(make_pair("Sam", SomeStruct(4,5,6)));
Hi Paul,
Going over your code, that's an extremely clever method of setting up the structure so it can be initialized in the format you show in main. I Googled for over 2 hours and could never find an explanation or even an example to match your method. Could I burden you to explain it to me (and other lurkers)?
How does this statement work?
Code:
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
1. Why does nesting SomeStruct (the same name) in SomeStruct make it work?
2. I learned that the single colon signifies the start of an initialization list. But why does x(xVal) work instead of x=xVal? IOW, how did you figure out to put the xVal in parenthesis?
3. How did you figure out that the {} is needed at the end of the statement without a semicolon';' ?
If you know of a link that explains it, please post it.
Your code is better than most books,
Raptor
-
Re: Which container to do what I need?
Paul's code is great, but you also aren't looking at the right books.
-
Re: Which container to do what I need?
Quote:
Originally Posted by
raptor88
How does this statement work?
Code:
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
1. Why does nesting SomeStruct (the same name) in SomeStruct make it work?
That is a constructor. Yes, even structs can have constructors.
Quote:
2. I learned that the single colon signifies the start of an initialization list. But why does x(xVal) work instead of x=xVal? IOW, how did you figure out to put the xVal in parenthesis?
Since the call is a constructor, all you need to do is to look up how to write constructors that initialize member variables in the initialization list.
Quote:
3. How did you figure out that the {} is needed at the end of the statement without a semicolon';' ?
The entire constructor function body is inlined into the struct. That is just an empty function block, no different than doing this:
Code:
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal)
{
// a do nothing constructor body
}
Quote:
If you know of a link that explains it, please post it.
Well, as ahoodin pointed out, that "link" is a C++ book or good tutorial on the C++ language. Nothing that I wrote is out of the ordinary, i.e. every C++ vetaran that responds to you on this board will understand that code right away.
Regards,
Paul McKenzie
-
Re: Which container to do what I need?
Quote:
Originally Posted by
ahoodin
Paul's code is great, but you also aren't looking at the right books.
OK, am more than willing to buy another C++ book. Please tell me the name of a book that explains what Paul did with his constructor statement within a struct. None of my 6 or 7 C++ books nor hours of Googling even mention doing anything like that, let alone how to do it.
EDIT: No need for another book info. I understand Paul's code pretty well now.
Thanks,
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
That is a constructor. Yes, even structs can have constructors.
Since the call is a constructor, all you need to do is to look up how to write constructors that initialize member variables in the initialization list.
The entire constructor function body is inlined into the struct. That is just an empty function block, no different than doing this:
Code:
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal)
{
// a do nothing constructor body
}
Well, as ahoodin pointed out, that "link" is a C++ book or good tutorial on the C++ language. Nothing that I wrote is out of the ordinary, i.e. every C++ vetaran that responds to you on this board will understand that code right away.
Regards,
Paul McKenzie
Hi Paul,
Thank you very much for taking the time to explain your code. Who would have guessed that even structs can have constructors. C++ books and web tutorials are so simplistic that they "all" cover the same "simple" ways of doing things. Not even over 2 hours of web searching even comes close to using or explaining code like yours. At least now your code and explanations are on the web and others Googling in the future might find it. Using your explanations, I think I can now continue research and figure out the rest.
EDIT: OK, now after reflecting on what you said, I realize now that the theory is that structs are like classes except they are always public. Looking at it in that light as a constructor function (same name as the "class" name, in this case the struct name) with an initialization list, it makes a lot more sense.
Thanks much!
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by
raptor88
EDIT: OK, now after reflecting on what you said, I realize now that the theory is that structs are like classes except they are always public. Looking at it in that light as a constructor function (same name as the "class" name, in this case the struct name) with an initialization list, it makes a lot more sense.
No, the difference is that in structs the members are public by default but for classes the members are private by default. I.e. in this case:
Code:
struct SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
};
the members are all public, but in this case:
Code:
class SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0) : x(xVal), y(yVal), z(zVal) {}
};
the members are all private (which obviously in this case would mean you couldn't make any instances of this class :)). You can of course use public, private and protected access specifiers in either structs or classes to explicitly determine the access rights.
Incidentally, the first search result I get for "c++ constructor" in google is this: http://www.cplusplus.com/doc/tutorial/classes/ , which explains all this and more.
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Peter_B
No, the difference is that in structs the members are public by default but for classes the members are private by default.
Yes, I did realize that but failed to say that "structs are like classes except they are always public by default". Thanks for clarifying it just in case I didn't realize it.
Yes, once one realizes that the statement is a constructor, searching becomes productive. My problem was that I had no clue it was a constructor being a wet behind the ears beginning C++ learner. I had realized that the statement was to allow initializing the struct later in the body, so all of my Googling had been for "C++ struct initialization" which turned up nothing like Paul's code.
I do appreciate your taking the time to help out :),
Raptor
-
Re: Which container to do what I need?
For other beginning C++ learners, here's a substitute for Paul's struct code. Tested and it works identically.
Code:
// The following code is equivalent to Paul's struct code and it works identically.
struct SomeStruct
{
int x;
int y;
int z;
SomeStruct(int xVal=0, int yVal=0, int zVal=0)
{
x = xVal;
y = yVal;
z = zVal;
}
};
Hope this helps other newbies like me with understanding his code,
Raptor
-
Re: Which container to do what I need?
Both yes and no. The code you show produce the same result as Paul's but it cause the created object first to be default initialized and then assigned new values in the constructor body.
-
Re: Which container to do what I need?
Quote:
Originally Posted by
S_M_A
Both yes and no. The code you show produce the same result as Paul's but it cause the created object first to be default initialized and then assigned new values in the constructor body.
Guess I need to do more research since I really don't understand why the code I showed works different from Pauls. Thanks for pointing that out.
-
Re: Which container to do what I need?
Quote:
Originally Posted by
raptor88
Guess I need to do more research since I really don't understand why the code I showed works different from Pauls. Thanks for pointing that out.
There is a difference. The code I showed you initializes the member variables, i.e. as soon as the members of the struct are created, those members are initialized to a value. Note that this occurs outside (before) the constructor body, emphasizing the fact that those members have initial values before the constructor body is invoked.
Your version doesn't give the members any values until the constructor body is invoked. You can see the difference if you place a breakpoint on the first line of the constructor. You will see that those members have values with my method, while with your method those variables have undefined or junk values.
Even though initialization list isn't required in this scenario, in other scenarios you are required to use the initialization list. For example, if the struct or class has members that cannot be default-constructed, or if the struct is derived from a struct/class that cannot be default constructed, you're required to use an init-list.
Code:
class A
{
public:
A(int x);
};
class B : public A
{
B() { } // error
};
The fix:
Code:
class A
{
public:
A(int x);
};
class B : public A
{
B() : A(0) { } // ok now
};
Regards,
Paul McKenzie
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
There is a difference.
... snip ...
Thanks for clearing that up Paul. Learned a lot from this thread. I did plan to only use your method in the future since it's easier to type but now I know it also works better.
Thanks,
Raptor
-
Re: Which container to do what I need?
Is this the correct way to use Paul's code of the map of structs in an array for 4 players?
Code:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <map>
using namespace std;
struct BetInfo
{
int betTotal; // Total amount of a particular bet on the table.
int coordX; // Horz coordinate of where to draw the chips for that bet.
int coordY; // Vert coordinate of where to draw the chips for that bet.
BetInfo(int xVal=0, int yVal=0, int zVal=0) : betTotal(xVal), coordX(yVal), coordY(zVal) {}
};
map<string, BetInfo> betInfoMap[4]; // Put before tmain to make instance of betInfoMap global.
enum {player1, player2, player3, player4}; // Set player1 = 0, player2 = 1, etc.
int _tmain(int argc, _TCHAR* argv[])
{
// Note that each time "insert(make_pair" is called, it creates a new struct in betInfoMap.
// In that process the inline constructor is called which initializes the struct values.
betInfoMap[player1].insert(make_pair("PassLine", BetInfo(0, 1, 2)));
betInfoMap[player1].insert(make_pair("PassBkup", BetInfo(0, 3, 4)));
betInfoMap[player1].insert(make_pair("NoPass", BetInfo(0, 5, 6)));
betInfoMap[player1].insert(make_pair("NoPassBkup", BetInfo(0, 7, 8)));
betInfoMap[player2].insert(make_pair("PassLine", BetInfo(0, 9, 10)));
betInfoMap[player2].insert(make_pair("PassBkup", BetInfo(0, 11, 12)));
betInfoMap[player2].insert(make_pair("NoPass", BetInfo(0, 13, 14)));
betInfoMap[player2].insert(make_pair("NoPassBkup", BetInfo(0, 15, 16)));
betInfoMap[player3].insert(make_pair("PassLine", BetInfo(0, 17, 18)));
betInfoMap[player3].insert(make_pair("PassBkup", BetInfo(0, 19, 20)));
betInfoMap[player3].insert(make_pair("NoPass", BetInfo(0, 21, 22)));
betInfoMap[player3].insert(make_pair("NoPassBkup", BetInfo(0, 23, 24)));
betInfoMap[player4].insert(make_pair("PassLine", BetInfo(0, 25, 26)));
betInfoMap[player4].insert(make_pair("PassBkup", BetInfo(0, 27, 28)));
betInfoMap[player4].insert(make_pair("NoPass", BetInfo(0, 29, 30)));
betInfoMap[player4].insert(make_pair("NoPassBkup", BetInfo(0, 31, 32)));
// Print the map key and associated struct values for all players (1-4) on the console.
for (int playerNbr=0; playerNbr < 4; playerNbr++)
{
cout << "\nPlayer Number = " << playerNbr+1 << endl;
map<string, BetInfo>::iterator it = betInfoMap[playerNbr].begin();
while(it != betInfoMap[playerNbr].end() )
{
cout << it->first << " -> (" << it->second.betTotal << "," << it->second.coordX << "," << it->second.coordY << ")\n";
++ it;
}
}
char ch;
cin >> ch;
return 0;
}
Thanks,
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by
raptor88
Is this the correct way to use Paul's code of the map of structs in an array for 4 players?
More or less, the code is correct.
Maybe some code rearrangement, removal of the global variable(s), and better design would be in order (maybe have a vector instead of an array, where the number of players can be variable instead of a hard-coded 4). Given that, the code you posted as of now will work correctly.
Regards,
Paul McKenzie
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
More or less, the code is correct.
Maybe some code rearrangement,
Would that be moving the enum statement before the struct statement?
Quote:
removal of the global variable(s),
Since I need to access the betInfoMap[4] in my "GetBets", "PayBets" and on every iteration of the crap table drawing routine which will be constantly looping, I decided to make betInfoMap[4] global. Seems like so much extra work to not make it global and have to pass a reference to every function that needs to access it. Comments welcome.
Quote:
and better design would be in order (maybe have a vector instead of an array, where the number of players can be variable instead of a hard-coded 4).
Hmmm, I'll have to do research on how to do that. My current plan is to use a const value for the number of players like:
---------------
// Place this statement where my constant values will be for easy access.
const int NUMBER_OF_PLAYERS = 4;
map<string, BetInfo> betInfoMap[NUMBER_OF_PLAYERS];
---------------
Quote:
Given that, the code you posted as of now will work correctly.
Thanks for confirming that what I posted will work OK. I posted the code to verify that I wasn't doing anything bad with the array since I know it's possible to read/write outside of an array with dire consequences.
Oh, one more question:
From what I've read, I believe that the memory allocated for the map will be released when the program terminates without my having to do anything. Is that correct? If not, what statement(s) do I need to use to release the memory?
Thanks,
Raptor
-
Re: Which container to do what I need?
Quote:
Originally Posted by raptor88;2089679Since I need to access the betInfoMap[4
in my "GetBets", "PayBets" and on every iteration of the crap table drawing routine which will be constantly looping, I decided to make betInfoMap[4] global. Seems like so much extra work to not make it global and have to pass a reference to every function that needs to access it.
The issue is that GetBets and PayBets are also global functions. Why go that route when you can create an entire class that encapsulates this whole thing? Then there is no need for global variables, global functions, or global definitions.
Code:
#include <vector>
class CrapsGame
{
//...
unsigned numPlayers;
//
public:
CrapsGame(unsigned numPlayers = 4);
void PlayGame(); // plays the game
};
int main()
{
CrapsGame theGame(10); // sets up a game for 10 players
theGame.PlayGame(); // plays the craps game
}
If you want another example, look at the "map" class you're using now. Do you see globals being used in the map class denoting the number of items in the map, the internal tree-like structure used in the map, etc.? You don't -- so how does std::map accomplish keeping track of the map internals without using global variables? The entire map internals are encapsulated in a class -- something your game does not do.
Quote:
Hmmm, I'll have to do research on how to do that. My current plan is to use a const value for the number of players like:
So what happens when you want 6 players, 8 players, etc? You now have to go and change your program, recompile, relink to get it to work for 6 players, and then create another program to have 8 players, etc. You can see how that won't work too well.
First, you should have a struct defining a single player. The road you're going down now seems to suggest you'll have information for a single player strewn about in different and disjoint structs, functions, variables, etc. in your code. Instead you should be consolidating all of this information into a single entity that describes a single player. You now create a vector of this "player information"
Code:
#include <map>
#include <string>
#include <vector>
//...
class PlayerInformation
{
BetInfo m_BetInfo;
std::string m_PlayerName;
//... etc.
};
class CrapsGame
{
typedef std::map<std::string, PlayerInformation> Player;
typedef std::vector<Player> AllPlayers;
//...
AllPlayers m_vPlayers;
//...
void initPlayerInformation()
{
// initialize information for all players defined
}
public:
CrapsGame(unsigned numPlayers = 4) : m_vPlayers(numPlayers)
{
initPlayerInformation();
}
void PlayGame(); // play the game
//...
};
The above is a sample of what could be done.
Quote:
Oh, one more question:
From what I've read, I believe that the memory allocated for the map will be released when the program terminates without my having to do anything. Is that correct?
Yes, the map will destroy itself correctly. No different than the std::string class.
Quote:
If not, what statement(s) do I need to use to release the memory?
Think about the question you asked. What good would a class such as map be if the user of the class has to clean up the remnants? The purpose of the map and other classes is to ensure that the objects will get properly destroyed once the object goes out of scope, and for any reason whatsoever. That's what destructor functions are for.
Let's say that the user did have to clean up the memory. Would you like to code something like this?
Code:
void someFunction()
{
std::map<string, int> SomeMap;
SomeMap.insert(make_pair("xyz", 1));
if ( whatever )
{
DoSomething();
CleanUpMyMap();
return;
}
else
if ( whatever2)
{
CleanUpMyMap();
return;
}
else
if ( whatever3)
{
DoSomething2();
CleanUpMap();
}
else
{
try
{
DoSomething4();
CleanUpMap();
}
catch (someException& )
{
CleanUpMap();
}
}
}
The "CleanUpMap" is the code that the user would need to invoke to clean up the map. Do you see how convoluted code like this would be? Everywhere you have a potential return point, including exceptions that you may or may not know about, you have to clean the map up, else you get a memory leak, a resource not properly destroyed or closed, etc.
Of course, this is not the way that well written classes such as map behave. You declare a map, and if the map goes out of scope for any reason whatsoever (a return from a function, an exception being thrown taking the code out of the current block, an exit from a block of code denoted by { ... }, etc.) the map is cleaned up automatically. Google the term "RAII". The string classes work the same way.
Regards,
Paul McKenzie
-
Re: Which container to do what I need?
Quote:
Originally Posted by
Paul McKenzie
The issue is that GetBets and PayBets are also global functions. Why go that route when you can create an entire class that encapsulates this whole thing? Then there is no need for global variables, global functions, or global definitions.
... snip ...
If you want another example, look at the "map" class you're using now. Do you see globals being used in the map class denoting the number of items in the map, the internal tree-like structure used in the map, etc.? You don't -- so how does std::map accomplish keeping track of the map internals without using global variables? The entire map internals are encapsulated in a class -- something your game does not do.
So what happens when you want 6 players, 8 players, etc? You now have to go and change your program, recompile, relink to get it to work for 6 players, and then create another program to have 8 players, etc. You can see how that won't work too well.
First, you should have a struct defining a single player. The road you're going down now seems to suggest you'll have information for a single player strewn about in different and disjoint structs, functions, variables, etc. in your code. Instead you should be consolidating all of this information into a single entity that describes a single player. You now create a vector of this "player information"
... snip ...
The above is a sample of what could be done.
Yes, the map will destroy itself correctly. No different than the std::string class.
Think about the question you asked. What good would a class such as map be if the user of the class has to clean up the remnants? The purpose of the map and other classes is to ensure that the objects will get properly destroyed once the object goes out of scope, and for any reason whatsoever. That's what destructor functions are for.
Let's say that the user did have to clean up the memory. Would you like to code something like this?
... snip ...
The "CleanUpMap" is the code that the user would need to invoke to clean up the map. Do you see how convoluted code like this would be? Everywhere you have a potential return point, including exceptions that you may or may not know about, you have to clean the map up, else you get a memory leak, a resource not properly destroyed or closed, etc.
Of course, this is not the way that well written classes such as map behave. You declare a map, and if the map goes out of scope for any reason whatsoever (a return from a function, an exception being thrown taking the code out of the current block, an exit from a block of code denoted by { ... }, etc.) the map is cleaned up automatically. Google the term "RAII". The string classes work the same way.
Regards,
Paul McKenzie
My bad Paul. In hindsight I can see why you think my plan is to code most everything using globals and not using classes. The code I posted was just extending your example to verify whether my approach to using an array for the 4 players was valid and was not meant as an example of how I intend to code my program.
I actually plan to use classes for every module and main will just be a very simple loop similar to this:
Code:
int _tmain(int argc, _TCHAR* argv[])
{
sf::RenderWindow App;
//Applications variables
std::vector<cScreen*> Screens;
int screen = 1; //Keeps track of the screen routine currently in use.
//Screens preparations
DummyScreen s0;
Screens.push_back (&s0);
PrimaryMenu s1;
Screens.push_back (&s1);
RTPlay s2;
Screens.push_back (&s2);
// Main loop
// Return zero = exit. Return value greater than zero goes to that screen (routine) number.
while (screen > 0)
{
screen = Screens[screen]->Run(App);
}
return EXIT;
}
There will be a lot more screen routines for different things like SETUP, DISPLAY STATISTICS, HELP, etc.
My plan is to have the one global array (or vector) of map/structs (like you showed me) called BetInformation.
The GetBets class will get mouse clicks and determine which bet the player wants to make. The betTotal for that particular bet will be updated for the active player in BetInformation.
The player will click the "Roll Dice" button which will call the RollDice class. This will produce die1, die2 and diceSum randomly.
The PayBets class will scan the betTotal in the global BetInformation looking for bets made (betTotal > 0). If a betTotal > 0 is found, the bet will be paid, collected or ignored as appropriate for the diceSum rolled. This will continue until the entire BetInformation is scanned.
The DisplayTable class is constantly being called during all of the above to reflect changes on the crap table. DisplayTable will use the betTotal, coordX and coordY to draw the proper amount of chips for every bet made, for each of the 1 to 4 players. IOW, DisplayTable draws everything on the crap table using information in BetInformation.
There's major classes for ComeoutRoll (which contains all of the above) and PointRoll (which also contains all of the above).
In summary, everything will be in classes except the BetInformation array of map/struts which every class needs to access.
Thanks so much for explaining things so well, including the destructors. I really appreciate all of your help and you don't know how much it's helping me structure my program. I'll look into the struct defining a single player you suggested as to how it can fit into my plans.
I always welcome your or other comments. I'm open to changing my plans. Thanks,
Raptor