【问题标题】:c++ runtime error with random_shuffle of vector in a classc++ 运行时错误,类中向量的 random_shuffle
【发布时间】:2012-10-21 03:11:13
【问题描述】:

我正在尝试编写二十一点游戏。我在业余时间一直在自学 C++,这是我第一次在任何网站上发布有关编程的文章。

我一直在寻找问题的答案,并且学到了很多东西。但是这个问题完全让我感到困惑。我担心我在完成任务时完全错误,希望你能帮助我。

我有一个 Card 类和一个包含 52 个 Card 的向量的 Deck 类。向量是 Deck 类的私有成员,我担心这是我的问题?

当我将 random_shuffle 行添加到我的代码中时,它可以正常编译,但随后控制台窗口崩溃(Windows 7 x64、code::blocks、c++)。我无法弄清楚我做错了什么。我将向量随机访问迭代器称为 begin() 和 end()...

deck.h

#ifndef DECK_H
#define DECK_H

#include <vector>

using namespace std;

/** Card Class */
class Card
{
public:
/** Constructor prototypes */
//Card(); //default constructor
Card(int s, int r) : suit(s), rank(r) {} 

/** GET function prototypes */
int getRank(); // returns card number as int
string getSuit(); // returns the suit in a string

private:
int rank;
int suit;
} ;

/** Deck class */
class Deck
{
public:
Deck();
vector <Card> get_deck() { return deck; };

private:
vector<Card> deck;
};

#endif // DECK_H

deck.cpp

#include <iostream>
#include <string>
#include <vector>
#include "deck.h"

using namespace std;

/** Deck ctor to initialise deck */
Deck::Deck()
{
for(int suit = 0; suit < 4; suit++)
{
    for(int rank = 0; rank < 13; rank++)
    {
        deck.push_back(Card(suit,rank));
    }
}

}

/** Functions to GET rank and suit */
// Function to get rank as int
int Card::getRank()
{
return rank;
}

// Function to get suit as string
string Card::getSuit()
{
switch(suit)
{
    case 0:
    return "Diamonds";

    case 1:
    return "Hearts";

    case 2:
    return "Clubs";

    case 3:
    return "Spades";

    default:
    return "Error";
}
}

ma​​in.cpp

#include <iostream>
#include <algorithm>
#include <ctime> // time()
#include <string>
#include <vector>

#include "deck.h"

using namespace std;

int main()
{

Deck mydeck;

random_shuffle( mydeck.get_deck().begin(), mydeck.get_deck().end() );

// Loop to iterate through deck of cards
for(int i = 0; i<52; i++)
{
    cout << mydeck.get_deck()[i].getRank() << " of " << mydeck.get_deck()[i].getSuit() << endl;
}

// Display size of deck
//cout << endl << "The size of deck is: " << mydeck.get_deck().size() << endl;


return 0;
}

任何帮助或智慧之言将不胜感激,我希望我的格式正确...

非常感谢

【问题讨论】:

  • +1 用于发布重现问题的可编译代码,-1 用于不缩小范围。所以 0。
  • 你的 Deck 类只不过是一个围绕卡片向量的 [无用] 包装器。在我看来,Deck 类应该有自己的 shuffle 方法,即void Deck::Shuffle() { random_shuffle(deck.begin(), deck.end()); } - 以及其他方法,例如获取顶牌或底牌,或从牌组中随机获得一张牌。然后我会摆脱你的get_deck() 方法。
  • @StarPilot 这是此页面的链接。
  • 哈哈。对于那个很抱歉。抓取了错误的窗口 URL。只是其中的一天。
  • @LuchianGrigore 将来我会将代码范围缩小到我的问题所在...谢谢

标签: c++ class vector blackjack


【解决方案1】:

这个访问器方法:

vector <Card> get_deck() { return deck; };

返回卡片向量的副本。所以当你调用它两次时,你会得到两个不同的副本,并且第一个副本的begin() 与第二个副本的end() 不匹配,所以它崩溃了。

要修复它,您应该通过引用返回数组,这样就不会复制:

vector <Card>& get_deck() { return deck; }  // no semicolon needed here
//           ^
//           |
//    this is a reference

但是,这允许调用者修改内部数组,这通常是一个坏主意。为避免这种情况,您应该通过const 参考返回它:

const vector <Card>& get_deck() { return deck; }

但是如果你这样做了,那么std::random_shuffle 就不能修改数组了。因此,为了解决这个问题,理想的解决方案是向 Deck 类添加一个类方法,该类方法本身调用 random_shuffle

【讨论】:

  • 另一种选择是在 Deck 类本身中实现随机播放。
  • @Will 这是个好主意。
  • 感谢您清楚地解释我哪里出错并帮助我解决问题。现在一切都说得通了,我现在可以看到封装的过程。
【解决方案2】:

尝试从get_deck() 返回vector&lt;Card&gt;&amp;。在发布的代码中,您将制作两个单独的副本并返回它们。

random_shuffle 试图完成它的工作时,它因此有指向两个不同向量的迭代器。

正如@Will 在 cmets 中指出的另一个答案,您最好通过实现一个方法 void Deck::shuffle() 来保留封装,该方法在成员 deck 上调用 random_shuffle 而根本不暴露 deck

【讨论】:

  • 我怎样才能循环遍历向量中的实际卡片而不是向量的副本?我猜它是像 void Deck::displayCard() 这样的 Deck 的成员函数,然后它将访问私有变量(向量甲板)?
猜你喜欢
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
相关资源
最近更新 更多