(C ++)未处理的异常-无效的vector <t>下标

时间:2019-12-12 04:11:04

标签: c++

我在代码中遇到此错误,程序在崩溃之前将运行一小段时间,然后将我定向到operator []函数,该函数在其中显示带有“无效向量下标”的Index_out_of_bounds。如果我继续阅读它,还可以通过计数器之一的if语句告诉我out_of_bounds。

这是以下代码:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
using namespace std;


const int X_SIZE = 20;
const int Y_SIZE = 20;
const float SQUARE_PIXELS = 20.0;

class Index_out_of_bounds {};

const int NUMBER_OF_ANTS = 100;
const int NUMBER_OF_DOODLEBUGS = 5;

enum Tile_type { EMPTY, ANTS, DOODLEBUGS, NUMBER_OF_TILES };
enum Direction { UP, DOWN, LEFT, RIGHT, NUMBER_OF_DIRECTIONS };

class World;
class Tile;
class Organism;
class Ants;
class Doodlebugs;
class Empty;

class Tile
{
public:
    Tile() : x(0), y(0), shape() {  }
    Tile(int x = 0, int y = 0, float radius = SQUARE_PIXELS, size_t point_count = 30) : x(x), y(y), shape(radius, point_count) { }
    virtual void display(sf::RenderWindow& window) = 0;
    static void tile_swap(Tile*& pTile1, Tile*& pTile2);
    virtual Tile_type who() = 0;
    virtual void move(World& w);
protected:
    int x;
    int y;
    sf::CircleShape shape;
    void fix_shape_position();
};


class Organism : public Tile
{

public:
    Organism(int x = 0, int y = 0) : Tile(x, y, (SQUARE_PIXELS - 2) / 2, 30)
    {
        shape.setPosition(sf::Vector2f(x * SQUARE_PIXELS, y * SQUARE_PIXELS));
    }
    void display(sf::RenderWindow& window) = 0;
    //virtual Empty* starve(int x, int y);
private:
};

class Ants : public Organism
{
public:
    Ants(int x = 0, int y = 0) : Organism(x, y)
    {
        shape.setFillColor(sf::Color::Green);
    }
    void display(sf::RenderWindow& window)
    {
        window.draw(shape);
    }
    virtual Tile_type who() { return ANTS; }
    void move(World& w);
    Ants* breed(int x, int y);
private:
    unsigned int ANTS_COUNTER = 3;
};


class Doodlebugs : public Organism
{
public:
    Doodlebugs(int x = 0, int y = 0) : Organism(x, y)
    {
        shape.setFillColor(sf::Color::Red);
    }
    void display(sf::RenderWindow& window)
    {
        window.draw(shape);
    }
    virtual Tile_type who() { return DOODLEBUGS; }
    void move(World& w);
    Empty* starve(int x, int y);
    Doodlebugs* breed(int x, int y);
private:
    int DOODLEBUGS_COUNTER = 8;
    int STARVATION_COUNTER = 30;
};

class Empty : public Tile
{
public:
    //Empty() : Tile(0, 0) { cout << "Calling default Empty constructor." << endl; }
    Empty(int x = 0, int y = 0) : Tile(x, y, (SQUARE_PIXELS - 2) / 2, 4)
    {
        shape.setFillColor(sf::Color(rand() % 256, rand() % 256, rand() % 256, 255));
        //tell the shape where it lives START HERE
        shape.setPosition(sf::Vector2f(x * SQUARE_PIXELS, y * SQUARE_PIXELS));
    }
    void display(sf::RenderWindow& window)
    {
        //window.draw(shape);
    }
    virtual Tile_type who() { return EMPTY; }

};

class World
{
public:
    World(int x = X_SIZE, int y = Y_SIZE, int ants = NUMBER_OF_ANTS, int doodlebugs = NUMBER_OF_DOODLEBUGS);
    ~World();
    //write the big 5
    void display(sf::RenderWindow& window);
    void run_simulation();
    void move();
    vector<Tile*>& operator[](int index);
    const vector<Tile*>& operator[](int index) const;

private:
    vector<vector<Tile*>> grid;
};

