深入理解整个比赛的执行流程
前面的一系列文章分别为大家讲解了博客园仿真足球竞赛平台的各个部分的功能和原理。在这篇文章中,我将把综合先前讲解的内容,将整个比赛平台的内部执行流程展现给大家。
咱们可以通过阅读下面的平台代码了解比赛平台的内部执行流程
/// <summary>
/// 让比赛平台执行一个仿真周期
/// </summary>
public void RunOneCycle()
{
//比赛周期数+1
_gameState.CurrentTime++;
//判断比赛是否结束
if (_gameState.CurrentTime >= _gameState.EndTime)
{
_gameState.IsEnd = true;
//给球队发送比赛结束的信息
Communicator.Instance.SentGameOverToTeams();
return;
}
//判断是否进球,如果进球,重新开球
if (_wm.ball.State != BallState.Normal)
{
//左队进球
if (_wm.ball.State == BallState.LeftGoal)
{
//左队得分加1
_gameState.LeftSorce++;
//右队重新开球
_wm.KickOff(TeamIndex.Right);
}
//右队进球
else if (_wm.ball.State == BallState.RightGoal)
{
//右队得分加1
_gameState.RightSorce++;
//左队重新开球
_wm.KickOff(TeamIndex.Left);
}
}
//将场上的信息(WorldModel)发送给2个球队
//这里发送给右边球队的WorldModel会自动进行转化,使右边的球员认为自己也是左边的队伍
//这么做的好处是编写球队的时候不需要考虑左右边的情况,只需要认为自己是左边的队伍即可。
Communicator.Instance.SentWorldModelToTeams(_wm);
/**********************************************
* *
* 这个时候球队接收到了平台发送过来的场上信息,*
* 并开始思考,本周期应该执行什么命令。 *
* *
***********************************************/
//接收球队的命令决策
//如果某个球队的思考时间超时(球队的思考时间在“比赛设置”中设置),则忽略这个超时的球队,并认为他本周期不执行任何命令
Command[] teamsCommands = Communicator.Instance.GetCommandsFromTeams();
//执行2支球队的命令,更新场上的信息(WorldModel)
for (int i = 0; i < teamsCommands.Length; i++)
{
ICommand command = CommandFactory.GetCommand(commands[i].CType);
//更新球员的信息
wm.agents[i].Success = command.Perform(wm, commands[i], i);
}
//更新足球的信息
wm.ball.DoMove();
}
这里有3个地方需要注意:
- 平台会自动转化发送给右边球队的场上信息,使得他的思考和自己在左边的队伍一致。所以说,我们编写代码的时候,可以始终认为自己是左边的球队。
- 平台将场上的信息发送给球队以后,会开始计时(在“比赛设置”中的“球员思考时间”),如果某个球队的思考超时,则本周期服务器将不会等待,直接认为这个球队本周期的所有球队都执行Stay的命令。
- 更新球员信息的command.Perform函数和更新足球信息ball.DoMove函数的实现在上一篇文章有介绍。
以上就是博客园仿真足球竞赛平台的内部执行流程。
在下一篇文章中,我们将讲解最快截球的设计和实现。