Moving one vector element into another vector?

Hi all,

I will try to put my question in an example:

If I have a vector of card objects mimicking a deck of cards:
std::vector<Card>Deck

and wanted to "draw" one card from that deck vector and transfer it into another vector of a player's current hand:
std::vector<Card>MyHand

How would I go about that? I saw many posts about a vector's move function, but I'm still a bit unsure.

Thank you in advance for the help!
1
2
3
4
void dealCard(std::vector<Card>& deck, std::vector<Card>& hand) {
    hand.push_back( deck.back() );
    deck.pop_back();
}

indeed, you should use std::stack to simulate deck of cards.
vector is not suited for this task.
you should use std::stack to simulate deck of cards.

And how is a std::stack supposed to be shuffled (cards randomized)? std::vector (or std::array) can be shuffled as if were a deck of cards.

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3551.pdf
Last edited on
> And how is a std::stack supposed to be shuffled

With the advent of move semantics, we can do this (if we must shuffle the contents of a stack):
move the items in the stack to a vector; shuffle the vector; move shuffled items back into the stack.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stack>
#include <vector>
#include <algorithm>
#include <random>

template < typename T, typename C >
std::stack<T,C>& shuffle( std::stack<T,C>& stk )
{
    std::vector<T> vec ;

    while( !stk.empty() )
    {
        vec.push_back( std::move( stk.top() ) ) ;
        stk.pop() ;
    }

    static std::mt19937 rng( std::random_device{}() ) ;
    std::shuffle( vec.begin(), vec.end(), rng ) ;

    for( T& v : vec ) stk.push( std::move(v) ) ;

    return stk ;
}
move the items in the stack to a vector; shuffle the vector; move shuffled items back into the stack.

That is rather a bit of overkill IMO, especially when seen in the context of a repeatable card game.

Yes, the code below is Frankensteined. Yes, it isn't OOPed. It IMO shows how using a std::vector overall can make more sense than using a std::stack.

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
#include <iostream>
#include <vector>
#include <numeric>
#include <random>
#include <algorithm>

using card = int;

void create_deck(std::vector<card>&);
void display_deck(std::vector<card>&);
void deck_cap(std::vector<card>&);
void deal_cards(std::vector<card>&, int, int);

int main()
{
   std::vector<card> deck;

   deck_cap(deck);

   create_deck(deck);
   display_deck(deck);
   deck_cap(deck);

   std::cout << "Dealing cards......\n\n";

   while (!deck.empty()) { deck.pop_back(); }
   deck_cap(deck);

   create_deck(deck);
   display_deck(deck);
   deck_cap(deck);

   std::cout << "Dealing that deck......\n";
   deal_cards(deck, 5, 7); // five players, 7 card stud
   deck_cap(deck);
}

void create_deck(std::vector<card>& deck)
{
   static std::default_random_engine rng(std::random_device{}());

   std::cout << "Creating a deck....\n";
   deck.resize(52);

   std::iota(deck.begin(), deck.end(), 0);
   std::shuffle(deck.begin(), deck.end(), rng);
}

void display_deck(std::vector<card>& deck)
{
   auto suit = [] (card c) { return "SHDC"[c / 13]; };
   auto rank = [] (card c) { return "23456789TJQKA"[c % 13]; };

   int count { };

   for (const auto& itr : deck)
   {
      std::cout << rank(itr) << suit(itr) << ' ';
      count++;
      if (0 == count % 13) { std::cout << '\n'; }
   }
   std::cout << '\n';
}

void deck_cap(std::vector<card>& deck)
{
   std::cout << "The deck's capacity: " << deck.capacity()
      << ", deck's size: " << deck.size() << "\n\n";
}

