C++ 比较一手牌的等级
我的家庭作业分为两部分。第一部分是制作一个程序,当您为类组创建一个对象时,该程序将放置52个卡片对象的向量。为此,我先制作了一副牌,每张牌上的数字分别是1-4和2-14。然后,它将数字更改为字符串,以便以“黑桃A,红桃2”等形式输出卡片。现在,我正在尝试找出如何使其绘制五张卡片并对其进行评估 一对,两对,三对,四对,满座 我不确定我的字符串是否可以这样做,或者我是否必须改变我的整个代码以另一种方式来做。这是代码 编辑:另外,main.cpp是作为模板提供的,我们被迫围绕它进行构建,因此即使有更好的方法,我们也必须以这种形式进行构建>< editedit:我们得到了一个提示“提示:创建一个映射,其中每对存储一个唯一的排名以及该排名在手上出现的次数。你也可以使用count_if函数来确定集合中有多少对或三对。”但老实说,我真的不明白他想要我们在这里做什么C++ 比较一手牌的等级,c++,poker,C++,Poker,我的家庭作业分为两部分。第一部分是制作一个程序,当您为类组创建一个对象时,该程序将放置52个卡片对象的向量。为此,我先制作了一副牌,每张牌上的数字分别是1-4和2-14。然后,它将数字更改为字符串,以便以“黑桃A,红桃2”等形式输出卡片。现在,我正在尝试找出如何使其绘制五张卡片并对其进行评估 一对,两对,三对,四对,满座 我不确定我的字符串是否可以这样做,或者我是否必须改变我的整个代码以另一种方式来做。这是代码 编辑:另外,main.cpp是作为模板提供的,我们被迫围绕它进行构建,因此即使有更好
//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没有强制执行任何有趣的不变量;它只是不可变的。如果你想这样做,你可以简单地声明你的结构Cardconst
。枚举本身已经强制执行了有意义的不变量。@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;
}