Hey guys,
Im making an uno card game and I think so far so good, however once I compile it, my program doesnt read any errors, but a box pops up stating "vector subscript out of range" and it is confusing me a lot. I think I can identify where the problem is, I just have no idea how to go about fixing it or even trying something different.
My code is in 5 different files but I will put 3 of them here. Hopefully its not too confusing. Any help would be greatly appreciated.

Header File

#ifndef UNODECK_H
#define UNODECK_H
#include <iostream>
#include <vector>
#include "unoNumberCard.h"
using namespace std;

class UnoDeck {
    vector<UnoNumberCard> draw_pile;
    vector<UnoNumberCard> discard_pile;
public:
    UnoDeck();
    void discard(UnoNumberCard);
    UnoNumberCard top_discard();
    UnoNumberCard draw();
    void shuffle();

};
#endif

UnoDeck Cpp file

#include <iostream>
#include <cstdlib>
#include "unoDeck.h"
using namespace std;



UnoDeck::UnoDeck() {
  for (int k=0; k<2; k++) {
    UnoNumberCard c1("Red",k);
    draw_pile.push_back(c1);
    UnoNumberCard c2("Blue",k);
    draw_pile.push_back(c2);
    UnoNumberCard c3("Yellow",k);
    draw_pile.push_back(c3);
    UnoNumberCard c4("Green",k);
    draw_pile.push_back(c4);
  }
  UnoNumberCard c5("Red",0);
  draw_pile.push_back(c5);
  UnoNumberCard c6("Blue",0);
  draw_pile.push_back(c6);
  UnoNumberCard c7("Yellow",0);
  draw_pile.push_back(c7);
  UnoNumberCard c8("Green",0);
  draw_pile.push_back(c8);

}


int randrange(int first, int last) {
  return (rand()%(last-first))+first;
}

void UnoDeck::shuffle() {
  for (int i(0); i<75; i++) {
    swap(draw_pile[i],draw_pile[randrange(i+1,76)]);
  }
}
void UnoDeck::discard(UnoNumberCard b){
    discard_pile.push_back(b);


}
UnoNumberCard UnoDeck::top_discard() {
     return discard_pile.back();
}


UnoNumberCard UnoDeck::draw(){
    
    if (draw_pile.empty()){
        UnoNumberCard temp= discard_pile.back();
        discard_pile.pop_back();
        while(!discard_pile.empty()){
            draw_pile.push_back(discard_pile.back());
            discard_pile.pop_back();
        }
        discard_pile.push_back(temp);
        shuffle();
        draw_pile.push_back(discard_pile.back());
        discard_pile.pop_back();
        

    }else{
        draw_pile.back();
    }
    return draw_pile.back();// I have a feeling something here is affecting my program
}

Cpp file containing main which creates a UnoDeck variable, and do the following 152 times
(i.e. twice through the deck): print the top discarded card, draw a new
card, and discard it. Because the deck will be shuffled partway
through, the order of the cards the second time will be different than the first.

#include <iostream>
#include <cstdlib> // for srand
#include <ctime> // for time
#include "unoDeck.h"
#include "unoNumberCard.h"
using namespace std;


int main () {
  srand((int)time(0)); // seed the random number generator with the current time



  UnoDeck d;

  d.shuffle();

  UnoNumberCard tempo("Blue",8);//I think this will have to change eventually, but for now I put blue and 8 to test

  for(int m; m=152; m++){//
      tempo = d.draw();
      tempo.print();
      UnoNumberCard discard_pile(tempo);
  }
}

Any one have any ideas?

Recommended Answers

All 9 Replies

I think I can identify where the problem is, I just have no idea how to go about fixing it or even trying something different.

Care to share where you think the problem is, or is it a secret?

I commented it out. Its in the first cpp file line 68 and in the last one with the main in it at lines 18 and down. I think those are affecting something but im just not sure. I cant understand what "vector out of range" means.

"vector subscript out of range"

Just based on that piece of information alone, I bet you are attempting to access a vector element that is larger than vector.size()

vector<int> v;

v.push_back(1);
v.push_back(2);
v.push_back(3);

//No bueno...  only elements 0,1, and 2 are currently populated:
cout << v[3];   //Access out of bounds

you might get better shuffling results if you use std::random_shuffle() found in <algorithm>.

how would i use that random_shuffle() found in algorithm?

Try looking it up.

