虚拟关键字似乎被忽略了 这是我的第一个“大”C++项目,我被卡住了。我试图创建一个简单的ASCII流氓。我有一个角色类,由玩家类和怪物类继承。怪物类由吸血鬼和狼人类继承
在GameSystem类的startName函数中,我将怪物数组的每个元素(应该充满吸血鬼和狼人对象)提交给moveAround函数。吸血鬼、狼人和怪物都有这个功能,但只有怪物移动功能被访问。如果你注意到在下面的代码中,我在Monster类中提供了virtual关键字 这让我觉得我在用子类填充怪物数组时搞砸了。在游戏系统构造器中,我通过随机确定怪物阵列中的特定元素是狼人还是吸血鬼来实现这一点 我使用代码块,在编译方面,我有g++遵循C++11 GameSystem.cpp虚拟关键字似乎被忽略了 这是我的第一个“大”C++项目,我被卡住了。我试图创建一个简单的ASCII流氓。我有一个角色类,由玩家类和怪物类继承。怪物类由吸血鬼和狼人类继承,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,在GameSystem类的startName函数中,我将怪物数组的每个元素(应该充满吸血鬼和狼人对象)提交给moveAround函数。吸血鬼、狼人和怪物都有这个功能,但只有怪物移动功能被访问。如果你注意到在下面的代码中,我在Monster类中提供了virtual关键字 这让我觉得我在用子类填充怪物数组时搞砸了。在游戏系统构造器中,我通过随机确定怪物阵列中的特定元素是狼人还是吸血鬼来实现这一点 我使用代码块,在编译方面,我有g++遵循C++11 GameSystem.cpp #include &l
#include <iostream>
#include <string>
#include "GameSystem.h"
#include "Map.h"
#include "Player.h"
#include "Werewolf.h"
#include "Vampire.h"
#include "conio.h"
#include <cstdio>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <time.h>
GameSystem::GameSystem(string mapName){
srand (time(NULL));
_map.load(mapName);
_map.obtainSpawningLocations(_player.getToken(),_player);
Werewolf werewolf;
Vampire vampire;
for(int i = 0; i < 5; i++){
_spawnValue = rand() % 2; //We generate either 1 or 2
if(_spawnValue==1){
_theMonsters[i] = werewolf;
cout<<"Werewolf"<<endl;
}
else{
_theMonsters[i] = vampire;
cout<<"Vampire"<<endl;
}
_map.obtainSpawningLocations(_theMonsters[i].getToken(),_theMonsters[i]);
}
}
void GameSystem::startGame(){
bool isOver = false;
while(isOver!=true){
_map.print();
movePlayer();
for(int i = 0; i <5; i++){
_theMonsters[i].moveAround(); //prints out Monster.moveAround()
//I need it to print out Vampire.moveAround() and //Werewolf.moveAround
}
}
}
void GameSystem::movePlayer(){
char input;
input = getch();
string clearScreenString(100,'\n'); //Prints out a newLine char 100 times
cout << clearScreenString;
_map.checkMovement(input, _player);
}
char GameSystem::getch(){
char buf=0;
struct termios old={0};
fflush(stdout);
if(tcgetattr(0, &old)<0)
{perror("tcsetattr()");}
old.c_lflag&=~ICANON;
old.c_lflag&=~ECHO;
old.c_cc[VMIN]=1;
old.c_cc[VTIME]=0;
if(tcsetattr(0, TCSANOW, &old)<0)
{perror("tcsetattr ICANON");}
if(read(0,&buf,1)<0)
{perror("read()");}
old.c_lflag|=ICANON;
old.c_lflag|=ECHO;
if(tcsetattr(0, TCSADRAIN, &old)<0)
{perror ("tcsetattr ~ICANON");}
//printf("%c\n",buf);
return buf;
}
Player.h
#pragma once
#include <string>
#include "Character.h"
using namespace std;
class Player : public Character {
public:
Player();
protected:
int _x;
int _y;
char _token = '@';
};
在_theMonsters[i].moveAround()上没有发生虚拟调度。您需要有一个指向monster类型对象的指针数组。事实上,在尝试设置类层次结构的方式中存在很多问题,例如,在派生类中有同名的成员变量。在_theMonsters[i].moveAround()上没有发生虚拟调度。您需要有一个指向monster类型对象的指针数组。事实上,在设置类层次结构的方法中存在很多问题,例如,在派生类中有同名的成员变量。这里有几个问题
怪物::_令牌
,狼人::_令牌
,吸血鬼::_令牌都是不同的变量。一个狼人
对象既有怪物::\u标记
又有狼人::\u标记
Monster\u theMonsters[5]
是由5个Monster
对象组成的数组。它永远不会是吸血鬼或狼人,永远是怪物。由于对象将始终是相同类型的:Monster
,因此不需要执行虚拟调度虚拟分派仅适用于指针和引用。要实现这一点,您需要使用指向
Monster
s:Monster*\u theMonsters[5]
的指针数组。然后你可以像\u theMonsters[i]=new Vampire()
那样填充它。如果这样做,您需要记住在处理完对象后删除对象,或者可以使用智能指针,如std::unique\u ptr
或std::shared\u ptr
而不是原始的Monster*
s。这里有几个问题
怪物::_令牌
,狼人::_令牌
,吸血鬼::_令牌都是不同的变量。一个狼人
对象既有怪物::\u标记
又有狼人::\u标记
Monster\u theMonsters[5]
是由5个Monster
对象组成的数组。它永远不会是吸血鬼或狼人,永远是怪物。由于对象将始终是相同类型的:Monster
,因此不需要执行虚拟调度虚拟分派仅适用于指针和引用。要实现这一点,您需要使用指向
Monster
s:Monster*\u theMonsters[5]
的指针数组。然后你可以像\u theMonsters[i]=new Vampire()
那样填充它。如果你这样做,你需要记住在处理完对象后删除它们,或者你可以使用智能指针,比如std::unique_ptr
或std::shared_ptr
而不是原始的Monster*
s.考虑到你的建议,我把Monster*_monsters指针放到了[5];在游戏系统中。我还修改了GameSystem构造函数中的for循环,使其具有\u monsterPointers[I]=new Werewolf()代码>吸血鬼也是如此。但是,这不允许我在收到此错误时调用obtainspawinglocations
:没有匹配的函数用于调用Map::obtainspawinglocations(char,Monster*&)。我如何减轻这种影响?是创建接受这些参数的非常相似的函数的唯一选项吗?只需像调用\u map一样调用它。获取生成位置(\u theMonsters[i]。getToken(),*\u theMonsters[i])代码>考虑到你的建议,我把怪物*_怪物指针[5];在游戏系统中。我还修改了GameSystem构造函数中的for循环,使其具有\u monsterPointers[I]=new Werewolf()代码>吸血鬼也是如此。但是,这不允许我在收到此错误时调用obtainspawinglocations
:没有匹配的函数用于调用Map::obtainspawinglocations(char,Monster*&)。我如何减轻这种影响?是创建接受这些参数的非常相似的函数的唯一选项吗?只需像调用\u map一样调用它。获取生成位置(\u theMonsters[i]。getToken(),*\u theMonsters[i])谢谢,德克也说过类似的话。我现在的问题是,我的函数“获取繁殖位置”不再适用,因为参数现在不同了。我希望该函数适用于角色类的所有实例。我现在是否必须创建一个函数,它除了接受指针外,还做同样的事情?或者还有其他更干净的工作吗?获取繁殖位置
已经使用了一个字符&
,就多态性而言,这很好。如果切换到使用指针数组,则需要取消对它们的引用以将它们传递到获取繁殖位置:\u map.获取繁殖位置(\u theMonsters[i]->getToken(),*\u theMonsters[i])谢谢,德克也说过类似的话。我现在的问题是,我的函数“获取繁殖位置”不再适用,因为参数现在不同了。伊娃
#include <string>
#include "Character.h"
using namespace std;
Character::Character(){
}
char Character::getToken(){
return _token;
}
void Character::setLocation(int x, int y){
_x = x;
_y = y;
}
void Character::getLocation(int &x, int &y){
x = _x;
y = _y;
}
#pragma once
#include <string>
class Character{
public:
Character();
char getToken();
void setLocation(int x, int y);
void getLocation(int &x, int &y);
protected:
int _x;
int _y;
char _token = '!';
};
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <cstring>
#include <random>
#include <ctime>
#include <tuple>
#include "Map.h"
#include <time.h>
Map::Map(){
srand (time(NULL));
}
void Map::load(string levelName){
ifstream theStream;
theStream.open(levelName);
if(theStream.fail()){
perror(levelName.c_str());
system("PAUSE");
exit(1);
}
string line;
while(getline(theStream, line)){
_mapData.push_back(line);
}
theStream.close();
}
void Map::obtainSpawningLocations(char characterToken,Character &_character){
/*
Below code provides all the possible spawning locations for the player
and stores them in an array of tuples.
*/
tuple<int,int> myTuple[600]; //Hard coded 600 value is messy. Change later
int numberOfSpawnPoints = 0;
int upperLimitForNumberGenerator = 0;
/*
The for loop below records all of the possible spawning locations and stores them in the tuple array
*/
for(int i = 0; i<_mapData.size();i++){
for(int j = 0; j<_mapData[i].size();j++){
if(_mapData[i][j]=='.'){
get<0>(myTuple[numberOfSpawnPoints]) = j;
get<1>(myTuple[numberOfSpawnPoints]) = i;
numberOfSpawnPoints++;
}
}
}
upperLimitForNumberGenerator = numberOfSpawnPoints;
int characterCoordinates = rand()%upperLimitForNumberGenerator;
int xCoordinate = get<0>(myTuple[characterCoordinates]);
int yCoordinate = get<1>(myTuple[characterCoordinates]);
_mapData[yCoordinate][xCoordinate] = characterToken; //Remember y is first and x is second
_character.setLocation(xCoordinate, yCoordinate);
}
void Map::print(){
for(int i=0;i<_mapData.size(); i++){
printf("%s\n", _mapData[i].c_str());
}
printf("\n");
}
void Map::checkMovement(char input, Player &aPlayer){
int x;
int y;
aPlayer.getLocation(x,y);
char aLocation;
switch(input) {
case 'w':
case 'W': //If 1 up from the player token is a '.' then we move him up
//via a different function
//Otherwise we do nothing.
aLocation = returnLocation(x,y-1);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y-1][x] = '@';
aPlayer.setLocation(x,y-1);
}
else
cout<<"Can't go here!"<<endl;
break;
case 'a':
case 'A':
aLocation = returnLocation(x-1,y);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y][x-1] = '@';
aPlayer.setLocation(x-1,y);
}
else
cout<<"Can't go here!"<<endl;
break;
case 's':
case 'S':
aLocation = returnLocation(x,y+1);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y+1][x] = '@';
aPlayer.setLocation(x,y+1);
}
else
cout<<"Can't go here!"<<endl;
break;
case 'd':
case 'D':
aLocation = returnLocation(x+1,y);
if(aLocation == '.'){
_mapData[y][x] = '.';
_mapData[y][x+1] = '@';
aPlayer.setLocation(x+1,y);
}
else
cout<<"Can't go here!"<<endl;
break;
default:
cout<<"Invalid input";
system("PAUSE");
break;
}
}
char Map::returnLocation(int x, int y){
cout<<x<<endl;
cout<<y<<endl;
char aSpot = _mapData[y][x];
return aSpot;
}
#pragma once
#include <vector>
#include <fstream>
#include <string>
#include <tuple>
#include <ctime>
#include <random>
#include "Player.h"
#include "Monster.h"
using namespace std;
class Map
{
public:
Map(); //Constructor
void load(string levelName);
void obtainSpawningLocations(char characterToken, Character &aCharacter);
void checkMovementMonsters(char input, Monster &aMonster);
//void obtainSpawningLocationsForMonsters(char characterToken, Monster aMonster);
void print();
void checkMovement(char input, Player &aPlayer);
void movement(char characterToken);
char returnLocation(int x,int y);
// int numberOfSpawnPoints;
private:
vector <string> _mapData;
Player _player;
Monster _monster;
};
#include <iostream>
#include <string>
#include "Monster.h"
using namespace std;
Monster::Monster(){
}
void Monster::moveAround(){
cout<<"Monster Mash"<<endl;
}
#pragma once
#include <string>
#include "Character.h"
class Monster: public Character{
public:
Monster();
virtual void moveAround();
protected:
char _token = 'M';
int _x;
int _y;
};
#include <iostream>
#include <string>
#include "Werewolf.h"
using namespace std;
Werewolf::Werewolf(){
}
void Werewolf::moveAround(){
cout<<"Werewolf moving around"<<endl;
}
#pragma once
#include <string>
#include "Character.h" //For inheritance/polymorphism
#include "Monster.h"
class Werewolf: public Monster{
public:
Werewolf();
void moveAround();
private:
char _token = 'W';
};
#include <iostream>
#include <string>
#include "Vampire.h"
using namespace std;
Vampire::Vampire(){
}
void Vampire::moveAround(){
cout<<"Vampire moving around"<<endl;
}
#pragma once
#include <string>
#include "Character.h" //For inheritance/polymorphism
#include "Monster.h"
class Vampire: public Monster{
public:
Vampire();
virtual void moveAround();
private:
char _token = 'V';
};
Player::Player(){
}
#pragma once
#include <string>
#include "Character.h"
using namespace std;
class Player : public Character {
public:
Player();
protected:
int _x;
int _y;
char _token = '@';
};
#include <iostream>
#include "GameSystem.h"
using namespace std;
int main()
{
GameSystem gameSystem("LevelOne.txt");
gameSystem.startGame();
return 0;
}
############################################
#..........................................#
#..........................................#
#...........................^..............#
#..........................................#
#......................#...................#
#......................#...................#
#......................#...................#
#............^.........#...................#
#......######..........#..&................#
#......\...............#...................#
#......................#...................#
#..........................................#
#..........................................#
############################################