Robocode成功的关键之一始终是掌握每个敌方机器人的最新信息。 要做到这一点,您必须以不会扫过更多战场的方式使用雷达。 例如,当您的机器人站在角落时,进行完整的360度扫掠是没有意义的。
本技巧文章讨论了我在et.Predator中用于控制雷达的代码。 假定您的机器人是AdvancedRobot,并且您有一个Enemy
类(一个包含ScannedRobotEvents
信息的类)和一个EnemyMap
类(一个敌人集合)。 我正在使用的EnemyMap
扩展了HashMap
,但您也可以使用Hashtable
或其他合适的类。
Enemy
类必须具有isUpdated()
函数,该函数检查自信息最后一次更新以来的时间getTime()
机器人的getTime()
减去ScannedRobotEvent
getTime()
)是否低于某个限制。 我目前使用16作为限制。
在机械手的初始化部分(在循环之前的run()
)中,使用以下命令:
addCustomEvent(new
RadarTurnCompleteCondition(this));
setAdjustRadarForGunTurn(true);
setTurnRadarRight(360);
接下来,为自定义事件添加事件处理程序:
public void onCustomEvent(CustomEvent e) {
if (e.getCondition() instanceof
RadarTurnCompleteCondition) sweep();
}
您还应该getScannedRobotEvents()
使用getScannedRobotEvents()
以确保记录所有ScannedRobotEvents
。
最后,添加清单1中的代码以控制雷达扫描。 请注意,该代码使用int sign(double n)
方法,该方法返回数字n(-1或1)的符号。 它还使用normalRelativeAngle(double angle)
将输入角度标准化为-180至180度之间的角度。
清单1.雷达扫描方法
private int radarDirection=1;
private void sweep() {
double maxBearingAbs=0, maxBearing=0;
int scannedBots=0;
Iterator iterator = theEnemyMap.values().
iterator();
while(iterator.hasNext()) {
Enemy tmp = (Enemy)iterator.next();
if (tmp!=null && tmp.isUpdated()) {
double bearing=normalRelativeAngle
(getHeading() + tmp.getBearing()
- getRadarHeading());
if (Math.abs(bearing)>maxBearingAbs) {
maxBearingAbs=Math.abs(bearing);
maxBearing=bearing;
}
scannedBots++;
}
}
double radarTurn=180*radarDirection;
if (scannedBots==getOthers())
radarTurn=maxBearing+sign(maxBearing)*22.5;
setTurnRadarRight(radarTurn);
radarDirection=sign(radarTurn);
}
函数sweep()
确定其他机器人的轴承绝对值的最大值。 如果所有机器人都进行了更新,它将使雷达转向具有最大方位的敌人。 如果尚未更新某些机器人,则会将雷达设置为继续沿当前方向扫掠。
请注意,我向扫描添加了22.5度,这是一个安全余量,因为自上次扫描以来机器人已经移动了。 选择22.5作为常数的动机是雷达每帧大约旋转45度。 通过不使用常数,可以计算与最大轴承的机器人之间的距离,并计算正确轴承可以具有的最大值,从而可以改进算法。
翻译自: https://www.ibm.com/developerworks/java/library/j-radar/index.html