Ошибка выполнения c ++ с random_shuffle вектора в классе

Я пытаюсь написать игру в Блэкджек. Я занимался самообучением C ++ в свободное время, и я впервые публикую на любом сайте информацию о программировании.

Я искал ответы на свои проблемы по ходу дела и узнал довольно много … но эта проблема полностью озадачила меня. Я боюсь, что подхожу к этой задаче совершенно неправильно, и, надеюсь, вы сможете мне помочь с этим.

У меня есть класс Card и класс Deck, который содержит вектор из 52 карт. Вектор является приватным членом класса 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";
}
}

main.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;
}

Любая помощь или слова мудрости будут высоко оценены, и я надеюсь, что я все правильно отформатировал …

Большое спасибо

Дэн

0

Решение

Этот метод доступа:

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 на себя.

6

Другие решения

Попробуй вернуться vector<Card>& от get_deck(), В размещенном коде вы делаете две отдельные копии и возвращаете их.

когда random_shuffle пытается выполнить свою работу, поэтому итераторы указывают на два разных вектора.

Как @Will указывает в комментариях к другому ответу, вам лучше сохранить инкапсуляцию, реализовав метод void Deck::shuffle() какие звонки random_shuffle на члене deck и не подвергать deck совсем.

2