I would like to generate a deck of card objects in a standard, 52 card deck of playing cards that contain information about each card's suit and rank using C .
The way I have been doing this so far is creating enumerated types for both the "Rank" and "Suit" information. So:
enum Rank {Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King};
enum Suit {Heart, Spades, Diamonds, Clubs};
Then, I define a class 'Card' like this: `
class Card {
public:
Rank CardRank;
Suit CardSuit;
};
` Now I need to generate an exhaustive list of all card objects using the two enumerated types (which I was going to do with some kind of "Generate Deck" function"). This sounds like it's going to involve some kind of for loop.
I tried to adapt the answer here to my situation, which looked like:
for ( int i = Ace; i != King; i )
{
Card DummyCard;
DummyCard.CardRank = static_cast<Rank>(i);
std::cout << "This is " << DummyCard.CardRank << std::endl; //This line is just to check what the program is doing
};
I'm having two problems:
The program just counts the int values, rather than returning what I want (which is the rank values).
That answer was dealing only with iterating over one a single enum and didn't deal with two enum types that are part of a class. I imagine I would need a nested for loop to iterate over the suits (in addition to the ranks), but I'm not really sure what that would look like.
So how can I iterate over two enum types that are both part of a class in order to generate an exhaustive list of class objects?
CodePudding user response:
You cannot print out the "name" of enum items unless you use something like a std::map<Rank, std::string>
and std::map<Suit, std::string>
. Keep in mind that the terms "Ace", "Spades", etc. are in the same boat as variable names, they don't exist in the final executable. An enumeration is, in your case, a fancy way of mapping a more memorable name to (usually) an int value. So, when you output that enum, you're printing the underlying int, not the identifier (again, which doesn't exist at runtime).
As for the nested loop, you just need to do exactly what you did for the ranks. I'm not sure where the confusion is there. Also, keep in mind that if you say i != King
, your loop will run for Ace through Queen. However, because the underlying type is an integer, you can just treat it like one. Ace is 0, King is 12, you can just say i <= King
.
for (int r = Ace; r <= King; r) {
for (int s = Heart; s <= Clubs; s) {
Card DummyCard;
DummyCard.CardRank = static_cast<Rank>(r);
DummyCard.CardSuit = static_cast<Suit>(s);
std::cout << r << " of " << s << std::endl;
}
}
CodePudding user response:
Yes you need another loop:
#include <iostream>
#include <vector>
enum Rank {Ace, Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King};
enum Suit {Heart, Spades, Diamonds, Clubs};
struct Card {
Rank CardRank;
Suit CardSuit;
};
int main() {
std::vector<Card> cards;
for (int rank = 0; rank < King 1; rank) {
for (int suit = 0; suit < Clubs 1; suit) {
cards.push_back({static_cast<Rank>(rank),static_cast<Suit>(suit)});
}
}
for (const auto& card : cards) {
std::cout << card.CardRank << " " << card.CardSuit <<"\n";
}
}
However, it is unclear what you mean with "The program just counts the int values, rather than returning what I want" because static_cast<Rank>(i)
is the Rank
you get by converting the int
to a Rank
. It is not an int
.
Your code looks fine, it only misses the last element because the loop only continues as long as i != King
. To include also King
s you can change the condition to i < King 1;
.