我有一份两部分的家庭作业。第一部分是在为Deck类创建对象时创建一个包含52个卡对象的向量的程序。我做了这个,让甲板首先给每张卡片1-4号套装,2-14张卡片。然后它将数字更改为字符串,以便它可以输出卡片的形式为"黑桃王牌,两个心脏"现在我想弄清楚如何让它画五张牌并评估它
对,两对,三种,四种,满屋。不确定我的字符串是否可以这样做,或者我是否必须更改整个代码才能以不同的方式执行此操作。这是代码。
编辑:此外,main.cpp作为模板提供,我们被迫围绕它进行构建,所以即使有更好的方法,我们也必须以这种形式进行构建>。
editedit:这是我们给出的一个提示"提示:创建一个地图,其中每个对存储一个唯一的等级和手中等级出现的次数。您还可以使用count_if函数来确定集合中有多少对或三对。"但说实话,我并没有真正得到他希望我们在这里做的事情......
//main.cpp
#include <iostream>
#include "Deck.h"
using namespace std;
int main()
{
Deck deck; // created the object called 'deck'
deck.shuffleCards(); // puts cards in the deck and shuffles them
while (not deck.empty()) // if the deck isn't empty loop will continue
{
cout << deck.draw().toString() << endl; // first it draws a card from the deck
} // of the form '000' and then puts those three
// numbers into the toString function which
} // converts them into a string of words
// in the form 'Card' of 'Suit'. Keeps drawing
// cards run out.
这是函数
#include "Deck.h"
// Constructor for cards that are created
inline Card::Card(int s, int r)
{
suit = s;
rank = r;
};
// This function turns three int 'Cards' into three word
// strings that get returned when you call the function.
std::string Card::toString()
{
std::string oldS = std::to_string(suit); // this creates a string called oldS(uit)
// and changes the int into a string
std::string oldR = std::to_string(rank); // this creates a string called oldR(ank)
// and changes the int into a string
std::string SR = oldS + oldR; // turns the two strings into one
// and puts them into a new string
std::string newS;
std::string newR; // These will be the new suit and rank
// this code turns the numbers (which are already strings) into words.
// 'substr' lets you search any length of the string. We have a string of
// two to three numbers but we need to analyze the first character and the
// second / third seperately. With 'substr' you can do this.
if(SR.substr(0, 1) == "1") // if starting at character 0 and reading one character
newS = "Hearts"; // is equal to '1' then make 'newS' equal to ' Hearts'
if(SR.substr(0, 1) == "2")
newS = "Diamonds";
if(SR.substr(0, 1) == "3")
newS = "Spades";
if(SR.substr(0, 1) == "4")
newS = "Clubs";
if(SR.substr(1, 2) == "2") // if starting at character 1 and reading 2 characters
newR = "Two"; // is equal to '2' then make 'newR' equal to 'Three'
if(SR.substr(1, 2) == "3")
newR = "Three";
if(SR.substr(1, 2) == "4")
newR = "Four";
if(SR.substr(1, 2) == "5")
newR = "Five";
if(SR.substr(1, 2) == "6")
newR = "Six";
if(SR.substr(1, 2) == "7")
newR = "Seven";
if(SR.substr(1, 2) == "8")
newR = "Eight";
if(SR.substr(1, 2) == "9")
newR = "Nine";
if(SR.substr(1, 2) == "10")
newR = "Ten";
if(SR.substr(1, 2) == "11")
newR = "Jack";
if(SR.substr(1, 2) == "12")
newR = "Queen";
if(SR.substr(1, 2) == "13")
newR = "King";
if(SR.substr(1, 2) == "14")
newR = "Ace";
SR = newR + " of " + newS; // this string had the numbers in it but now we can
// reassign it the string 'Card of suit'
return SR; // returns the string which is outputted to the console when you call
// the 'toString' function
};
// This function draws top object of the vector then pops it from
// the vector and returns it to the call. It is of return type 'Card'.
Card Deck::draw()
{
int a = Cards.size();
int b = a - 1; // -1 because the vector has 52 cards but you
Cards.pop_back(); // want to access [0] - [51] not [52]
return Cards[b];
};
// This is the function that creates the cards in the vector.
// It uses two loops and assigns a number to 'a' and 'b'. The first number is
// in the range 1 - 4 and the second is 2 - 14. It then creates an object using
// 'a' and 'b' which is then pushed back onto the vector. All vector objects have
// the same name as of now (but not the same data). Shuffles the objects at the end.
void Deck::shuffleCards()
{
int a;
int b;
for(a = 1; a < 5; a++) // 1 - 4
{
for(b = 2; b < 15; b++ ) // 2 - 14
{
Card newCard(a, b);
Cards.push_back(newCard);
}
}
std:: mt19937 seed(rd()); // this creates the seed
std::shuffle(Cards.begin(), Cards.end(), seed); // this shuffles the deck with the
}; // random seed
// This function checks if the deck is empty
// if it is not it will return false and when it is empty
// it will return true which breaks the loop in main.cpp
bool Deck::empty()
{
if(Cards.size() < 1)
return true;
else
return false;
};
// This function will reset the deck if called. It will purge
// the vector and then repopulate it with the original contents.
// but will not shuffle them.
void Deck::reset()
{
Cards.clear();
int a;
int b;
for(a = 1; a < 5; a++)
{
for(b = 2; b < 15; b++ )
{
Card newCard(a, b);
Cards.push_back(newCard);
}
}
};
和标题
#ifndef DECK_H
#define DECK_H
#include <vector>
#include <string>
#include <random>
#include <algorithm>
class Card
{
public:
inline Card(int s, int r);
int rank;
int suit;
std::string toString();
};
class Deck
{
private:
std::vector<Card> Cards;
std::random_device rd;
public:
void shuffleCards();
void reset();
Card draw();
bool empty();
};
class Hand
{
public:
std::vector<std::string> Hand;
void fillHand()
{
Deck deck;
std::string C1 = deck.draw().toString();
std::string C2 = deck.draw().toString();
std::string C3 = deck.draw().toString();
std::string C4 = deck.draw().toString();
std::string C5 = deck.draw().toString();
Hand.push_back(C1);
Hand.push_back(C2);
Hand.push_back(C3);
Hand.push_back(C4);
Hand.push_back(C5);
}
};
#endif
提前谢谢你:D
此时我基本上是从手类创建一个新对象,用5张随机牌填充手牌,每张卡片中都有一张#34;西装卡片的字符串&#34;。因为我只需要担心&#34;卡&#34;我应该更改代码以丢弃&#34;&#34;和&#34;适合&#34;?最终我们还需要使用西装,这就是为什么我不想那样做。
答案 0 :(得分:3)
字符串对玩家只有重要意义,对于计算机而言,只比int解决方案浪费内存。
那就是说,我建议你使用枚举:
enum Suit {Hearts, Clubs, Spades, Diamonds};
enum Rank {Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen King, Ace};
请注意,枚举从0开始,如果没有其他内容,则添加1,因此它们处于完美的顺序,只是碰巧它们更好地表示为int。
使用to_string方法:
string toString(const Suit){
switch(Suit){
case Hearts:
return "Hearts";
et cetera
与
class Card
{
public:
Card(const Suit suit, const Rank rank); //<--- why did you declare this inline? arguments should be const
string toString() const;
Rank rank() const;
Suit suit() const;
private: // <-- encapsule. A card should not be able to change those values
Rank _rank;
Suit _suit;
};
此类卡是完美的容器。没有必要将其更改为字符串,至少在您不想打印时不会。
现在有趣的部分:
首先,我要让Hand成为Deck(“创建手”)返回的东西,或者让它成为一个唯一的构造函数的Deck。应始终使用五张卡来实例化一只手,这应该是唯一可能的状态。甲板应始终是一个独立的对象。
我给Hand一张卡片。不需要字符串。让一切变得更轻松。
作为辅助方法,我将添加一个方法来创建一个计算每个等级的多重性的向量。从那里,您可以轻松获得一个计算有多少双打,三元组和四元组的向量。如果你有,那你就完成了。所以这样:
enum HandValue {HighCard, Pair, ThreeOfAKind, FourOfAKind, FullHouse };
class Hand //note that I omitted some methods that are not relevant for the answer
{
private:
vector<Card> cards;
vector<unsigned int> multiplicityOfRank() const;
vector<unsigned int> components() const; //<-- uses multiplicityOfRank
public:
Hand(Deck& deck); // <-- will reduce deck by five cards. Note that a reference is used.
HandValue evaluate() const; // <-- uses components
}
组件可能像位置0存储双打数量,位置1是三元组,位置2是四元组
这有帮助吗?还有问题吗?
(顺便说一下,如果名称空间很明显,我个人不想编写名称空间 - 你知道using
关键字,就像using std::vector;
一样吗?不要像{1}}那样使用using namespace std;
但是,给定的主,std太大,不能排除名称冲突。)
答案 1 :(得分:2)
Re:&#34;如果您更改代码以丢弃&#39;&#39;并且&#39;适合&#39;?&#34;
我没有理由这样做。你有一个toString()方法,它将为输出生成一个显示字符串,我喜欢示例代码不是将字符串结果存储在类成员中。
你的.suit和.rank会员可以用来评估一张卡是否是所谓的套装之一(一对,两对,三种,四种,满屋)。不要与字符串表示进行比较 - 因为这是一种不太直接的比较,效率较低,并且如果可能更新字符串表示的真实情况,例如错误,则容易出错。提供西班牙语本地化。
我认为大部分工作都是在这里完成的。您对卡片的评估应该非常简单。也许为Hand添加一种新方法,检查你已经推入手牌的牌中的牌组。
答案 2 :(得分:-1)
正如另一个答案中所建议的那样,我会专注于使用枚举而不是字符串。您有一个非常有限的潜在价值清单。我首先要设置以下typedef:
enum class Suit {Hearts, Clubs, Spades, Diamonds};
constexpr static auto num_ranks = 13; // must be consistent with below
enum class Rank {Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace};
enum class PokerHand {Nada, Pair, TwoPair, ThreeOfKind, FullHouse, FourOfKind};
using Card = const struct {
Suit suit;
Rank rank;
};
using PlayerHand = std::array<Card, 5>;
设置完这个机器后,我们现在可以继续推出我们的解决方案:
PokerHand determineHand(const PlayerHand& player_hand) {
std::vector<int> rank_count(num_ranks);
for (auto& card : player_hand) {
++rank_count[static_cast<int>(card.rank)];
}
auto count_rank_counts = [&] (int count) {
return std::count(rank_count.begin(), rank_count.end(), count);
};
if (count_rank_counts(4)) return PokerHand::FourOfKind;
if (count_rank_counts(3)) {
if (count_rank_counts(2)) return PokerHand::FullHouse;
else return PokerHand::ThreeOfKind;
}
if (count_rank_counts(2) == 2) return PokerHand::TwoPair;
if (count_rank_counts(2) == 1) return PokerHand::Pair;
return PokerHand::Nada;
}
几个关键点。 static_cast可能看起来有点奇怪,但实际上这是合法的,因为枚举类的支持类型没有明确声明它是int,除非int不够大。然后我们设置一个函数来计算某个排名发生的次数。我知道它有点奇怪,因为它是计数的数量。但它确实如此。然后我们只需检查手从最高到最低。不是很有效但很容易理解。