void deal_cards(std::vector<card>& deck, int num_players, int num_cards)
{
   auto suit = [] (card c) { return "SHDC"[c / 13]; };
   auto rank = [] (card c) { return "23456789TJQKA"[c % 13]; };

   std::vector<std::vector<card>> players(num_players, std::vector<card>(num_cards));

   for (size_t cards { }; cards < num_cards; cards++)  // fixed dealing
   {
      for (size_t player { }; player < num_players; player++)
      {
         players[player][cards] = deck.back();
         deck.pop_back();
      }
   }

   for (size_t player { }; player < num_players; player++)
   {
      std::cout << "Player#:" << player + 1 << ' ';

      for (const auto& itr : players[player])
      {
         std::cout << rank(itr) << suit(itr) << ' ';
      }
      std::cout << '\n';
   }
   std::cout << '\n';
}

The deck's capacity: 0, deck's size: 0

Creating a deck....
QC QS 7D 5D 8D AH 3H 4S 6S AC JH 7S 6D
TC 4H KD 9C 5S 9H JC KC 2C JS AS 6C 9D
TS 4D 3D 6H 8S KS 5C TD 2H TH 7H 3C 8H
3S AD 7C QH JD KH 2D 5H 4C 8C 2S 9S QD

The deck's capacity: 52, deck's size: 52

Dealing cards......

The deck's capacity: 52, deck's size: 0

Creating a deck....
6S 6H 2C AC 7H 8H 6D AH 9D 3H 4H 8C 7D
9C 8S 4S JH TC AD 2H 9S 5D 5H 6C 8D JC
2D QC JD QS 7C 2S KS KD 3S AS 9H 4D TH
4C KC 3C 3D 7S QH 5S TD KH TS QD JS 5C

The deck's capacity: 52, deck's size: 52

Dealing that deck......
Player#:1 5C JS QD TS KH TD 5S
Player#:2 QH 7S 3D 3C KC 4C TH
Player#:3 4D 9H AS 3S KD KS 2S
Player#:4 7C QS JD QC 2D JC 8D
Player#:5 6C 5H 5D 9S 2H AD TC

The deck's capacity: 52, deck's size: 17


Being a quick test bed I did no error checking, especially if the number of players and cards dealt to each player exceeds the number of cards in the deck.

Originally I was dealing players' hands "wrong." Fixed that. (One card to each player; lather rinse and repeat until each player has the appropriate number of a cards)
Last edited on
both answers are truly awesome!
I never worked on card game, but stack seems more logical for the purpose. IDK, it really depends on what you want. but yes, std::stack is little cumbersome on what you can do with it in this specific case.
wanted to "draw" one card from that deck vector and transfer it into another vector of a player's current hand:

A bit of advice: don't write functions and methods that "do the work." Write functions/methods that "make doing the work easy." If you think like this, you'll write code that is flexible. In this case, you could write a method that will transfer a card from the deck to a hand, but then what about when you put a card on the table? Or discard it?

What you want is a method that will remove a card from a deck (or hand). Then you can do whatever you want with the removed card:
1
2
3
4
5
Card removeCard(vector<Card> &hand) {
    Card result = hand.back();
    hand.pop_back();
    return result;
};


Now if you want to transfer a card from the deck to a hand, it's a one-liner:
hand.push_back(removeCard(deck));
you could leave all the cards in one place and use pointers to hold the 'deck' and the 'hands' and to 'deal', which minimizes excess copying / data movement.

pseudocode for that..
vector deck<cards*>;
init(deck); //probably just copying pointers from a fixed vector of cards
shuffle the deck; //just moves pointers, no data
index = 0;
cards * myhand[5] = {0};
myhand[0] = deck[index++]; //deal me a card

a 10 cent crude example of the idea.
Last edited on
Write functions/methods that "make doing the work easy."

If I were coding a multiple card game app, as the OP apparently is wanting to do, I certainly wouldn't have written what I did in my example above. At least not as Frankensteined as I did.

I write code snippets to test out various ideas of what I want to achieve in a larger program. That way I have an idea if, for example, actually adding/removing a container's elements or using pointers is a better approach for what I want to do. What the costs/benefits are for the different ways to code what is needed for each part of the program.
Topic archived. No new replies allowed.