0

Visual studio said I got no issue but, every time I try to run my code I get an assertion failure error, and the error says that vector subscript is out of range, what should I do to fix this, I dont really know what I am doing wrong.

#include <iostream>
#include <ctime>
#include <windows.h>
#include <conio.h>
#include <vector>
using std::cin;
using std::cout;
using std::endl;

class Human
{
private:
    int ap;
    int hp;
public:
    Human()
    {
        srand(time(NULL));
        ap = rand() % 3 + 8;
        hp = rand() % 2 + 9;
    }
    int getAp() { return ap; }
    int getHp() { return hp; }
    void dmg(int x) { hp -= x; }
    
};

class Skeleton
{
private:
    int ap;
    int hp;
public:
    Skeleton()
    {
        srand(time(NULL));
        ap = rand() % 3 + 3;
        hp = rand() % 2 + 4;
    }
    int getAp() { return ap; }
    int getHp() { return hp; }
    void dmg(int x) { hp -= x; }

};

class game
{
private:
    std::vector<Human*> hum;
    std::vector<Skeleton*> ske;
    bool adv;
    int sC;
    int hC;
public:
    game(int h, int s)
    {
        srand(time(NULL));
        adv = rand() % 2;
        sC = s;
        hC = h;
        for (int i = 0; i < h; i++) { hum.push_back( new Human()); }
        for (int i = 0; i < h; i++) { ske.push_back(new Skeleton()); }
    }
    ~game()
    {
        for (int i = 0; i < hum.size(); i++)
        {
            Human* current = hum.back();
            hum.pop_back();
            delete current;
        }
        for (int i = 0; i < ske.size(); i++)
        {
            Skeleton* current = ske.back();
            ske.pop_back();
            delete current;
        }
    }
    void start()
    {
        
        int x = hC-1;
        int y = sC-1;
        bool quit = false;
        while (!quit)
        {
            if (adv)
            {
                ske[y]->dmg(hum[x]->getAp());
                if (ske[y]->getHp() <= 0) { y--; ske.pop_back();}
                adv = 0;
            }
            if (!adv)
            {
                hum[x]->dmg(ske[y]->getAp());
                if (hum[x]->getHp() <= 0) { x--; hum.pop_back(); }
                adv = 1;
            }
            if (hum.size() == 0 || ske.size() == 0)
            {
                cout << "human left : " << hum.size() << "skeleton left : " << ske.size();
                quit = true;
            }
        }
    }
};

int main()
{
    game g1(10, 5);
    g1.start();

    return 0;
}

I always get this error box.

this is the error message i got no idea what are they talkin about.

I also get this, what is this?

this

ive fixed it thx to all of ur comments, this is the completed code, it may look like garbage but it runs

#include <iostream>
#include <ctime>
#include <windows.h>
#include <conio.h>
#include <vector>
using std::cin;
using std::cout;
using std::endl;

class Human
{
private:
    int ap;
    int hp;
public:
    Human()
    {
        ap = rand() % 3 + 8;
        hp = rand() % 2 + 9;
    }
    int getAp() { return ap; }
    int getHp() { return hp; }
    void dmg(int x) { hp -= x; }
    
};

class Skeleton
{
private:
    int ap;
    int hp;
public:
    Skeleton()
    {
        ap = rand() % 3 + 3;
        hp = rand() % 2 + 4;
    }
    int getAp() { return ap; }
    int getHp() { return hp; }
    void dmg(int x) { hp -= x; }

};

class game
{
private:
    std::vector<Human*> hum;
    std::vector<Skeleton*> ske;
    bool adv;
    int sC;
    int hC;
public:
    game(int h, int s)
    {
        srand(time(NULL));
        adv = rand() % 2;
        sC = s;
        hC = h;
        for (int i = 0; i < h; i++) { hum.push_back( new Human()); }
        for (int i = 0; i < s; i++) { ske.push_back(new Skeleton()); }
    }
    ~game()
    {
        for (int i = 0; i < hum.size(); i++)
        {
            Human* current = hum.back();
            hum.pop_back();
            delete current;
        }
        for (int i = 0; i < ske.size(); i++)
        {
            Skeleton* current = ske.back();
            ske.pop_back();
            delete current;
        }
    }
    void start()
    {
        
        int x = hum.size()-1;
        int y = ske.size()-1;
        bool quit = false;
        while (!quit)
        {
            if (hum.size() == 0 || ske.size() == 0)
            {
                cout << "human left : " << hum.size() << "skeleton left : " << ske.size();
                quit = true;
                break;
            }
            if (adv)
            {
                ske.at(y)->dmg(hum.at(x)->getAp());
                if (ske.at(y)->getHp() <= 0) { y--; ske.pop_back();}
                adv = 0;
            }
            else if (!adv)
            {
                hum.at(x)->dmg(ske.at(y)->getAp());
                if (hum.at(x)->getHp() <= 0) { x--; hum.pop_back(); }
                adv = 1;
            }
            
        }
    }
};

int main()
{
    game g1(8, 20);
    g1.start();

    return 0;
}
Jahnavi Paliwal
  • 1,721
  • 1
  • 12
  • 20