Main.cpp

#include "main.h"


int main()
{
    srand(time(0));
    World world;
    world.run_simulation();
}


World::World(int x, int y, int ants, int doodlebugs)
{
    vector<Tile*> column(y);
    for (int i = 0; i < x; i++)
    {
        grid.push_back(column);
    }

    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
        {
            if (ants > 0)
            {
                grid[i][j] = new Ants(i, j);
                ants--;
            }
            else if (doodlebugs > 0)
            {
                grid[i][j] = new Doodlebugs(i, j);
                doodlebugs--;
            }
            else
            {
                grid[i][j] = new Empty(i, j);
            }
        }
    }

    int x1, x2;
    int y1, y2;
    for (int i = 0; i < 100000; i++)
    {
        x1 = rand() % x;
        x2 = rand() % x;
        y1 = rand() % y;
        y2 = rand() % y;
        Tile::tile_swap(grid[x1][y1], grid[x2][y2]);
    }
}

World::~World()
{
    for (int i = 0; i < grid.size(); i++)
    {
        for (int j = 0; j < grid[i].size(); j++)
        {
            delete grid[i][j];
        }
    }
}

void World::display(sf::RenderWindow& window)
{
    for (int i = 0; i < grid.size(); i++)
    {
        for (int j = 0; j < grid[i].size(); j++)
        {
            grid[i][j]->display(window);
        }
    }
}

void World::move()
{
    vector<Tile*> doodlebugs;
    for (int i = 0; i < grid.size(); i++)
    {
        for (int j = 0; j < grid[i].size(); j++)
        {
            if (grid[i][j]->who() == DOODLEBUGS)
            {
                doodlebugs.push_back(grid[i][j]);
            }
        }
    }

    for (auto doodlebugs : doodlebugs)
    {
        doodlebugs->move(*this);
    }

    vector<Tile*> ants;
    for (int i = 0; i < grid.size(); i++)
    {
        for (int j = 0; j < grid[i].size(); j++)
        {
            if (grid[i][j]->who() == ANTS)
            {
                ants.push_back(grid[i][j]);
            }
        }
    }

    for (auto ants : ants)
    {
        ants->move(*this);
    }


}

void World::run_simulation()
{
    sf::RenderWindow window(sf::VideoMode(400, 400), "ANTS VS DOODLEBUGS");
    int count = 0;
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            //cout << event.type << endl;
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Enter))
            {
                window.clear();
                count++;
                if (count == 2)
                {
                    move();
                    count = 0;
                }
                display(window);
                window.display();
                sf::sleep(sf::milliseconds(100));
            }
        }
        //sf::sleep(sf::milliseconds(33));
        window.clear();
        display(window);
        //shape.move(sf::Vector2f(rand()%3 -1, rand()%3 - 1));
        //shape.rotate(1);
        //window.draw(shape);
        window.display();
    }
}

void Tile::tile_swap(Tile*& pTile1, Tile*& pTile2)
{
    swap(pTile1->x, pTile2->x);
    swap(pTile1->y, pTile2->y);
    swap(pTile1, pTile2);
    pTile1->fix_shape_position();
    pTile2->fix_shape_position();
}

void Tile::fix_shape_position()
{
    shape.setPosition(sf::Vector2f(x * SQUARE_PIXELS, y * SQUARE_PIXELS));
}

//default move statement for organisms
void Tile::move(World& w)
{
    switch (rand() % NUMBER_OF_DIRECTIONS)
    {
    case UP:
        if (y > 0)
        {
            if (w[x][y - 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y - 1]);
            }
        }
        break;
    case DOWN:
        if (y < Y_SIZE - 1)
        {
            if (w[x][y + 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y + 1]);
            }
        }
        break;
    case LEFT:
        if (x > 0)
        {
            //go left
            if (w[x - 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x - 1][y]);
            }
        }
        break;
    case RIGHT:
        if (x < X_SIZE - 1)
        {
            if (w[x + 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x + 1][y]);
            }
        }
        break;
    }

}


