c++ - Boost multi_array BOOST_ASSERT 已抛出断点

标签 c++ visual-c++ boost

我正在为我的 C++ 类编写一个基于 tex 的 dungeoncrawler 风格的游戏,我遇到了一个运行时错误,指出 boost assert 触发了一个断点。我使用相同的逻辑在 C# 中创建了一个非常相似的项目,因此我认为这与导致我的问题的特定 C++ 有关。 这是我的代码: ArtoriaClasses.h

#pragma once
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17

#include <iostream>
#include <sstream>
#include <memory>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <ctime>
#include <vector>
#include <fstream>
#include "boost/multi_array.hpp"
#include <cassert>

using namespace std;

//Class representing one tile of the map
class MapTile
{
private:
    int X;
    int Y;
    string message;
    int eventID;
public:
    //Default Constructor
    MapTile()
    {

    }

    //Constructor with minimum arguments
    MapTile(int x, int y)
    {
        X = x;
        Y = y;
        message = "You are unable to go that way.";
        eventID = -1;
    }

    //Constructor with all arguments
    MapTile(int x, int y, string message, int eventID)
    {
        X = x;
        Y = y;
        this->message = message;
        this->eventID = eventID;
    }

    //function to return coords as a vector with 2 elements
    vector<int> getCoords()
    {
        vector<int> coords;
        coords.push_back(X);
        coords.push_back(Y);

        return coords;
    }

    //function to get the message;
    string getMessage()
    {
        return message;
    }

    //function to get the eventID
    int getEventID()
    {
        return eventID;
    }
};
//Class that is the game object itself, is implemented in the main "runner" 
class Artoria
{
private:
    int tempCoordinates[2];
    int coordinates[2];
    Player player;
    Enemy currentEnemy;
    bool activeEnemy;
    //This is what I tried originally but it throws a bad_alloc at runtime
    //when I first try to assign it a value in populateMap()
    //MapTile map[10][10];

    //Trying something for map
    boost::multi_array<MapTile, 2> map2 { boost::extents[10][10] };

