我正在为我的C ++类编写一个基于texbased的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;
}
}
};
Runner.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");
}
答案 0 :(得分:2)
什么是“省略的作业”?如果他们解决非法指数,那就可以做到。
我也没有看到你在任何地方初始化坐标。你可能认为你可以免费获得,比如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;
管理以使导航“可玩”。它到达Alchemist Lab,很好:
<强> 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.
...
如您所见,您需要处理输入循环并检测文件结尾:)