我正在开发一款游戏并且像我一样理想主义,我想要像人工智能一样对待人类玩家。问题是玩家使用AI意味着它必须是异步的。因此我提出了一个类似这样的解决方案:
interface PlayerOrAI
{
takeTurn();
}
class Game
{
doMove(Move move);
}
Move
类是一个描述玩家移动的类。 (你可以轻松地将一个版本变成没有那个额外类的东西,但我认为这是问题的更容易表示)。
想法是Game类调用播放器或AI的takeTurn()
函数,然后他们思考,当它们完成时,它们创建Move类的实例并通过使用{返回它{1}}功能。
(使用此设计,您必须确保您的AI也异步执行回调,否则您将逐渐向堆栈溢出移动。)
然而,出现的问题是我希望能够检查移动是否来自正确的来源。当然,我可以依靠从这里开始编写“正确”的代码,但我更愿意实际检查一下。我想出了一个使用令牌的解决方案,如下所示。
doMove()
这里的想法是,class Token
{
}
interface PlayerOrAIWithToken
{
takeTurn(Token token);
}
class GameWithToken
{
private Token currentToken;
doMove(Move move, Token token);
}
类会在调用GameWithToken
之前创建一个新的Token
,将其存储在takeTurn()
中,然后将其传递给具有currentToken
的类在致电takeTurn()
时转弯。然后PlayerOrAI
必须将Token
作为makeMove()
的参数。这样GameWithToken
总能验证Move来自正确的玩家。
看起来很完美。如果你问我,有点太完美了。您可以在几乎任何OOP语言中使用它,并且您正在使用已经使用语言的系统来解决问题。然而,我从来没有听说过它,也无法在任何地方找到它。
在为此寻找先例时,我是否只是遗漏了一些东西?我可能正在解决我正在编造的问题吗?还有其他事情在发生吗?或者这只是解决这类问题的一种非常简单而又合理的方法吗?
答案 0 :(得分:0)
不是简单地用“playerNumber” - 参数实现doMove就足够了吗?然后只是排队或从doMove返回一个假的“它不是你的回合”?
为什么两个玩家都必须异步调用并不完全清楚,因为在我看来游戏是基于回合的,因此游戏可以轻松地循环并调用每个玩家的“performMove”方法。做任何计算,执行一个移动然后返回(因此没有像你提到的那样累积到堆栈溢出)。