分享
 
 
 

在Robocode中使用Vector实现敌人列表

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

前言

RoboCode的混战模式中,如何更好的掌握多个对手的情况,从而采取更好的策略,成为每一个玩家迫切需要解决的问题。而世界级的机器人大都采用了向量(vector)数组的方式来保存多个对手的信息。

而且vector的作用不止于此,上届世界冠军Yngwie还使用vector来保存子弹的命中率信息,为更好的决策提供依据。当然这超出了我们今天的话题,有兴趣的朋友可以看一下Yngwie中的Enemy类和Strategy类。

好了,让我们正式开始今天的vector之旅吧,如果您对JAVA中的vector还不是特别了解,没关系,我在最后介绍了一些关于vector的知识。

给我们的敌人排个队

熟悉JAVA的朋友都知道,vector是用来保存一系列对象的集合。今天我们用他来保存我们的敌人的一些信息,把这些四处乱跑的家伙都抓进我们的集合还真不是个轻松的活。孔子云:“万物皆类”。所以,我们首先要声明一个类:Track类。将我们能知道的敌人的属性全都作为这里类中的一个属性:名称、绝对角度、敌人坦克相对于你车头方向的相对角度、距离、能量、速率和敌人坦克所面对的方向等。这些都是通过ScannedRobotEvent对象得到的,具体的API函数请参考Robocode的API帮助。代码如下:

/**

* Track类,保存目标的信息

*/

package mytest;

import robocode.*;

public class Track

{

public String Name;

//敌人坦克的名称

//敌人的绝对角度,通过计算得出

public double Heading;

//敌人坦克相对于你车头方向的相对角度

public double Bearing;

public double Distance;

//敌人坦克的距离

public double Energy;

//能量

public double Velocity;

//速率

public double FaceHeading;

//敌人坦克面向的方向

public double trackX,trackY;

//敌人坦克的坐标

//下一个标准时间中敌人坦克所在的位置

public double nextTrackX,nextTrackY;

public void update(ScannedRobotEvent e)

{

Name=e.getName();

//敌人坦克的名称

Bearing=e.getBearing();

//敌人坦克相对于你车头方向的相对角度

Distance=e.getDistance(); //敌人坦克的距离

Energy=e.getEnergy();

//能量

Velocity=e.getVelocity();

//速率

FaceHeading=e.getHeading(); //敌人坦克面向的方向

}

}

在战场上,一个优秀的指挥官会很好的利用他手头有限的信息,而我们的信息都来自于雷达找到敌人后产生的ScannedRobotEvent事件,至于我们能得到哪些信息,看上边的注释好了,不多解释了。

下一步就是如何把已经现身在雷达中的敌人抓到一个vector里去了,让我们回到我们的机器人主体中去:派生自AdvancedRobot 类的MyVector类中。

首先,声明一个vector类型,并在run中进行初始化。

public class MyVector extends AdvancedRobot

{

final double version=0.1;

//版本号

private Vector trackVector;

//声明我们的向量数组

/**

* run: MyVector's default behavior

*/

public void run() {

out.println("myVector Version is "+version);

trackVector=new Vector();

//初始化我们的向量数组

while(true) {

// Replace the next 4 lines with any behavior you would like

showTrack();

setTurnRadarRight(360);

//让雷达不停转

execute();

}

}

好了,vector建好了,那下一步就……

请君入队

在Robocode中90%以上的外界信息来自于雷达的扫描,在这个例子里,我没有对雷达的动作进行更细致地处理,一直让他在不停旋转,从而能更多的收集不同敌人的信息。如果是在单挑模式中,可能采取雷达锁定目标会更加有效。

只要雷达工作正常,我们就能获取每一个敌人的信息了。当敌人的信息源源不断地涌入我们的onScannedRobot中,我们的机器人要像一个优秀的指挥官一样去鉴别情报,那些是已经有的,那些是没有的。如果已经存在我们则更新该对象的属性;如果没有的话,就在向量数组中添加一个新的成员。让我们去onScannedRobot事件里看一下吧。

/**

* onScannedRobot: What to do when you see another robot

*/

public void onScannedRobot(ScannedRobotEvent e) {

if(!isInVector(e))

{

Track myTrack=new Track();

myTrack.update(e);

trackVector.add(myTrack);

}

}

我的myVector机器人是靠自定义方法isInVector来判断该机器人是否存在于向量数组中的,我们等下去看isInVector的里边。如果isInVector返回值为false,则初始化一个Track对象,调用它的update方法来初始化敌人的信息,然后调用Vector类型的add方法,将该对象加入到向量数组中。

在这里请大家注意的一点是:同一个Vector对象中可以存储不同类型的对象,这是JAVA优于C++的一点,但是切忌滥用,我们在trackVector对象中存贮的对象都是Track类型。 好了,让我们去isInVector里边看看吧。

/**

* isInVector:自定义方法,判断该机器人是否已存在于队列中

*/

public boolean isInVector(ScannedRobotEvent e)

{

int i=0;

while(i

{

Track myTrack=(Track)trackVector.get(i);

if(myTrack.Name==e.getName())

{

myTrack.update(e);

return true;

}

i++;

}

return false;

}

isInVector方法的基本思路是,通过传进来的ScannedRobotEvent中的getName来和vector中已经存在的对象的Name来进行比较,如果有相同的Name存在,则说明该敌人的对象已经储存在vector中了,我们只需要简单的调用Track类的update方法,更新信息,并返回true 就可以了。如果没有在vector中找到同名的机器人,则返回false,交给onScannedRobot事件来将这个机器人添加到vector中来。

这里我使用了Vector类型的size方法来得到向量数组中存在的对象的数量,在后边我们还会用到这个方法。同时使用一个int变量来控制操作哪个对象,更好的办法是使用迭代器,有兴趣的朋友可以参考一下《JAVA编程指南》。要得到vector中的Track对象,则需要使用Vector 类型的get方法,它指定返回第几个对象。注意,这里需要进行强制类型的转换。得到对象后我们就可以比较Track的 Name和ScannedRobotEvent的getName()是否相同了。

敌人不见了

在Robocode的战场上,杀戮与被杀的几率是相同的。不知道大家想过没有,如果一个敌人被干掉了,他的对象还保存在我们的vector中!如果我们的火控系统偏巧选中了他来作为下一个攻击目标的话……不用担心,如果我的机器人真那么傻,他恐怕等不到别人被杀的情况。很简单,我们只需要在onRobotDeath事件中调用Vector类型的remove方法。Remove方法是用来删除指定位置上的对象的。下面代码的基本思路和isInVector是一样的。显示如下:

/**

* onScannedRobot:有机器人被消灭时产生该事件

*/

public void onRobotDeath(RobotDeathEvent event)

{

int i=0;

while(i

{

Track myTrack=(Track)trackVector.get(i);

if(myTrack.Name==event.getName())

{

trackVector.remove(i);

}

i++;

}

}

显示敌人的距离

我们这么辛苦地保存了战场上所有敌人的信息后,由myVector在每个基本时间里报告每个机器人距我们的距离。但这里应该注意的是,myVector报告的距离是我们的雷达最后一次看到敌人时的距离,敌人很可能已经移动了。正如一位物理学家所说:“我们无法预测未来是因为我们无法看到真实的现在。”

我在run的while中调用了下面的函数,用来显示当前的时间、敌人的数量及每个敌人与我们的距离。对数量的计算用到了Vector 的size方法。

/**

* 自定义函数:显示当前敌人的距离

*/

public void showTrack()

{

int i=0;

out.println("This Time is "+getTime());

out.println("Track's count is "+trackVector.size());

while(i

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有