jjzjj

c++ - 比较一手牌的等级

coder 2024-02-11 原文

我的家庭作业分为两部分。第一部分是编写一个程序,当您为 Deck 类创建一个对象时,该程序会放置一个包含 52 个卡片对象的 vector 。为此,我首先让一副牌给每张牌的花色编号 1-4 和纸牌编号 2-14。然后它将数字更改为字符串,以便它可以以“黑桃 A、红心两”等形式输出卡片。现在我想弄清楚如何让它抽五张卡片并评估它

一对,两对,三对,四对,葫芦。

不确定这是否适用于我的字符串,或者我是否必须更改我的整个代码才能以不同的方式执行此操作。这是代码。

编辑:此外,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 张随机牌填充手牌,每张牌中都有一个“花色牌”形式的字符串。既然我只需要担心“卡”,我是否应该更改代码以丢弃“of”和“suit”?最终我们还需要使用套装,这就是我不想这样做的原因。

最佳答案

字符串只对玩家有意义,对于电脑来说,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;
};

此类 Card 本身就是完美的容器。无需将其更改为字符串,至少如果您不想打印它则不需要。

现在是有趣的部分:

首先,我会让 Hand 成为 Deck(“创建手”)返回的东西,或者在它的唯一构造函数中获取 Deck。 Hand 应该总是用五张牌实例化,这应该是它唯一可能的状态。 Deck 应该始终是一个独立的对象。

我会给 Hand 一个 Card vector 。不需要字符串。让一切变得更简单。

作为辅助方法,我将添加一个创建 vector 的方法,该 vector 计算每个等级的多重性。由此,您可以轻松获得一个 vector ,计算有多少双胞胎、三胞胎和四胞胎。如果你有,你就完成了。所以像这样:

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; 吗?不要像在给定的 main 中那样使用 using namespace std;,不过,std 太大而无法排除名称冲突。)

关于c++ - 比较一手牌的等级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44168693/

有关c++ - 比较一手牌的等级的更多相关文章

  1. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby - 是否有用于复杂比较的漂亮语法? - 2

    方法应返回-1,0或1分别表示“小于”、“等于”和“大于”。对于某些类型的可排序对象,通常将排序顺序基于多个属性。以下是可行的,但我认为它看起来很笨拙:classLeagueStatsattr_accessor:points,:goal_diffdefinitializepts,gd@points=pts@goal_diff=gdenddefothercompare_pts=pointsother.pointsreturncompare_ptsunlesscompare_pts==0goal_diffother.goal_diffendend尝试一下:[LeagueStats.new(

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  9. ruby - 尝试比较两个文本文件,并根据信息创建第三个 - 2

    我有两个文本文件,master.txt和926.txt。如果926.txt中有一行不在master.txt中,我想写入一个新文件notinbook.txt。我写了我能想到的最好的东西,但考虑到我是一个糟糕的/新手程序员,它失败了。这是我的东西g=File.new("notinbook.txt","w")File.open("926.txt","r")do|f|while(line=f.gets)x=line.chompifFile.open("master.txt","w")do|h|endwhile(line=h.gets)ifline.chomp!=xputslineendende

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