在 Robocode 的混戰模式中,如何有效掌握多個對手的動態並制定相應策略,是每位玩家必須解決的核心課題。世界級機器人普遍採用向量(Vector)陣列來管理多目標資訊。例如上屆世界冠軍 Yngwie 更進一步利用 Vector 記錄子彈命中率,以輔助決策系統——這雖超出本文範圍,但有興趣的讀者可參考其 Enemy 與 Strategy 類別的實作。
本文將帶領您實作一套基於 Vector 的敵人追蹤系統。即使您對 Java 的 Vector 不熟悉也無妨,文末將補充相關基礎知識。
「萬物皆類」。首先定義一個 Track 類別,封裝從 ScannedRobotEvent 取得的所有敵人屬性:名稱、絕對角度、相對角度、距離、能量、速度、朝向及座標等。
/** 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();
}
}
在繼承 AdvancedRobot 的主類別中宣告 Vector 並在 run() 中初始化,同時讓雷達持續掃描以收集情報。
public class MyVector extends AdvancedRobot {
final double version = 0.1;
private Vector trackVector; // 向量陣列
public void run() {
out.println("myVector Version is " + version);
trackVector = new Vector(); // 初始化
while (true) {
showTrack(); // 顯示追蹤資訊
setTurnRadarRight(360); // 雷達持續旋轉
execute();
}
}
}
核心邏輯在 onScannedRobot 事件中:利用自訂方法 isInVector 判斷敵人是否已存在。若不存在則建立新 Track 物件並加入 Vector;若存在則更新現有物件屬性。
public void onScannedRobot(ScannedRobotEvent e) {
if (!isInVector(e)) {
Track myTrack = new Track();
myTrack.update(e);
trackVector.add(myTrack);
}
}
/** 判斷敵人是否已在向量中 */
public boolean isInVector(ScannedRobotEvent e) {
int i = 0;
while (i < trackVector.size()) {
Track myTrack = (Track) trackVector.get(i);
if (myTrack.Name.equals(e.getName())) { // 建議使用 equals 比較字串
myTrack.update(e);
return true;
}
i++;
}
return false;
}
注意: Vector 可儲存不同類型物件,但強烈建議統一型別(此處皆為 Track)。取出物件時需強制轉型。實務上可改用迭代器提升效率與可讀性。
敵人被擊毀後,其物件仍留在 Vector 中會干擾火控系統。需在 onRobotDeath 中移除對應物件:
public void onRobotDeath(RobotDeathEvent event) {
int i = 0;
while (i < trackVector.size()) {
Track myTrack = (Track) trackVector.get(i);
if (myTrack.Name.equals(event.getName())) {
trackVector.remove(i);
} else {
i++; // 僅在未移除時遞增,避免索引錯位
}
}
}
在主迴圈中呼叫 showTrack() 輸出當前時間、敵人數量及各敵人距離(雷達最後掃描時的距離)。實戰中可進一步分析這些資料,例如鎖定最近敵人作為攻擊目標。
public void showTrack() {
int i = 0;
out.println("This Time is " + getTime());
out.println("Track's count is " + trackVector.size());
while (i < trackVector.size()) {
Track myTrack = (Track) trackVector.get(i);
out.println(myTrack.Name + "'s Distance is " + myTrack.Distance);
i++;
}
}

List 介面,容量自動增長,儲存物件引用而非實體。size()(長度)、capacity()(容量)、add()(新增)、get()(取得)、remove()(移除)、set()(替換)。toArray())或使用迭代器。本文提供的機器人雖屬入門級,但展示了在 Robocode 中善用 Java 集合框架的核心思維。掌握這些技術,能讓您的機器人在複雜戰場上遊刃有餘。