Container questions

Started by
5 comments, last by Zahlman 15 years, 10 months ago
I'm working on Uno with the goal of eventually adding an AI (Uno is a very simply game) and possibly networking (way down the road). Anyways, I'm trying to decided on the correct container for cards in the Player class. A vector is nice because I can use [] to access elements which is great for getting input from the user. However, I need the cards to be ordered, which means that a set or something else would be great because that would all happen without my intervention and it would stay sorted over additions and removals. For reference I ask players to play cards like this 1 2 3 4 5G 7R 4B 7B And then I have them input the number above the card they want to play (it's text based for right now). Thanks!
Advertisement
Vector and ordered container are not mutually exclusive. You can keep a vector sorted, and so have it ordered. Make a utility function for inserting an element into a sorted vector, and find the insertion point using, say, std::lower_bound, and maybe a similar function for removing elements for symmetry between insertion and removal.

That way you have simple ways to insert and remove, the vector is ordered, and you have random access to its content.

For reference, check this. Binary search related functions are in 3.3.
Another question I have is whether it's bad form to store a pointer in a vector. For my hand variable it would be something like std::vector<Card*> hand. This is nice because I can simply pass around pointers and don't have to construct Cards all the time. Plus, if you don't use pointers, you can't use polymorphism. It just makes it much more difficult when a set sorts by pointer rather than what the pointer points to.
What kind of cards do you use that are so heavy and expensive to create and/or copy that you consider using pointer to cards instead? And what kind of cards do you use that requires inheritance?
It was a general question, my cards are very lightweight and won't use inheritance. But say I was writing a game that had a base moveableobject type and I had a list of those. I would be required to use a pointer in that case, right? Is that bad form?
In a mostly unrelated question I have a std::list of players that I need to iterate over both forwards and backwards. In Uno you can play a reverse card that reverses the order of play. I was thinking about using an iterator to keep track of the position and then when it was reversed switch to the alternate type of iterator. However as I'm implementing it, it's getting rather nasty. Does anyone have a good alternative?
Quote:Original post by starruler
In a mostly unrelated question I have a std::list of players that I need to iterate over both forwards and backwards. In Uno you can play a reverse card that reverses the order of play. I was thinking about using an iterator to keep track of the position and then when it was reversed switch to the alternate type of iterator. However as I'm implementing it, it's getting rather nasty. Does anyone have a good alternative?


List iterators are bidirectional, because std::list is a doubly-linked list. Therefore, you can use the operator-- of the iterator as well as operator++. Set a flag to remember which direction you're going in, and pick accordingly.

You might try something like:

template <typename Container, typename BidirectionalIterator>void advance_cyclic(const Container& c, BidirectionalIterator& iter, int delta) {  if (delta > 0) {    if (++iter == c.end()) { iter = c.begin(); } advance_cyclic(delta - 1);  } else if (delta < 0) {    if (iter == c.begin()) { iter = c.end(); } --iter; advance_cyclic(delta + 1);  }}


But you might find it more practical to manipulate the list instead, such that the desired player is always at the front:

template <typename Container>void rotate_n(const Container& c, int delta) {  Container::iterator iter = (delta < 0) ? c.end() : c.begin();  std::advance(iter, delta);  std::rotate(c.begin(), iter, c.end());}

This topic is closed to new replies.

Advertisement