网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  robocode 高手的秘诀:因数避墙法     
  文章作者:未知  文章来源:水木森林  
  查看:74次  录入:管理员--2007-11-17  
 
  设计出一种算法,使您的机器人不会被困在角落里或者过多的偏离想要的移动方向,而且不会靠近墙,这是件很困难的事。因数避墙法是一种简单的解决办法。在这篇小技巧中,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();
  }
  }
  
  关于它就是这样了。简单,但有效。
 
 
上一篇: robocode 基本原理之方向剖析    下一篇: robocode 高手的秘诀:躲避子弹
  相关文档
jsp牵手jsf打造完美的web应用 11-17
java设计模式之工厂方法模式 11-17
数据库相关:hibernate对多表关联查询 01-09
多形对象的互换使用 11-17
java中this、super用法简谈 11-17
jdbc 概述(四) 11-17
jakarta commons digester 简介和具体使用方法 11-17
java学习:ejb的专用术语解释 11-16
构建器的调用顺序 11-17
使用技巧:对java语言中的日期处理大全 11-16
java 中classspath 的默认值是什么? 11-17
web框架对比: wicket vs struts 11-17
轻松掌握 java 泛型 (第 2 部分) 11-17
jdk6.0新特性:用console开发控制台程序 11-16
java10年回顾:世界各地开发高手谈java 11-17
利用rmi实现java分布式应用 11-17
java初学者实践教程24-反射 11-17
表单递交合法性检测 - 只接受数字 11-17
[oracle]使用oracle10g jdbc 驱动中connectioncaching所产生的.. 11-17
实例学习struts 11-16
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
厦门(总部):13616026886 福州:0591-87655121
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息