我正在开发一个面向对象的tic tac toe游戏,我遇到了问题。我的一个类充当游戏的主控制器并控制所有其他对象。下面是该类的剥离版本。
最终用户可以选择一到两个玩家。因此,我没有必要创建第二个玩家和一个ai玩家。游戏只需要一个或另一个。正如您在下面看到的,我尝试使用if语句来解决问题,但是对象没有范围。
如何根据传递给Game构造函数的玩家数量初始化一个或另一个对象?
谢谢!
Game.h
#include "Player.h"
#include "AIPlayer.h"
class Game
{
private:
Player human;
// I would like to put these here so they have scope
// but it is unecessary to declare them both
// If the user chooses one player then human2 is unecessary
// if the user choosed two player then ai is unecessary
AIPlayer ai;
Player human2;
public:
Game(int players)
{
if (players == 1)
{
AIPlayer ai; // this does not have scope
}
else
{
Player human2; // this does not have scope
}
}
};
答案 0 :(得分:6)
我的建议是从公共基类(例如,Player)派生AIPlayer和Player(或者更好的HumanPlayer),并在Game中有一个指向该基类的指针。然后构造函数实例化AIPlayer或HumanPlayer并将其分配给指针。
AIPlayer和HumanPlayer之间不同的任何方法都应该在基类Player中声明为虚方法,然后在派生类中实现。
答案 1 :(得分:1)
您可能想要做的是指向抽象Player
超类作为游戏成员的指针,并将其分配给new AIPlayer
或new HumanPlayer
,具体取决于播放器。
类似的东西:
#include "Player.h"
#include "AIPlayer.h"
#include "HumanPlayer.h"
class Game
{
private:
Player* other_player;
public:
Game(int players)
{
if (players == 1)
{
other_player = new AIPlayer;
}
else
{
other_player = new HumanPlayer;
}
}
};
答案 2 :(得分:1)
你应该为Player和AIPlayer创建一个(抽象)基类,例如:
abstract class Player
{
virtual void MakeMove(GameBoard& b);
}
class HumanPlayer : public Player
{...}
class AIPlayer : public Player
{...}
然后在游戏中,你可以简单地存储两个Player实例。
答案 3 :(得分:1)
类继承是一个很好的解决方案。你创建一个基类并从中派生出其他玩家,如下所示:
class Player{
virtual int move(int)=0;
}
class AIPlayer: Player{
virtual int move(int);
}
class HumanPlayer: Player{
virtual int move(int);
}
答案 4 :(得分:1)
你对这里的“范围”有一点误解。类声明不是范围 - 它只是支持该类的数据和函数的声明。范围存在于函数内部。
class A
{
int a;
};
a
是A
的成员,但由于它从未被实例化,因此它不属于任何范围。
void func()
{
A a;
}
func
具有已定义的范围,a
是其中的一部分。当func
结束时,a
超出范围并被销毁。
现在,问题:解决问题的最简单方法是使用继承。它将阻止您在整个代码中进行各种条件检查,以确定哪些对象有效,哪些对象无效。一个例子如下:
class Player
{
public:
virtual void Move() = 0; // pure virutal function
};
class HumanPlayer()
{
public:
...
virtual void Move() { ... }
};
class AIPlayer()
{
public:
...
virtual void Move() { ... }
};
class Game
{
public:
Game(unsigned int humanPlayerCount = 0)
{
if (humanPlayerCount == 0)
{
m_player1.reset(new AIPlayer());
m_player2.reset(new AIPlayer());
}
else if (humanPlayerCount == 1)
{
m_player1.reset(new HumanPlayer());
m_player2.reset(new AIPlayer());
}
else // assume it is 2
{
m_player1.reset(new HumanPlayer());
m_player2.reset(new HumanPlayer());
}
}
...
private:
std::unique_ptr<Player> m_player1;
std::unique_ptr<Player> m_player2;
};
构造完成后,你会对它们进行同样的处理(从Game
的观点来看它们之间没有区别。)
答案 5 :(得分:0)
你无法做你想做的事。 您的问题的解决方案是使用继承。 创建一个没有任何这两个字段的基类,然后创建2个派生类,并在每个字段中放置一个字段。
答案 6 :(得分:0)
正如您所发现的那样,您不能使用 if 语句,因为if语句是在运行时执行的,但是必须在编译时确定类的成员。 / p>
这给你留下了其他几个选择:
您可以随时声明两个人类玩家对象和一个AIPlayer对象,并在任何特定游戏中保留一个未使用的对象。 (这就是我要做的事,除非这样做会产生巨大的开销,因为这是最简单的方法)
您可以声明指向所有三个对象的指针,然后使用new运算符动态分配您想要使用的对象。 (完成后,请务必使用删除来取消分配)
你可以创建Game的几个子类(例如OnePlayerGame和TwoPlayerGame),这样子类就有你需要的额外对象(例如Game只声明了human1,OnePlayerGame添加了ai,而TwoPlayerGame添加了human2)
答案 7 :(得分:0)
模板怎么样? 创建对象时选择类型(AIPlayer或播放器)