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.
#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 (constauto& 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 (constauto& 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)
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:
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
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.