C++ 比较一手牌的等级

C++ 比较一手牌的等级,c++,poker,C++,Poker,我的家庭作业分为两部分。第一部分是制作一个程序,当您为类组创建一个对象时,该程序将放置52个卡片对象的向量。为此,我先制作了一副牌,每张牌上的数字分别是1-4和2-14。然后,它将数字更改为字符串,以便以“黑桃A,红桃2”等形式输出卡片。现在,我正在尝试找出如何使其绘制五张卡片并对其进行评估 一对,两对,三对,四对,满座 我不确定我的字符串是否可以这样做,或者我是否必须改变我的整个代码以另一种方式来做。这是代码 编辑:另外,main.cpp是作为模板提供的,我们被迫围绕它进行构建,因此即使有更好

我的家庭作业分为两部分。第一部分是制作一个程序,当您为类组创建一个对象时,该程序将放置52个卡片对象的向量。为此,我先制作了一副牌,每张牌上的数字分别是1-4和2-14。然后,它将数字更改为字符串,以便以“黑桃A,红桃2”等形式输出卡片。现在,我正在尝试找出如何使其绘制五张卡片并对其进行评估

一对,两对,三对,四对,满座

我不确定我的字符串是否可以这样做,或者我是否必须改变我的整个代码以另一种方式来做。这是代码

编辑:另外,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. 
//main.cpp
#包括
#包括“Deck.h”
使用名称空间std;
int main()
{
Deck Deck;//创建了名为“Deck”的对象
牌组。shuffleCards();//将牌放入牌组并洗牌
while(不是deck.empty())//如果deck不是空的,循环将继续
{
coutRe:“你是否应该改变代码,扔掉‘of’和‘suit’?”

我看不出有什么理由这样做。您有一个toString()方法,它将为输出生成一个显示字符串,我喜欢示例代码没有将字符串结果存储在类成员中

您的.suit和.rank成员可用于评估一张卡是否是希望的一组(一对、两对、三对、四对和满座)。不要与字符串表示法进行比较——因为这是一种不太直接的比较,效率较低,并且在可能更新字符串表示法的实际情况下(例如,提供西班牙语本地化)容易出错


我认为大部分工作都在这里完成。你对牌的评估应该很容易。也许可以在手上添加一种新方法,检查你推到手上的牌中的集合。

字符串对玩家只有意义,而对于计算机来说,它只是在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 toString(const Suit){
    switch(Suit){
        case Hearts:
        return "Hearts";
et cetera

类卡
{
公众:

Card(const Suit Suit,const Rank Rank);//正如另一个答案中所建议的,我将重点使用枚举,而不是字符串。您有一个非常有限的潜在值列表。我将从设置以下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>;
enum类套装{红心、梅花、黑桃、钻石};
constexpr static auto num_ranks=13;//必须与下面的一致
Enm类秩{2,三,四,五,六,七,八,九,十,杰克,皇后,国王,ACE };
enum类扑克手{Nada,Pair,TwoPair,Three of Kind,FullHouse,Fourof Kind};
使用Card=const结构{
西服;
等级;
};
使用PlayerHand=std::array;
设置好这一机制后,我们现在可以继续并将我们的解决方案作为一项功能:

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;
}
PokerHand determinatehand(const playernand&player\u hand){
std::向量秩计数(num\u秩);
用于(自动和卡片:玩家手){
++等级计数[静态施法(卡片等级)];
}
自动计数排名计数=[&](整数计数){
返回std::count(rank\u count.begin(),rank\u count.end(),count);
};
if(count\u rank\u counts(4))返回PokerHand::FourOfKind;
如果(计数、排名、计数(3)){
如果(计数排名计数(2))返回扑克手::全场;
否则还扑克手::三种;
}
if(count\u rank\u counts(2)==2)返回PokerHand::TwoPair;
if(count\u rank\u counts(2)==1)返回扑克手::对;
返回扑克手::Nada;
}
几个关键点。静态_cast可能看起来有点奇怪,但事实上这是合法的,因为没有显式声明它的枚举类的支持类型是int,除非int不够大。然后我们设置了一个函数来计算某个秩计数发生的次数。我知道这有点奇怪,因为它是数数。但就是这样。然后我们简单地从最高点到最低点检查手。不是很有效,但很容易遵循


活生生的例子:。

这是一个比通常在这里发布的关于这个主题的问题更好的问题。通常有
enum
用于表示卡片等级。@giraffe船长,他们写了/保留了评论!@Ðаn我们从一个很低的栏开始。但是我不愿意投票结束。这个问题确实有工作on:已经给出了上下文,并对代码进行了注释。但是,如果它只是可回答的,那么实际问题和预期答案是什么?这是一个可接受的实现吗?是否有可能通过它实现目标:可能只需要一些小的修复,例如将一个外部甲板传递给另一个人::fillHand(你不需要为每只手拿一副新牌,而是使用当前的牌)。这是一个很好的实现吗:绝对不是。应该使用enum并直接测试enum(或者至少是int)不是首先转换为字符串并测试子字符串。这里的主题是什么?我不同意类
Card
;它可以是一个有两个公共成员的结构。Card没有强制执行任何有趣的不变量;它只是不可变的。如果你想这样做,你可以简单地声明你的结构Card
const
。枚举本身已经强制执行了有意义的不变量。@NirFriedman我会这样做的
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;
};
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
}
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;
}