    vector<Item> looseItems;
    vector<Weapon> weapons;
    vector<Armor> armors;
    Random randomGen;
    bool playerDied;

public:
    //Default Constructor
    Artoria()
    {
        populateItems();
        populateMap();
        activeEnemy = false;
        startGame();
    }
    //Function that creates the entire map by populating the multidimensional array of MapTile objects
    void populateMap()
    {
        map2[0][0] = MapTile(0, 0, "You cannot go this way.", -1);
        //Omitted additional assignments to save character space
        map2[9][9] = MapTile(9, 9, "You are in the Alchemists' Lab!", 3);

    }
    //Function to evaluate user's input
    string evaluateInput(string userInput)
    {
        boost::algorithm::to_lower(userInput);
        if (userInput == "north")
        {
            if (!activeEnemy)
            {
                //moving south so add one to Y coordinate
                coordinates[1] = (coordinates[1] + 1);
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "south")
        {
            if (!activeEnemy)
            {
                //moving south so subract one from Y coordinate
                coordinates[1] = (coordinates[1] - 1);
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "east")
        {
            if (!activeEnemy)
            {
                //moving east so add 1 to X coordinate
                coordinates[0] = (coordinates[0] + 1);
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "west")
        {
            if (!activeEnemy)
            {
                //moving west so subract 1 from X coordinate
                coordinates[0] = (coordinates[0] - 1);
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "attack")
        {
            if (activeEnemy)
            {
                battleEnemy();
            }
            else
            {
                cout << "There is no enemy attacking you, move around to find enemies." << endl << "Type 'help_me' for detailed instructions." << endl;
            }
        }
        else if (userInput == "stopplayingartoria")
        {
            string ret = quitGame();
            return ret;
        }
        else if (userInput == "help_me")
        {
            stringstream ret;
            ret << "You can move around the map typing the following commands: 'north', 'south', 'east', and 'west'" << endl << "If you encounter an enemy, attack them by typing 'attack' If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
        }
        else
        {
            return "false";
        }
        return "true";
    }

    //Function to generate the message output to the console.
    string genMessage()
    {
        if (!activeEnemy)
        {
            //get the current map tile from the map container
            MapTile currentTile = map2[coordinates[0]][coordinates[1]];
            string message = currentTile.getMessage();
            int eventID = currentTile.getEventID();

            //string variable to fill with return value;
            string retStr;
            //3 different areas each with event id(1-3), event ids are added for additional custom events
            switch (eventID)
            {
            case 1:
                //Dungeon Hallway
                retStr = genDungeonHallway();
                cout << message << endl << retStr;
                break;
            case 2:
                //Crypt
                retStr = genCrypt();
                cout << message << endl << retStr;
                break;
            case 3:
                //Alchemist's Lab
                retStr = genAlchemistsLab();
                cout << message << endl << retStr;
                break;
            case 4:
                retStr = "This appears to be a safe place, nothing can surprise you here, but you will also find nothing here.";
                cout << message << retStr << endl;
                break;
            case -1:
                //player cannot go here so reset his coordinates
                coordinates[0] = tempCoordinates[0];
                coordinates[1] = tempCoordinates[1];
                return message;
            default:
                // Case 0 is just print message(currently unused)
                retStr = message;
                break;
            }
            //set tempCoords to keep track of last tile.
            tempCoordinates[0] = coordinates[0];
            tempCoordinates[1] = coordinates[1];
            return retStr;
        }
    }
};

运行者.cpp

//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17

#include <iostream>
#include <string>
#include <memory>
#include <boost/algorithm/string.hpp>
#include "ArtoriaClasses.h";

using namespace std;

int main()
{
    string userInput;

    cout << "Welcome to the game 'Artoria'. You can start a new game by typing 'new' " << endl << " load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'" << endl;
    getline(cin, userInput);
    boost::algorithm::to_lower(userInput);
    if (userInput == "new")
    {
        Artoria artoriaGame = Artoria();
        while (userInput != "QUIT")
        {
            getline(cin, userInput);
            string ret = artoriaGame.evaluateInput(userInput);
            if (ret == "true")
            {
                cout << artoriaGame.genMessage();
            }
            else if (ret == "false")
            {
                cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
            }
            else if (ret == "QUIT")
            {

            }
        }
    }
    else if (userInput == "load")
    {
        cout << "What is the name you used?" << endl;
        getline(cin, userInput);
        Artoria artoriaGame = Artoria(userInput);
        while (userInput != "QUIT")
        {
            getline(cin, userInput);
            string ret = artoriaGame.evaluateInput(userInput);
            if (ret == "true")
            {
                cout << artoriaGame.genMessage();
            }
            else if (ret == "false")
            {
                cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
            }
            else if (ret == "QUIT")
            {

            }
        }
    }
    else if (userInput == "help_me")
    {
        cout << "Artoria is a text-based dungeon crawler created by Jake Farley. The goal of the game is to get the highest score." << endl;
        cout << "You score points by defeating monsters and picking up items, as you walk around the map you will encounter various enemies and find various items." << endl;
        cout << "As you fight enemies, you will take damage; be warned, there is no way to regain your health. Once your health reaches zero, the game will end." << endl;
        cout << "You can move around the map by typing the four compass directions 'north', 'south', 'east', and 'west'" << endl;
        cout << "If you encounter an enemy, attack them by typing 'attack' you cannot run away from an enemy encounter." << endl;
        cout << "If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
    }
    else
    {
        cout << "Error: Invalid response, closing program." << endl;
    }
    system("pause");
}

最佳答案

什么是“省略的作业”?如果他们解决非法索引,那就可以了。

我也没有看到您在任何地方初始化坐标。您可能认为您可以免费获得它,就像在 C# 中一样?

int tempCoordinates[2] = {0,0};
int coordinates[2] = {0,0};

看起来您没有对运动(向西、向东等)进行任何范围验证,还请查看复制粘贴评论...:)

//moving south so add one to Y coordinate
coordinates[1] = (coordinates[1] + 1);

//moving south so subract one from Y coordinate
coordinates[1] = (coordinates[1] - 1);

//moving east so add 1 to X coordinate
coordinates[0] = (coordinates[0] + 1);

//moving west so subract 1 from X coordinate
coordinates[0] = (coordinates[0] - 1);

建议

抽象一点会更好:

enum { Rows = 10, Columns = 10 };

struct Coords {
    int x = 0, y = 0;

    bool west()  { if (x>0)         { --x; return true; } return false; }
    bool south() { if (y>0)         { --y; return true; } return false; }
    bool east()  { if (x+1<Columns) { ++x; return true; } return false; }
    bool north() { if (y+1<Rows)    { ++y; return true; } return false; }
};
Coords lastCoordinates;
Coords coordinates;

现在您可以使用这些常量了:

boost::multi_array<MapTile, 2> map2 { boost::extents[Columns][Rows] };

并使用它们进行安全操作:

    if (userInput == "north")
    {
        if (!activeEnemy)
        {
            coordinates.north();
        }
     // ...

不再需要评论,更不用说错误的评论:)

使用它:

        MapTile currentTile = map2[coordinates.x][coordinates.y];

或者:

        case -1:
            //player cannot go here so reset his coordinates
            coordinates = lastCoordinates;
            return message;

和:

        //set lastCoordinates to keep track of last tile.
        lastCoordinates = coordinates;

现场演示

设法使导航“可玩”。它到达炼金术士实验室,很好:

Live On Coliru

//#pragma once
//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17
struct Player {
};

struct Enemy {
};

struct Item {
};

struct Weapon {
};

struct Armor {
};


#include <iostream>
#include <sstream>
#include <memory>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <ctime>
#include <vector>
#include <fstream>
#include "boost/multi_array.hpp"
#include <cassert>

using Random = boost::random::mt19937;

using namespace std;

//Class representing one tile of the map
class MapTile
{
private:
    int X;
    int Y;
    string message;
    int eventID;
public:
    //Default Constructor
    MapTile()
    {

    }

    //Constructor with minimum arguments
    MapTile(int x, int y)
    {
        X = x;
        Y = y;
        message = "You are unable to go that way.";
        eventID = -1;
    }

    //Constructor with all arguments
    MapTile(int x, int y, string message, int eventID)
    {
        X = x;
        Y = y;
        this->message = message;
        this->eventID = eventID;
    }

    //function to return coords as a vector with 2 elements
    vector<int> getCoords()
    {
        vector<int> coords;
        coords.push_back(X);
        coords.push_back(Y);

        return coords;
    }

    //function to get the message;
    string getMessage()
    {
        return message;
    }

    //function to get the eventID
    int getEventID()
    {
        return eventID;
    }
};
//Class that is the game object itself, is implemented in the main "runner" 
class Artoria
{
private:
    enum { Rows = 10, Columns = 10 };

    struct Coords {
        int x = 0, y = 0;

        bool west()  { if (x>0)         { --x; return true; } return false; }
        bool south() { if (y>0)         { --y; return true; } return false; }
        bool east()  { if (x+1<Columns) { ++x; return true; } return false; }
        bool north() { if (y+1<Rows)    { ++y; return true; } return false; }
    };
    Coords lastCoordinates;
    Coords coordinates;
    Player player;
    Enemy currentEnemy;
    bool activeEnemy;

    boost::multi_array<MapTile, 2> map2 { boost::extents[Columns][Rows] };

    vector<Item> looseItems;
    vector<Weapon> weapons;
    vector<Armor> armors;
    Random randomGen;
    bool playerDied;

public:
    //Default Constructor
    Artoria(std::string const& /*s*/ = {})
    {
        //populateItems();
        populateMap();
        activeEnemy = false;
        //startGame();
    }
    //Function that creates the entire map by populating the multidimensional array of MapTile objects
    void populateMap()
    {
        map2[0][0] = MapTile(0, 0, "You cannot go this way.", -1);
        //Omitted additional assignments to save character space
        map2[9][9] = MapTile(9, 9, "You are in the Alchemists' Lab!", 3);

    }
    //Function to evaluate user's input
    string evaluateInput(string userInput)
    {
        boost::algorithm::to_lower(userInput);
        if (userInput == "north")
        {
            if (!activeEnemy)
            {
                coordinates.north();
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "south")
        {
            if (!activeEnemy)
            {
                coordinates.south();
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "east")
        {
            if (!activeEnemy)
            {
                coordinates.east();
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "west")
        {
            if (!activeEnemy)
            {
                coordinates.west();
            }
            else
            {
                cout << "You cannot move when there is an enemy attacking you!" << endl << "Type 'Attack' to attack the enemy. Type 'help_me' for detailed instructions." << endl;
                return "false";
            }
        }
        else if (userInput == "attack")
        {
            if (activeEnemy)
            {
                //battleEnemy();
            }
            else
            {
                cout << "There is no enemy attacking you, move around to find enemies." << endl << "Type 'help_me' for detailed instructions." << endl;
            }
        }
        else if (userInput == "stopplayingartoria")
        {
            //string ret = quitGame();
            return "quit";
        }
        else if (userInput == "help_me")
        {
            stringstream ret;
            ret << "You can move around the map typing the following commands: 'north', 'south', 'east', and 'west'" << endl << "If you encounter an enemy, attack them by typing 'attack' If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
        }
        else
        {
            return "false";
        }
        return "true";
    }

    //Function to generate the message output to the console.
    string genMessage()
    {
        if (!activeEnemy)
        {
            //get the current map tile from the map container
            MapTile currentTile = map2[coordinates.x][coordinates.y];
            string message = currentTile.getMessage();
            int eventID = currentTile.getEventID();

            //string variable to fill with return value;
            string retStr;
            //3 different areas each with event id(1-3), event ids are added for additional custom events
            switch (eventID)
            {
            case 1:
                //Dungeon Hallway
                retStr = "genDungeonHallway()";
                cout << message << endl << retStr;
                break;
            case 2:
                //Crypt
                retStr = "genCrypt()";
                cout << message << endl << retStr;
                break;
            case 3:
                //Alchemist's Lab
                retStr = "genAlchemistsLab()";
                cout << message << endl << retStr;
                break;
            case 4:
                retStr = "This appears to be a safe place, nothing can surprise you here, but you will also find nothing here.";
                cout << message << retStr << endl;
                break;
            case -1:
                //player cannot go here so reset his coordinates
                coordinates = lastCoordinates;
                return message;
            default:
                // Case 0 is just print message(currently unused)
                retStr = message;
                break;
            }
            //set lastCoordinates to keep track of last tile.
            lastCoordinates = coordinates;
            return retStr;
        }
    }
};

//Jake Farley
//CSC275
//Artoria (Final)
//11/25/17

#include <iostream>
#include <string>
#include <memory>
#include <boost/algorithm/string.hpp>
//#include "ArtoriaClasses.h";

using namespace std;

int main()
{
    string userInput;

    cout << "Welcome to the game 'Artoria'. You can start a new game by typing 'new' " << endl << " load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'" << endl;
    getline(cin, userInput);
    boost::algorithm::to_lower(userInput);
    if (userInput == "new")
    {
        Artoria artoriaGame = Artoria();
        while (userInput != "QUIT")
        {
            getline(cin, userInput);
            string ret = artoriaGame.evaluateInput(userInput);
            if (ret == "true")
            {
                cout << artoriaGame.genMessage();
            }
            else if (ret == "false")
            {
                cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
            }
            else if (ret == "QUIT")
            {

            }
        }
    }
    else if (userInput == "load")
    {
        cout << "What is the name you used?" << endl;
        getline(cin, userInput);
        Artoria artoriaGame = Artoria(userInput);
        while (userInput != "QUIT")
        {
            getline(cin, userInput);
            string ret = artoriaGame.evaluateInput(userInput);
            if (ret == "true")
            {
                cout << artoriaGame.genMessage();
            }
            else if (ret == "false")
            {
                cout << "You have entered an invalid command. You can type 'help_me' for instructions.";
            }
            else if (ret == "QUIT")
            {

            }
        }
    }
    else if (userInput == "help_me")
    {
        cout << "Artoria is a text-based dungeon crawler created by Jake Farley. The goal of the game is to get the highest score." << endl;
        cout << "You score points by defeating monsters and picking up items, as you walk around the map you will encounter various enemies and find various items." << endl;
        cout << "As you fight enemies, you will take damage; be warned, there is no way to regain your health. Once your health reaches zero, the game will end." << endl;
        cout << "You can move around the map by typing the four compass directions 'north', 'south', 'east', and 'west'" << endl;
        cout << "If you encounter an enemy, attack them by typing 'attack' you cannot run away from an enemy encounter." << endl;
        cout << "If you wish to quit the game, type 'StopPlayingArtoria'" << endl;
    }
    else
    {
        cout << "Error: Invalid response, closing program." << endl;
    }
}

打印

Welcome to the game 'Artoria'. You can start a new game by typing 'new' 
 load an existing save by typing 'load' or view instructions on how to play the game by typing 'help_me'
You cannot go this way.
You are in the Alchemists' Lab!
genAlchemistsLab()
genAlchemistsLab()
You have entered an invalid command. 
You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
You have entered an invalid command. You can type 'help_me' for instructions.
...

如您所见,您需要处理输入循环并检测文件结尾:)

关于c++ - Boost multi_array BOOST_ASSERT 已抛出断点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47841265/

相关文章:

c++ - 如何为匿名命名空间中未引用的本地函数生成警告?

c++ - 如何在 boost 日期时间中忽略周末和假期?

c++ - boost::unordered_multimap 中的等键函数:查询键是否保证是第一个 arg?

python - 多维数组索引C++中的多维数组

c++ - 退出后调试崩溃? (主要返回后)

javascript - NPAPI:修改插件对象的 CSS 属性

c++ - 在 Qt Creator 中禁用编译器警告项目范围(使用 MSVC 时)

c++ - 将 boost lambda 与复合表达式一起使用

c++ - 模板参数修饰符

c++ - std::uninitialized_copy 和 std::copy 之间的区别?