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
本文探讨了在Robocode中如何有效控制雷达扫描,避免无谓的全范围扫掠,提高战斗效率。通过创建一个信息更新类和敌人集合类,利用时间差判断何时更新雷达方向。在初始化时设置事件处理程序,并利用数学方法确定雷达转向,确保覆盖战场盲区。这种方法适用于AdvancedRobot,可以优化雷达扫描角度,减少遗漏敌人。
1034

被折叠的 条评论
为什么被折叠?