Ok, I'll do the work for you:
http://www.cplusplus.com/reference/algorithm/random_shuffle/

template <class RandomAccessIterator>
void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last );

template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& rand );

Rearrange elements in range randomly
Rearranges the elements in the range [first,last) randomly.

The function swaps the value of each element with that of some other randomly chosen element. When provided, the function rand chooses which element.

template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator& rand )

{
  iterator_traits<RandomAccessIterator>::difference_type i, n;
  n = (last-first);
  for (i=2; i<n; ++i) swap (first[i],first[rand(i)]);
}

Parameters

first, last
Forward iterators to the initial and final positions of the sequence to be shuffled. The range used is [first,last), which contains all the elements between first and last, including the element pointed by first but not the element pointed by last.
rand
Pointer to unary function taking one argument and returning a value, both of the appropriate difference type (generally ptrdiff_t). The function shall return a value between zero and its argument (lower than this).

// random_shuffle example
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

// random generator function:
ptrdiff_t myrandom (ptrdiff_t i) { return rand()%i;}

// pointer object to it:
ptrdiff_t (*p_myrandom)(ptrdiff_t) = myrandom;

int main () {
  srand ( unsigned ( time (NULL) ) );
  vector<int> myvector;
  vector<int>::iterator it;

  // set some values:
  for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9

  // using built-in random generator:
  random_shuffle ( myvector.begin(), myvector.end() );

  // using myrandom:
  random_shuffle ( myvector.begin(), myvector.end(), p_myrandom);

  // print out content:
  cout << "myvector contains:";
  for (it=myvector.begin(); it!=myvector.end(); ++it)
    cout << " " << *it;

  cout << endl;

  return 0;
}

I have identified that my problem mainly comes from my shuffle function. I am reading up and trying to figure out the random_shuffle(), but feel that would cause me to change a lot of code, although I am not entirely sure. This is my shuffle function

#include <iostream>
#include <cstdlib>
#include "unoDeck.h"
#include "unoNumberCard.h"
using namespace std;



UnoDeck::UnoDeck() {
  for (int k=0; k<10; k++) {
    UnoNumberCard c1("Red",k);
    draw_pile.push_back(c1);
    UnoNumberCard c2("Blue",k);
    draw_pile.push_back(c2);
    UnoNumberCard c3("Yellow",k);
    draw_pile.push_back(c3);
    UnoNumberCard c4("Green",k);
    draw_pile.push_back(c4);
  }
  UnoNumberCard c5("Red",0);
  draw_pile.push_back(c5);
  UnoNumberCard c6("Blue",0);
  draw_pile.push_back(c6);
  UnoNumberCard c7("Yellow",0);
  draw_pile.push_back(c7);
  UnoNumberCard c8("Green",0);
  draw_pile.push_back(c8);

}


int randrange(int first, int last) {
  return (rand()%(last-first))+first;
}
//Right here is where I believe I am getting vector out of range. This means that I am trying to get more cards than I have? 
void UnoDeck::shuffle() {
  for (int i(0); i<75; i++) {
    swap(draw_pile[i],draw_pile[randrange(i+1,76)]);
  }
}
void UnoDeck::discard(UnoNumberCard b){
    discard_pile.push_back(b);


}
UnoNumberCard UnoDeck::top_discard() {
     return discard_pile.back();
}


UnoNumberCard UnoDeck::draw(){
    while (!draw_pile.empty()){
        UnoNumberCard tempo = draw_pile.back();
        draw_pile.pop_back();
        return tempo;
    }

    if (draw_pile.empty()){
        UnoNumberCard temp= discard_pile.back();
        discard_pile.pop_back();
        while(!discard_pile.empty()){
            draw_pile.push_back(discard_pile.back());
            discard_pile.pop_back();
        }
        discard_pile.push_back(temp);
        shuffle();
        draw_pile.push_back(discard_pile.back());
        discard_pile.pop_back();
        

    }else{
        draw_pile.back();
    }
    return draw_pile.back();
}

Also, I was thinking maybe instead of having it be a member function, I should just use shuffle in the cpp file that contains main. Would this work? Could I use the same basic format of the shuffle I have now?

>>but feel that would cause me to change a lot of code

Oh yea -- one line is a lot of code to change.

Yep you guys were right. That random_shuffle() algorithm did the trick. Thanks a bunch. I got it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.