麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Robocode 高手的秘訣:因數(shù)避墻法

2019-11-18 13:08:51
字體:
供稿:網(wǎng)友

  設(shè)計(jì)出一種算法,使您的機(jī)器人不會(huì)被困在角落里或者過多的偏離想要的移動(dòng)方向,而且不會(huì)靠近墻,這是件很困難的事。因數(shù)避墻法是一種簡單的解決辦法。在這篇小技巧中,David McCoy 將向您展示如何實(shí)現(xiàn)這項(xiàng)方便的技術(shù)。
  
  我們只要對(duì)在 Tracking your opponents' movement 中做的機(jī)器人加以補(bǔ)充,就能將因數(shù)避墻法添加到現(xiàn)有的或討厭的移動(dòng)算法中。這種方法將預(yù)想的方向和根據(jù)機(jī)器人和墻之間距離遠(yuǎn)近確定的安全方向作為因數(shù)試圖找到最可能的方向。
  
  添加做常見數(shù)學(xué)計(jì)算的輔助方法
  我們先要給機(jī)器人添加常見數(shù)學(xué)算法使用的一些輔助方法。
  
  calculateBearingToXYRadians() 方法使用 java.lang.Math 中的 atan2() 方法來計(jì)算從 sourceX,sourceY 到 targetX,targetY 的絕對(duì)方位,然后再把這個(gè)值轉(zhuǎn)化為相對(duì)于 sourceHeading 的相對(duì)方位。
  
  我們還需要 normalizeAbsoluteAngleRadians() 方法和 normalizeRelativeAngleRadians() 方法。
  
  清單 1. 數(shù)學(xué)輔助方法
  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 擴(kuò)展到有倒行功能
  接著,為了以相反方向?qū)Ш剑覀冃枰靡恍┹o助方法把 AdvancedRobot 類的功能擴(kuò)展到答應(yīng)倒行操作:
  
  getRelativeHeading() 方法將應(yīng)付正確計(jì)算相對(duì)于機(jī)器人當(dāng)前的方向的相對(duì)方向產(chǎn)生的額外開銷。
  
  reverseDirection() 非常簡單。它負(fù)責(zé) direction 實(shí)例變量的開關(guān)和使機(jī)器人掉頭。請(qǐng)注重,由于減速需要時(shí)間,依據(jù)機(jī)器人的速度,在掉過頭來之前最多會(huì)沿原來的方向再走 4 格。
  
  setAhead() 和 setBack() 方法將覆蓋 AdvancedRobot 類中的同名方法。這兩個(gè)方法會(huì)設(shè)置機(jī)器人對(duì)于目前方向的相對(duì)速度,必要的時(shí)候,還會(huì)調(diào)整 direction 實(shí)例變量。我們這么做的目的是要確保相對(duì)操作都與機(jī)器人當(dāng)前的移動(dòng)方向有關(guān)。
  
  setTurnLeftRadiansOptimal() 和 setTurnRightRadiansOptimal() 方法使機(jī)器人的方向轉(zhuǎn)過的角度超過 (Math.PI / 2)。您會(huì)希望這個(gè)方法和 adjustHeadingForWalls 方法(我們將在后面討論)一起使用。
  
  注:我沒有使用 getter 和 setter 方法,而是直接存取 direction 實(shí)例變量。盡管通常這并非良好的編程習(xí)慣,但為了加快數(shù)據(jù)存取,在我的機(jī)器人代碼中我一直都是直接存取的。
  
  清單 2. 機(jī)器人輔助方法
  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);
  }
  
  添加因數(shù)避墻法
  我們需要添加的最后一個(gè)方法是 adjustHeadingForWalls() 方法。
  
  這個(gè)方法的前面一半根據(jù)機(jī)器人和墻的靠近程度選擇安全的 x 和 y 的位置(機(jī)器人當(dāng)前的 x 或 y 位置,或者假如機(jī)器人靠近墻,則就是中心點(diǎn))。方法的后面一半則計(jì)算距離“安全點(diǎn)”的方位,并把這個(gè)方位和依機(jī)器人離墻遠(yuǎn)近得到的預(yù)想方向都作為因數(shù)考慮在內(nèi)。
  
  可以使用 WALL_AVOID_INTERVAL 和 WALL_AVOID_FACTORS 常量來調(diào)整機(jī)器人對(duì)墻的擔(dān)憂程度。
  
  清單 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;
  }
  }
  
  匯總
  其余的工作很輕易。我們可以使用目前的導(dǎo)航算法,將得出的結(jié)果送入 adjustHeadingForWalls() 方法來避開墻。
  
  為了保持簡單,示例機(jī)器人(請(qǐng)參閱參考資料下載添加這一技術(shù)所需的源代碼)要求方向改變?yōu)榱悖瑥亩囍刂本€移動(dòng)。
  
  清單 4. 避墻法方法
  public void run() {
  while(true) {
  setTurnRightRadiansOptimal(adjustHeadingForWalls(0));
  setAhead(100);
  execute();
  }
  }
  
  關(guān)于它就是這樣了。簡單,但有效。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产美女做爰免费视 | sese在线视频 | 一级电影在线观看 | 久久久久久久久久久久久国产精品 | 免费福利在线视频 | 一级成人欧美一区在线观看 | 欧美黄色三级视频 | 国产精品欧美久久久久一区二区 | 国内一区| 国产一区二区在线免费观看 | 欧美性a视频 | 久久99精品久久久久久秒播放器 | 激情久久一区二区 | 日韩精品久久久久久久九岛 | 欧美成年人在线视频 | 嫩呦国产一区二区三区av | 成人免费看视频 | 亚洲人成综合第一网 | 久久亚洲网 | www.91操| 成人福利视频导航 | 播色网 | 中文字幕免费在线看 | 一区二区三区手机在线观看 | 精品国产精品久久 | 亚洲小视频在线播放 | 国产深夜福利视频在线播放 | 日本高清黄色片 | 久久精品小短片 | 精品黑人一区二区三区国语馆 | 久久久久99999| 一级免费黄色免费片 | 九九久久视频 | 亚洲精品在线观看免费 | 国产一国产一级毛片视频在线 | 国产女厕一区二区三区在线视 | 永久av在线免费观看 | 一级观看免费完整版视频 | 免费一级在线视频 | 欧美一级片免费在线观看 | 国内精品久久久久久久影视红豆 |