国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Robocode 高手的秘訣:因數避墻法

2019-11-18 13:08:51
字體:
來源:轉載
供稿:網友

  設計出一種算法,使您的機器人不會被困在角落里或者過多的偏離想要的移動方向,而且不會靠近墻,這是件很困難的事。因數避墻法是一種簡單的解決辦法。在這篇小技巧中,David McCoy 將向您展示如何實現這項方便的技術。
  
  我們只要對在 Tracking your opponents' movement 中做的機器人加以補充,就能將因數避墻法添加到現有的或討厭的移動算法中。這種方法將預想的方向和根據機器人和墻之間距離遠近確定的安全方向作為因數試圖找到最可能的方向。
  
  添加做常見數學計算的輔助方法
  我們先要給機器人添加常見數學算法使用的一些輔助方法。
  
  calculateBearingToXYRadians() 方法使用 java.lang.Math 中的 atan2() 方法來計算從 sourceX,sourceY 到 targetX,targetY 的絕對方位,然后再把這個值轉化為相對于 sourceHeading 的相對方位。
  
  我們還需要 normalizeAbsoluteAngleRadians() 方法和 normalizeRelativeAngleRadians() 方法。
  
  清單 1. 數學輔助方法
  PRivate static final double DOUBLE_PI = (Math.PI * 2);
  private static final double HALF_PI = (Math.PI / 2);
  
  public double calculateBearingToXYRadians(double sourceX, double sourceY,
  double sourceHeading, double targetX, double targetY) {
  return normalizeRelativeAngleRadians(
  Math.atan2((targetX - sourceX), (targetY - sourceY)) -
  sourceHeading);
  }
  
  public double normalizeAbsoluteAngleRadians(double angle) {
  if (angle < 0) {
  return (DOUBLE_PI + (angle % DOUBLE_PI));
  } else {
  return (angle % DOUBLE_PI);
  }
  }
  
  public static double normalizeRelativeAngleRadians(double angle) {
  double trimmedAngle = (angle % DOUBLE_PI);
  if (trimmedAngle > Math.PI) {
  return -(Math.PI - (trimmedAngle % Math.PI));
  } else if (trimmedAngle < -Math.PI) {
  return (Math.PI + (trimmedAngle % Math.PI));
  } else {
  return trimmedAngle;
  }
  }
  
  使 AdvancedRobot 擴展到有倒行功能
  接著,為了以相反方向導航,我們需要用一些輔助方法把 AdvancedRobot 類的功能擴展到答應倒行操作:
  
  getRelativeHeading() 方法將應付正確計算相對于機器人當前的方向的相對方向產生的額外開銷。
  
  reverseDirection() 非常簡單。它負責 direction 實例變量的開關和使機器人掉頭。請注重,由于減速需要時間,依據機器人的速度,在掉過頭來之前最多會沿原來的方向再走 4 格。
  
  setAhead() 和 setBack() 方法將覆蓋 AdvancedRobot 類中的同名方法。這兩個方法會設置機器人對于目前方向的相對速度,必要的時候,還會調整 direction 實例變量。我們這么做的目的是要確保相對操作都與機器人當前的移動方向有關。
  
  setTurnLeftRadiansOptimal() 和 setTurnRightRadiansOptimal() 方法使機器人的方向轉過的角度超過 (Math.PI / 2)。您會希望這個方法和 adjustHeadingForWalls 方法(我們將在后面討論)一起使用。
  
  注:我沒有使用 getter 和 setter 方法,而是直接存取 direction 實例變量。盡管通常這并非良好的編程習慣,但為了加快數據存取,在我的機器人代碼中我一直都是直接存取的。
  
  清單 2. 機器人輔助方法
  public double getRelativeHeadingRadians() {
  double relativeHeading = getHeadingRadians();
  if (direction < 1) {
  relativeHeading =
  normalizeAbsoluteAngleRadians(relativeHeading + Math.PI);
  }
  return relativeHeading;
  }
  
  public void reverseDirection() {
  double distance = (getDistanceRemaining() * direction);
  direction *= -1;
  setAhead(distance);
  }
  
  public void setAhead(double distance) {
  double relativeDistance = (distance * direction);
  super.setAhead(relativeDistance);
  if (distance < 0) {
  direction *= -1;
  }
  }
  
  public void setBack(double distance) {
  double relativeDistance = (distance * direction);
  super.setBack(relativeDistance);
  if (distance > 0) {
  direction *= -1;
  }
  }
  
  public void setTurnLeftRadiansOptimal(double angle) {
  double turn = normalizeRelativeAngleRadians(angle);
  if (Math.abs(turn) > HALF_PI) {
  reverseDirection();
  if (turn < 0) {
  turn = (HALF_PI + (turn % HALF_PI));
  } else if (turn > 0) {
  turn = -(HALF_PI - (turn % HALF_PI));
  }
  }
  setTurnLeftRadians(turn);
  }
  
  public void setTurnRightRadiansOptimal(double angle) {
  double turn = normalizeRelativeAngleRadians(angle);
  if (Math.abs(turn) > HALF_PI) {
  reverseDirection();
  if (turn < 0) {
  turn = (HALF_PI + (turn % HALF_PI));
  } else if (turn > 0) {
  turn = -(HALF_PI - (turn % HALF_PI));
  }
  }
  setTurnRightRadians(turn);
  }
  
  添加因數避墻法
  我們需要添加的最后一個方法是 adjustHeadingForWalls() 方法。
  
  這個方法的前面一半根據機器人和墻的靠近程度選擇安全的 x 和 y 的位置(機器人當前的 x 或 y 位置,或者假如機器人靠近墻,則就是中心點)。方法的后面一半則計算距離“安全點”的方位,并把這個方位和依機器人離墻遠近得到的預想方向都作為因數考慮在內。
  
  可以使用 WALL_AVOID_INTERVAL 和 WALL_AVOID_FACTORS 常量來調整機器人對墻的擔憂程度。
  
  清單 3. 避墻法方法
  private static final double WALL_AVOID_INTERVAL = 10;
  private static final double WALL_AVOID_FACTORS = 20;
  private static final double WALL_AVOID_DISTANCE =
  (WALL_AVOID_INTERVAL * WALL_AVOID_FACTORS);
  
  private double adjustHeadingForWalls(double heading) {
  double fieldHeight = getBattleFieldHeight();
  double fieldWidth = getBattleFieldWidth();
  double centerX = (fieldWidth / 2);
  double centerY = (fieldHeight / 2);
  double currentHeading = getRelativeHeadingRadians();
  double x = getX();
  double y = getY();
  boolean nearWall = false;
  double desiredX;
  double desiredY;
  
  // If we are too close to a wall, calculate a course toward
  // the center of the battlefield.
  if ((y < WALL_AVOID_DISTANCE)
  ((fieldHeight - y) < WALL_AVOID_DISTANCE)) {
  desiredY = centerY;
  nearWall = true;
  } else {
  desiredY = y;
  }
  if ((x < WALL_AVOID_DISTANCE)
  ((fieldWidth - x) < WALL_AVOID_DISTANCE)) {
  desiredX = centerX;
  nearWall = true;
  } else {
  desiredX = x;
  }
  
  // Determine the safe heading and factor it in with the desired
  // heading if the bot is near a wall
  if (nearWall) {
  double desiredBearing =
  calculateBearingToXYRadians(x,
  y,
  currentHeading,
  desiredX,
  desiredY);
  double distanceToWall = Math.min(
  Math.min(x, (fieldWidth - x)),
  Math.min(y, (fieldHeight - y)));
  int wallFactor =
  (int)Math.min((distanceToWall / WALL_AVOID_INTERVAL),
  WALL_AVOID_FACTORS);
  return ((((WALL_AVOID_FACTORS - wallFactor) * desiredBearing) +
  (wallFactor * heading)) / WALL_AVOID_FACTORS);
  } else {
  return heading;
  }
  }
  
  匯總
  其余的工作很輕易。我們可以使用目前的導航算法,將得出的結果送入 adjustHeadingForWalls() 方法來避開墻。
  
  為了保持簡單,示例機器人(請參閱參考資料下載添加這一技術所需的源代碼)要求方向改變為零,從而試著沿直線移動。
  
  清單 4. 避墻法方法
  public void run() {
  while(true) {
  setTurnRightRadiansOptimal(adjustHeadingForWalls(0));
  setAhead(100);
  execute();
  }
  }
  
  關于它就是這樣了。簡單,但有效。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 专栏| 兴城市| 疏勒县| 江城| 墨江| 宜章县| 海门市| 教育| 衡山县| 惠安县| 息烽县| 扎鲁特旗| 梧州市| 五家渠市| 双鸭山市| 郎溪县| 苍山县| 桓台县| 大宁县| 两当县| 雅安市| 新巴尔虎左旗| 鄂托克前旗| 水城县| 河东区| 昌乐县| 新建县| 云浮市| 洛浦县| 福清市| 凌源市| 离岛区| 中西区| 淄博市| 治县。| 苍梧县| 辛集市| 松溪县| 永登县| 望都县| 定襄县|