tbsnsa
  • 29
  • 6
  • Unrelated to your problem, but you should call `srand` only *once* in your program. – Some programmer dude Jul 28 '21 at 07:58
  • Use the debugger to stop exactly when this happens and observe the variables etc. Also naming variables better would help you and others to understand the code. hC, y, etc don’t say anything about what they are – Sami Kuhmonen Jul 28 '21 at 08:00
  • As for your problem, why do you need the `hC` and `sC` variables in the `game` class? Isn't the vector sizes enough? Especially since you use the wrong variables when creating your skeletons. – Some programmer dude Jul 28 '21 at 08:00
  • You're also leaking memory, do your vectors need to be of pointers? The error itself likely means you've tried to access either hum or ske with an index they don't have - maybe -1? The easiest thing to do might be to read up a bit on using visual studio's debugger. – George Jul 28 '21 at 08:03
  • You need to check `x` and `y` 's values before using them as indexes. It would be much better to use iterators here. Your crash is caused by y's value become negative. – prehistoricpenguin Jul 28 '21 at 08:07
  • Why write a destructor at all? Use `unique_ptr` instead of raw pointers and they will delete the objects automatically. That being said, if you insist on deleting them yourself, you should look at the [Rule of three](https://en.cppreference.com/w/cpp/language/rule_of_three) – IWonderWhatThisAPIDoes Jul 28 '21 at 08:08
  • the simple way to find the bug is to replace all element access via `[]` with element access via `at()`, you will then get an informative error message – 463035818_is_not_an_ai Jul 28 '21 at 08:09
  • You instantiate h skeletons, not s. – SR_ Jul 28 '21 at 08:17
  • When last skeleton dies, you try to hit a human with a non-existing skeleton. – SR_ Jul 28 '21 at 08:24
  • btw you don't need to pop from the vectors in the destructor. Calling `delete` on the elements is sufficient. The vector already cleans up after itself in its destructor – 463035818_is_not_an_ai Jul 28 '21 at 08:29
  • @-SR_ and everyone, i finally run it, im really grateful for all ur advice, thank you, ive corrected all of the things u guys mentioned, once again thank you very much – tbsnsa Jul 28 '21 at 08:40
  • i switch the if ske or hum vector size == 0 to the top and now it runs – tbsnsa Jul 28 '21 at 08:41
  • Then you may paste the latest code here, it can be improved in variety of ways. – prehistoricpenguin Jul 28 '21 at 08:42
  • @prehistoricpenguin ive posted the new code, i believe its still looks untidy and unprofessional. – tbsnsa Jul 28 '21 at 08:48
  • please do not add the corrected code in the question. Questions are for the questions and the broken code. If you like you can answer your own question, but answering in the question makes the question rather pointless – 463035818_is_not_an_ai Jul 28 '21 at 09:13
  • @463035818_is_not_a_number sorry im new to ask a question in stackoverflow i didnt kno where to post the corrected code – tbsnsa Jul 29 '21 at 04:07
  • Welcome @tbsnsa! In future questions if you can, please send the error messages as text instead of images. Thank you! – CausingUnderflowsEverywhere Jul 29 '21 at 04:21

2 Answers2

0

In function start, ske[y] is accessed with a negative index. std::vector does not like negative indexes, this needs to be fixed.

ScaledLizard
  • 171
  • 1
  • 9
0

Your final code is somewhat complex than it should be, I have simplified it by:

  • Remove the windows related header files, they are not used
  • Use member initializer lists
  • Modify dmg to return the latest hp
  • Remove the unnecessary index in start, to use back
  • Remove the vector of pointers, it's Ok to use objects here
  • Move the srand call into main(Actually we can use std::random here)
  • Simplify the while loop in start
#include <ctime>
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;

class Human {
 private:
  int ap;
  int hp;

 public:
  Human() : ap(rand() % 3 + 8), hp(rand() % 2 + 9) {}
  int getAp() { return ap; }
  int getHp() { return hp; }
  int dmg(int x) { return hp -= x; }
};

class Skeleton {
 private:
  int ap;
  int hp;

 public:
  Skeleton() : ap(rand() % 3 + 3), hp(rand() % 2 + 4) {}
  int getAp() { return ap; }
  int getHp() { return hp; }
  int dmg(int x) { return hp -= x; }
};

class game {
 private:
  bool adv;
  int sC;
  int hC;
  std::vector<Human> hum;
  std::vector<Skeleton> ske;

 public:
  game(int h, int s) : adv(rand() % 2), sC(s), hC(h), hum(h), ske(s) {}

  void start() {
    while (!hum.empty() && !ske.empty()) {
      if (adv) {
        if (ske.back().dmg(hum.back().getAp()) <= 0) {
          ske.pop_back();
        }
      } else {
        if (hum.back().dmg(ske.back().getAp()) <= 0) {
          hum.pop_back();
        }
      }
      adv = !adv;
    }
    cout << "human left : " << hum.size() << ", skeleton left : " << ske.size();
  }
};

int main() {
  srand(time(NULL));
  game g1(8, 20);
  g1.start();

  return 0;
}

Online demo

prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42
  • a question, why i shouldnt use pointer for this? – tbsnsa Jul 28 '21 at 10:56
  • @tbsnsa Short answer: use vector of objects here is the most cache efficient way, all the elements in vectors have nearby addresses. If you use to store the addresses of heap objects, the addresses of the objects are mostly dispersed. Long version: https://stackoverflow.com/a/22146244/1292791 – prehistoricpenguin Jul 28 '21 at 14:38