Empty* Doodlebugs::starve(int x, int y)
{
    return new Empty(x, y);
}


//move statement for ants
void Ants::move(World& w)
{
    //directions
    switch (rand() % NUMBER_OF_DIRECTIONS)
    {
    case UP:
        if (y > 0)
        {
            if (w[x][y - 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y - 1]);
                ANTS_COUNTER--;
            }
            //once ant has taken 3 or more steps and theres an ant adjacent, breed if theres an empty spot
            else if (ANTS_COUNTER == 0 && (w[x][y - 1]->who() == ANTS ||
                                           w[x - 1][y]->who() == ANTS ||
                                           w[x][y + 1]->who() == ANTS ||
                                           w[x + 1][y]->who() == ANTS))
            {
                ANTS_COUNTER = 3;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    case DOWN:
        if (y < Y_SIZE - 1)
        {
            if (w[x][y + 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y + 1]);
                ANTS_COUNTER--;
            }
            else if (ANTS_COUNTER == 0 && (w[x][y - 1]->who() == ANTS ||
                                           w[x - 1][y]->who() == ANTS ||
                                           w[x][y + 1]->who() == ANTS ||
                                           w[x + 1][y]->who() == ANTS))
            {
                ANTS_COUNTER = 3;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    case LEFT:
        if (x > 0)
        {
            //go left
            if (w[x - 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x - 1][y]);
                ANTS_COUNTER--;
            }
            else if (ANTS_COUNTER == 0 && (w[x][y - 1]->who() == ANTS ||
                                           w[x - 1][y]->who() == ANTS ||
                                           w[x][y + 1]->who() == ANTS ||
                                           w[x + 1][y]->who() == ANTS))
            {
                ANTS_COUNTER = 3;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    case RIGHT:
        if (x < X_SIZE - 1)
        {
            if (w[x + 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x + 1][y]);
                ANTS_COUNTER--;
            }
            else if (ANTS_COUNTER == 0 && (w[x][y - 1]->who() == ANTS ||
                                           w[x - 1][y]->who() == ANTS ||
                                           w[x][y + 1]->who() == ANTS ||
                                           w[x + 1][y]->who() == ANTS))
            {
                ANTS_COUNTER = 3;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    }
}


void Doodlebugs::move(World& w) 
{
    switch (rand() % NUMBER_OF_DIRECTIONS)
    {

    case UP:
        if (y > 0)
        {
            if (STARVATION_COUNTER == 0)
            {
                w[x][y] = starve(x, y);
            }
            else if (w[x][y - 1]->who() == ANTS)
            {
                w[x][y - 1] = new Empty(x, y - 1);
                Tile::tile_swap(w[x][y], w[x][y - 1]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER = 3;
            }
            else if (w[x][y - 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y - 1]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER--;
            }
            if (DOODLEBUGS_COUNTER == 0 && (w[x][y - 1]->who() == DOODLEBUGS ||
                                                 w[x - 1][y]->who() == DOODLEBUGS ||
                                                 w[x][y + 1]->who() == DOODLEBUGS ||
                                                 w[x + 1][y]->who() == DOODLEBUGS))
            {
                DOODLEBUGS_COUNTER = 8;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }

        }
        break;
    case DOWN:
        if (y < Y_SIZE - 1)
        {
            if (STARVATION_COUNTER == 0)
            {
                w[x][y] = starve(x, y);
            }
            else if (w[x][y + 1]->who() == ANTS)
            {
                w[x][y + 1] = new Empty(x, y + 1);
                Tile::tile_swap(w[x][y], w[x][y + 1]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER = 3;
            }
            else if (w[x][y + 1]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x][y + 1]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER--;
            }
            if (DOODLEBUGS_COUNTER == 0 && (w[x][y - 1]->who() == DOODLEBUGS ||
                                                 w[x - 1][y]->who() == DOODLEBUGS ||
                                                 w[x][y + 1]->who() == DOODLEBUGS ||
                                                 w[x + 1][y]->who() == DOODLEBUGS))
            {
                DOODLEBUGS_COUNTER = 8;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    case LEFT:
        if (x > 0)
        {
            //go left
            if (STARVATION_COUNTER == 0)
            {
                w[x][y] = starve(x, y);
            }
            else if (w[x - 1][y]->who() == ANTS)
            {
                w[x][y + 1] = new Empty(x - 1, y);
                Tile::tile_swap(w[x][y], w[x - 1][y]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER = 3;
            }
            else if (w[x - 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x - 1][y]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER--;
            }
            if (DOODLEBUGS_COUNTER == 0 && (w[x][y - 1]->who() == DOODLEBUGS ||
                                                 w[x - 1][y]->who() == DOODLEBUGS ||
                                                 w[x][y + 1]->who() == DOODLEBUGS ||
                                                 w[x + 1][y]->who() == DOODLEBUGS))
            {
                DOODLEBUGS_COUNTER = 8;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x + 1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x - 1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y + 1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y - 1] = breed(x, y - 1);
                }
            }
        }
        break;
    case RIGHT:
        if (x < X_SIZE - 1)
        {
            if (STARVATION_COUNTER == 0)
            {
                w[x][y] = starve(x, y);
            }
            else if (w[x + 1][y]->who() == ANTS)
            {
                w[x + 1][y] = new Empty(x + 1, y);
                Tile::tile_swap(w[x][y], w[x + 1][y]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER = 3;
            }
            else if (w[x + 1][y]->who() == EMPTY)
            {
                Tile::tile_swap(w[x][y], w[x + 1][y]);
                DOODLEBUGS_COUNTER--;
                STARVATION_COUNTER--;

            }
            if (DOODLEBUGS_COUNTER == 0 && (w[x][y - 1]->who() == DOODLEBUGS ||
                                                 w[x - 1][y]->who() == DOODLEBUGS ||
                                                 w[x][y + 1]->who() == DOODLEBUGS ||
                                                 w[x + 1][y]->who() == DOODLEBUGS))
            {
                DOODLEBUGS_COUNTER = 8;
                if ((x < (X_SIZE - 1)) && w[x + 1][y]->who() == EMPTY)
                {
                    w[x+1][y] = breed(x + 1, y);
                }
                else if ((x > 0) && w[x - 1][y]->who() == EMPTY)
                {
                    w[x-1][y] = breed(x - 1, y);
                }
                else if ((y < (Y_SIZE - 1)) && w[x][y + 1]->who() == EMPTY)
                {
                    w[x][y+1] = breed(x, y + 1);
                }
                else if ((y > 0) && w[x][y - 1]->who() == EMPTY)
                {
                    w[x][y-1] = breed(x, y - 1);
                }
            }
        }
        break;
    }

}

Ants* Ants::breed(int x, int y)
{
    return new Ants(x, y);
}

Doodlebugs* Doodlebugs::breed(int x, int y)
{
    return new Doodlebugs(x, y);
}


vector<Tile*>& World::operator[](int index)
{
    if (index >= grid.size())
    {
        throw Index_out_of_bounds();
    }
    return grid.at(index);
}
const vector<Tile*>& World::operator[](int index) const
{
    if (index >= grid.size())
    {
        throw Index_out_of_bounds();
    }
    return grid.at(index);
}

我不确定发生了什么事,这会导致代码在特定时间点后崩溃,这是计数器吗?我该怎么做才能解决此问题?

编辑1:更新了仿真功能,使其更易于调试

0 个答案:

没有答案