我在代码中遇到此错误,程序在崩溃之前将运行一小段时间,然后将我定向到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:更新了仿真功能,使其更易于调试