前言
老板的任务罢了-----解读源码,阐明原理,自定义展示。
源码1
以下为我负责的代码阐明部分,其中的函数均可从robocodeAPI查询,如INDEX方法
package lyx;//为方便做实验从sample的Tracker复制例程到我自己包里,仅作小部分修改
import robocode.HitRobotEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;
import robocode.WinEvent;
import static robocode.util.Utils.normalRelativeAngleDegrees;
import robocode.*;
import java.awt.*;
public class Testor extends AdvancedRobot
{
int count = 0; // 计数器,确切来说是标置
double gunTurnAmt;
String trackName;//为体现追踪特点,会记住扫描到的第一个敌人(冤种)
public void run() {
setBodyColor(new Color(255, 0, 0));//车体颜色稍作更改
setGunColor(new Color(0, 0, 250));
setRadarColor(new Color(0, 250, 0));
setScanColor(Color.blue);
setBulletColor(Color.white);
trackName = null; // 刚开始没有目标,目标名字为null
setAdjustGunForRobotTurn(true); // 炮和身体分离,此外还有setAdjustRadarForGunTurn(true),雷达炮管分离
gunTurnAmt = 15; // 每轮炮管旋转15度
while (true) {//循环体,每次都会来一遍对于cout大小的判断,具体表现为在cout足够大时,一定先左再右
turnGunRight(gunTurnAmt);
count++;
if (count >18) {
trackName =null;//如果超过12了,则会重置目标,再次找一个第一个扫描的敌人为目标,类似饥不择食
}
if (count > 10) {
gunTurnAmt = 30;//在count在3-11之间时,炮管转向为左,超过后以更快速度右转扫描
}
else if (count > 2) {
gunTurnAmt = -20;//右边转完45没找到就左边转,转的快点
}
}
}
public void onScannedRobot(ScannedRobotEvent e) {
if (trackName != null && !e.getName().equals(trackName)) {//有目标且扫描到的不是当前锁定目标则不作理会,选择return
return;
}
if (trackName == null) {//如果没有目标,则令目标名字等于检测到的目标,e.getName 推测为获取检测到的目标名字
trackName = e.getName();
out.println("Tracking " + trackName);
}
// 每次检测目标都会让cout归0,使得下次坦克寻找目标可以让scan线左右晃动快速搜索
count = 0;//重置搜索标志,使scan能有左右扫描找到目标
// 如果目标太远,适当接近目标
if (e.getDistance() > 150) {//这个应该读的扫描瞬间的位置
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading()-getRadarHeading()));//稍后会作该部分解答。
turnGunRight(gunTurnAmt);
turnRight(e.getBearing());//在本函数范围内是车体和雷达的相对角度,范围-180-180度
ahead(e.getDistance() - 140);//保持距离150以内
return;
}//先接近再开火
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));//
turnGunRight(gunTurnAmt);
fire(3);//弹丸大也是一种优势,但目前没考虑弹丸问题,日后会考虑smartfire算法
if (e.getDistance() < 150) {//在150单位范围内根据敌人方位适当进行调整
if (e.getBearing() > -90 && e.getBearing() <= 90) {//这代表敌人前方
back(40);//敌人在前半部分就后退一定距离
} else {
ahead(40);//敌人在屁股后就往前开,也是远离敌人
}
}
scan();
}
public void onHitRobot(HitRobotEvent e) {//撞别的坦克了
trackName = e.getName();//撞击坦克也会设定目标值
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
//Returns the bearing to the robot you hit, relative to your robot's heading, in degrees (-180 <= getBearing() < 180),不同事件中getBearing代表的意义不同
//这个可以认为是炮台先跟车体前方对齐再按着车子的姿态角度转过去,在之前的事件中都是靠雷达发现目标,那个时候e.getBearing() + (getHeading() - getRadarHeading())对应值应该为0
turnGunRight(gunTurnAmt);
fire(3);
back(50);//打完就跑
}
//嘲讽以下(doge)
public void onWin(WinEvent e) {
for (int i = 0; i < 50; i++) {
turnRight(30);
turnLeft(30);
}
}
}
源码2
//为做实验将crazy例程复制一份并稍作修改
package lyx;
import robocode.*;
import java.awt.*;
import static robocode.util.Utils.normalRelativeAngleDegrees;
public class Crazyor2 extends AdvancedRobot {
boolean movingForward;
double amt=0;
public void run() {
// Set colors
setBodyColor(new Color(0, 200, 0));
setGunColor(new Color(0, 150, 50));
setRadarColor(new Color(0, 100, 100));
setBulletColor(new Color(255, 255, 100));
setScanColor(new Color(255, 200, 200));//颜色和原sample中crazy例程一个色
while (true) {
setAhead(40000);
//设置一个大的前进路程,40000,这样以后车子会在一段时间内处于前进或者后退状态
//如果setAhead(40000)在循环之外会存在由于没撞墙撞车进入reverseDirection()重置前进后退路程情况
//所以我选择放死循环里面
movingForward = true;
turnRight(90);//右转90度,在setahead较小时候才会原地转,否则就表现为边走边转
turnLeft(180);
turnRight(180);//setTurnRight(180);
//Sets the robot's body to turn right by degrees when the next execution takes place.
}
}
public void onHitWall(HitWallEvent e) {
reverseDirection();//撞墙则触发转向函数并重置前进的路程,也就是40000
}
public void reverseDirection() {
if (movingForward) {//如果movingforward为true,则前进变后退
setBack(40000);
movingForward = false;
} else {
setAhead(40000);
movingForward = true;
}
}
public void onScannedRobot(ScannedRobotEvent e) {
fire(1);
}
public void onHitRobot(HitRobotEvent e) {
amt=normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
//计算转向角
turnRight(amt);//添加撞车会转过来开炮功能
fire(1);
if (e.isMyFault()) {//这个英文意思是--这是我的错,字面上不好理解具体作用
reverseDirection();
}
}
以上两个例程均有这一行代码
normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()))
getHeading() 与getRadarHeading()
在不同的函数,如onHitRobot-和其他坦克相撞,onScannedRobot-扫描到其他机器人,e.getBearing()返回值具有不同意义:
onHitRobot:
Returns the bearing to the robot you hit, relative to your robot’s heading, in degrees (-180 <= getBearing() < 180),即返回你的机器人正方向,与和你相撞机器人之间的夹角
onScannedRobot:
Returns the bearing to the robot you scanned, relative to your robot’s heading, in degrees (-180 <= getBearing() < 180),返回你的机器人与扫描到的机器人方向之间的夹角
(生怕老板看不懂)
源码1+2
抱着想尝试将两者优点合起来的想法,我把上边的代码放在一起试试,并作适当修改让效果好点
package lyx;
import robocode.HitRobotEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;
import robocode.WinEvent;
import static robocode.util.Utils.normalRelativeAngleDegrees;
import robocode.*;
import java.awt.*;
public class Testor2 extends AdvancedRobot
{
int count = 0;
double gunTurnAmt;
String trackName;
boolean movingForward;
public void run() {
setBodyColor(new Color(255, 0, 0));
setGunColor(new Color(0, 0, 250));
setRadarColor(new Color(0, 250, 0));
setScanColor(Color.blue);
setBulletColor(Color.white);
trackName = null;
setAdjustGunForRobotTurn(true);
gunTurnAmt = 90;
movingForward = true;
while (true) {
setAhead(40000);
turnGunRight(gunTurnAmt);
count++;
turnRight(30);
if (count >18) {
trackName =null;
}
turnLeft(30);
if (count > 10) {
gunTurnAmt = 90;
}
else if (count > 4) {
gunTurnAmt = -90;
}
turnRight(30);
}
}
public void onHitWall(HitWallEvent e){
reverseDirection();
}
public void reverseDirection(){
if (movingForward) {
setBack(40000);
movingForward = false;
} else {
setAhead(40000);
movingForward = true;
}
}
public void onScannedRobot(ScannedRobotEvent e) {
if (trackName != null && !e.getName().equals(trackName)) {
return;
}
if (trackName == null) {
trackName = e.getName();
}
count = 0;
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
turnGunRight(gunTurnAmt);
fire(3);
scan();
}
public void onHitRobot(HitRobotEvent e) {
trackName = e.getName();
gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
turnGunRight(gunTurnAmt);
fire(3);
if (e.isMyFault()) {
reverseDirection();
}
}
public void onWin(WinEvent e) {
for (int i = 0; i < 50; i++) {
turnRight(30);
turnLeft(30);
}
}
}//如你所见就是放在一起了而已,没想象的丝滑
//
此外,编程期间遇见如:public void非法的表达式开始 需要‘;’的错误,这里的原因是花括号不一一对应出现问题
以下为battle节选,其中三个机器人对应情况如下:源码1-Testor ,源码2-Crazyor2,源码1+2-Testor2
录屏
(原来这么糊?!非常抱歉)
从中看出,源码1Testor的表现其实很稳定,但是为啥源码1+2的分数最高(如下),刚上手我也不清楚
##总结
robocode平台在调试和投入使用上还是很方便快捷有意思的,不过对于机器人如何设计以获得高分这一问题需要一步步寻找答案。同时,也希望能够就robocode多交流,以提升自身的思维和变成水平。
(老板,如果你看到这里记得给个好评,孩子还有好多事,尽力了5555)