gpt4 book ai didi

c++ - 控制台和 GUI 的通用设计

转载 作者:可可西里 更新时间:2023-11-01 15:13:02 26 4
gpt4 key购买 nike

为了自己的乐趣和训练,我正在设计一个小游戏。游戏的真实身份与我的实际问题无关,假设它是 Mastermind游戏(实际上是:)

我在这里的真正目标是拥有一个界面 IPlayer ,它将用于任何播放器:计算机或人类、控制台或 gui、本地或网络。我还打算拥有一个 GameController,它将只处理两个 IPlayer

IPlayer 界面看起来像这样:

class IPlayer
{
public:
//dtor
virtual ~IPlayer()
{
}
//call this function before the game starts. In subclasses,
//the overriders can, for example, generate and store the combination.
virtual void PrepareForNewGame() = 0;
//make the current guess
virtual Combination MakeAGuess() = 0;
//return false if lie is detected.
virtual bool ProcessResult(Combination const &, Result const &) = 0;
//Answer to opponent's guess
virtual Result AnswerToOpponentsGuess(Combination const&) = 0;
};

GameController 类会做这样的事情:

IPlayer* pPlayer1 = PlayerFactory::CreateHumanPlayer();
IPlayer* pPlayer1 = PlayerFactory::CreateCPUPlayer();

pPlayer1->PrepareForNewGame();
pPlayer2->PrepareForNewGame();

while(no_winner)
{
Guess g = pPlayer1->MakeAguess();
Result r = pPlayer2->AnswerToOpponentsGuess(g);
bool player2HasLied = ! pPlayer1->ProcessResult(g, r);
etc.
etc.
}

通过这种设计,我愿意让GameController类不可变,也就是说,我只把游戏规则塞进去,没有别的,所以既然游戏本身已经建立,这个类就应该不会改变。对于主机游戏来说,这种设计会很完美。我会有 HumanPlayer,它在其 MakeAGuess 方法中将从标准输入读取一个 Combination,以及一个 CPUPlayer ,这会以某种方式随机生成它等。

现在我的问题是:IPlayer 接口(interface)和 GameController 类在本质上是同步的。我无法想象当 GUIHumanPlayerMakeAGuess 方法必须等待时,我将如何使用相同的 GameController 实现游戏的 GUI 变体例如,一些鼠标移动和点击。当然,我可以启动一个等待用户输入的新线程,而主线程会阻塞,以模仿同步 IO,但不知何故,这个想法让我感到厌恶。或者,我可以将 Controller 和播放器都设计为异步的。在这种情况下,对于主机游戏,我将不得不模仿异步性,这似乎比第一个版本更容易。

您能否评论一下我的设计以及我对选择同步或异步设计的顾虑?另外,我觉得我把更多的责任放在了玩家类上,而不是 GameController 类。等等等等

非常感谢您。

附言我不喜欢我的问题的标题。随意编辑它:)

最佳答案

与其使用各种 IPlayer 方法的返回值,不如考虑为 IPlayer 对象引入一个观察者类,如下所示:

class IPlayerObserver
{
public:
virtual ~IPlayerObserver() { }
virtual void guessMade( Combination c ) = 0;
// ...
};

class IPlayer
{
public:
virtual ~IPlayer() { }
virtual void setObserver( IPlayerObserver *observer ) = 0;
// ...
};

IPlayer 的方法应该调用已安装的 IPlayerObserver 的适当方法,而不是返回一个值,如:

void HumanPlayer::makeAGuess() {
// get input from human
Combination c;
c = ...;
m_observer->guessMade( c );
}

然后,您的 GameController 类可以实现 IPlayerObserver,以便在玩家做了一些有趣的事情(例如猜测)时它会收到通知。

在这种设计下,如果所有的 IPlayer 方法都是异步的就完全没问题了。事实上,这是意料之中的——它们都返回 void!。您的游戏 Controller 在事件玩家上调用 makeAGuess(这可能会立即计算结果,或者它可能会为多人游戏做一些网络 IO,或者它会等待 GUI 做一些事情)并且每当玩家做了他的选择,游戏 Controller 可以放心 guessMade 方法将被调用。此外,玩家对象仍然对游戏 Controller 一无所知。他们只是在处理一个不透明的“IPlayerObserver”界面。

关于c++ - 控制台和 GUI 的通用设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5219743/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com