robocode冠军代码怎么追踪一个坦克却不碰到

Robocode机器人中的行为事件[2]
Robocode机器人中的行为事件[2]
&&& Robocode 行为事件&&& 坦克的主要都定义在一个主循环中,我们在程序中定义为上面四个策略定义四种战略如Move,Radar,Power,Target,当某一事件发生,基于这个事件而定的行为就会触发。而每个战略中都有不同的行为处理方式。这些行为通过遗传算法触发,遗传算法将调用这些基本动作并搜索这些策略的最佳组合。基于这些基本动作将有4224 (=4*11*4*3*8)种可能发生。在Robocode AdvancedRobot 类下有如下的移动函数:&&& * setAhead和ahead:让机器人向前移动一定距离。&&& * setBack和back:让机器人向后移动一定距离。&&& * setMaxTurnRate:设置机器人最大的旋转速度。&&& * setMaxVelocity:设置机器人最大的运动速度。&&& * setStop和stop:停止移动或暂停机器人,并记住停止的位置。&&& * setResume和resume:重新开始移动停止的机器人。&&& * setTurnLeft和turnLeft:向左旋转机器人。&&& * setTurnRight和turnRight:向右旋转机器人。&&& 下面是 doMove 移动方法中使用部分程序代码:&&& Random:&&& switch(Math.random()*2) {&& &&&& case 0:&& &setTurnRight(Math.random()*90);&&& &&& &&& &&& case 1:&& &setTurnLeft(Math.random()*90);&& &&&&&&& &}&& &execute();&&& Linear:&&& ahead(200);&&& setBack(200);&&& Circular:&&& setTurnRight(1000);&&& setMaxVelocity(4);&&& ahead(1000);&&& anti gravity:&& &double forceX = 0;&&& double forceY = 0;&&& for (int i=0; i&targetInfo.size(); i++){&&& &&& TargetInformation ti = (TargetInformation)targetInfo.get(i);&& &&&& double targetToMeX = getX()-ti.x;&& &&&& double targetToMeY = getY()-ti.y;&& &&&& double targetDistance = Math.sqrt(ti.x * ti.x + ti.y * ti.y);&& &&&& forceX += (targetToMeX/(ti.distance * ti.distance));&& &&&& forceY += (targetToMeY/(ti.distance * ti.distance));&& &&& &}&&& forceX += 1/(getX());&&& forceY += 1/(getY());&&& forceX += 1/(getX()-getBattleFieldWidth());&&& forceY += 1/(getY()-getBattleFieldHeight());&&& double forceMagnitude = Math.sqrt(forceX*forceX+forceY*forceY);&&& forceX*=8/forceM&&& forceY*=8/forceM&&& desiredX = getX() + forceX;&&& desiredY = getY() + forceY;&&& …&&& 这里我们用遗传算法来控制机器人移动位置。这些策略是基于下面几点:机器人人自己的位置、速度和方位;对手的位置(x,y坐标)、速度、方位以及相对角;所有机器人和子弹位置,方位及速度;场地大小等参数。&&& 当上面的信息在下一回移动中使用时,出输出一对坐标值,根据这对坐标在Robocode就能得到距离和角度。要想让移动实现遗传必须要让它实现在线学习:所以我们的代码必须做下面几件事:要有一个函数收集适应度值,在Robocode运行过程中要运用到遗传操作,遗传后代要在Robocode运行中产生,而不是事后由手写入代码。[] &[2] &
H3C认证Java认证Oracle认证
基础英语软考英语项目管理英语职场英语
.NETPowerBuilderWeb开发游戏开发Perl
二级模拟试题一级模拟试题一级考试经验四级考试资料
软件测试软件外包系统分析与建模敏捷开发
法律法规历年试题软考英语网络管理员系统架构设计师信息系统监理师
高级通信工程师考试大纲设备环境综合能力
路由技术网络存储无线网络网络设备
CPMP考试prince2认证项目范围管理项目配置管理项目管理案例项目经理项目干系人管理
职称考试题目
招生信息考研政治
网络安全安全设置工具使用手机安全
生物识别传感器物联网传输层物联网前沿技术物联网案例分析
Java核心技术J2ME教程
Linux系统管理Linux编程Linux安全AIX教程
Windows系统管理Windows教程Windows网络管理Windows故障
数据库开发Sybase数据库Informix数据库
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&Robocode坦克大战 -
Robocode坦克大战
本来我们学校有一个Java机器人比赛,后来因为参赛人数过少就取消了。这个代码写的并不是很好,等以后闲下来再继续完善。
import java.awt.C
import java.awt.geom.Point2D;
import robocode.*;
public class RoundSheep9 extends AdvancedRobot&&
&&& RStarget enemy = new RStarget();
&&& RSpoint [] point=new RSpoint[5];
&&& double previousEnergy = 100;
&&& int movementDirection = 1;
&&& int radarDirection = 1;
&&& double degree=0;
&&& double distance=0;
&&& boolean noTarget =
&&& double RadarO
&&& int curP=0;
&&& double firePower=1;
&&& double preHeading=-1;
&&& boolean fireStatus=
&&& int missCount=0;
&&& int gunOffdir=1;
&&& public void run()
&&&&&&& doInit();
&&&&&&& while(true)
&&&&&&&&&&&&&&& if( noTarget )
&&&&&&&&&&& setTurnRadarRightRadians(Double.POSITIVE_INFINITY);
&&&&&&& else
&&&&&&&&&&& doScan();
&&&&&&&&&&& doMove();
&&&&&&&&&&& doFire();
&&&&&&&&&&& noTarget =
&&&&&&& execute();
&&&&&&& fireStatus=
&&& public void doInit()
&&&&&&& setBodyColor(Color.black);
&&&& setGunColor(Color.black);
&&&&& setRadarColor(Color.black);
&&&&&&& setScanColor(Color.black);
&&&& setBulletColor(Color.black);
&&&&&&& setAdjustGunForRobotTurn(true);
&&&&&&& setAdjustRadarForGunTurn(true);
&&&&&&& setAdjustRadarForRobotTurn(true);
&&&&&&& for(int i=0;i&5;i++)
&&&&&&&&&&& point[i]=new RSpoint();
&&& public void doScan()
&&& RadarOffset=format(enemy.direction-getRadarHeadingRadians());
&&& setTurnRadarRightRadians(RadarOffset*2.0);
&&& public void doMove()
&&&&&&& if( Math.abs( getDistanceRemaining() ) & 1 )&&&
&&&&&&& double myX = getX();
&&&&&&& double myY = getY();
&&&&&&& double nextX, nextY;&&&&
&&&&&&& nextX = Math.random() * ( getBattleFieldWidth() - 100 ) + 50;
&&&&&&& nextY = Math.random() * ( getBattleFieldHeight() - 100 ) + 50;
&&&&&&& double turnAngle = enemy.getAngle( myX, myY, nextX, nextY );
&&&&&&& turnAngle = enemy.normalizeBearing( turnAngle - getHeadingRadians() );
&&&&&&& double moveDistance = Point2D.distance( myX, myY, nextX, nextY );
&&&&&&& double moveDirection = 1;
&&&&&&& if ( Math.abs( turnAngle ) & Math.PI/2 )
&&&&&&& {&&&&&&&&
&&&&&&&&&&& turnAngle = enemy.normalizeBearing( turnAngle + Math.PI );&&&&
&&&&&&&&&&& moveDirection = -1;
&&&&&&& setTurnRightRadians( turnAngle );
&&&&&&& setAhead( moveDirection * moveDistance );
&&& public void doFire()
&&&&&&& //System.out.println(&Fire&);
&&& public void onScannedRobot(ScannedRobotEvent e)
&&&&&&& /*for(int i=0;i&5;i++)
&&&&&&&&&&& System.out.println(point[i].x);
&&&&&&&&&&& System.out.println(point[i].y);
&&&&&&& }*/
&&&&&&& //System.out.println(Math.acos(0.5));
&&&&&&& //System.out.println(Math.acos(0));
&&&&&&& //System.out.println(Math.acos(1));
&&&&&&& //System.out.println(Math.round(3.1));
&&&&&&& //System.out.println(Math.round(3.5));
&&&&&&& //System.out.println(Math.round(3.8));
&&&&&&& //System.out.println(Math.sqrt(3.8));
&&&&&&& //System.out.println(&random:&+(int)(Math.random()*1000%2));
&&&&&&&&&&&
&&&&&&& firePower=300/e.getDistance();
&&&&&&&&&&&
&&&&&&& getTarget(e);
&&&&&&&&&&&&
&&&&&&& noTarget =
&&& enemy.update(e, this);
&&&&&&& distance=e.getDistance();
&&&&&&& degree=getGunHeading()-getRadarHeading();
&&&&&&& double changeInEnergy =previousEnergy-e.getEnergy();
&&&&&&& if(getOthers()==2)
&&&&&&&&&&& setTurnRight(e.getBearing()+90-30*movementDirection);
&&&&&&&&&&&&
&&&&&&&&&&& //System.out.println(&changeInEnergy:&+changeInEnergy);
&&&&&&&&&&&
&&&&&&&&&&& if (changeInEnergy&0 &&changeInEnergy&=3)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& //if(0==(int)(Math.random()*1000%2))
&&&&&&&&&&&&&&& {&&&&&&&&
&&&&&&&&&&&&&&&&&&& movementDirection =-movementD
&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& setAhead((distance/4+25)*movementDirection);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& //else
&&&&&&&&&&&&&&& // setBack((distance/4+25));
&&&&&&&&&&& }&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&& radarDirection = -radarD
&&&&&&&&&&&
&&&&&&& //if(fireStatus==false)
&&&&&&& // setTurnGunLeft(normalRelativeAngle(degree));
&&&&&&& //System.out.println(&getVelocity():&+e.getVelocity() );
&&&&&&& //System.out.println(&getGunHeading():&+getGunHeading());
&&&&&&& //System.out.println(&getRadarHeading():&+getRadarHeading());
&&& if(Math.abs(degree)&distance/50+10)
&&&&&&& //System.out.println(&getDistance():&+distance);
&&&&&&& //if (getGunHeat() == 0)
&&&&&&& // fire(200/distance);
&&&&&&& previousEnergy = e.getEnergy();
&&&&&&& preHeading=(getHeading() + e.getBearing()) % 360;
&&&&&&&&&&&
&&& public void onBulletMissed(BulletMissedEvent event)
&&&&&&& missCount++;
&&&&&&& if(7&=missCount)
&&&&&&&&&&& gunOffdir=-gunO
&&&&&&&&&&& missCount=0;
&&&&&&& }&&
&&& public void onBulletHit(BulletHitEvent event)
&&&&&&& missCount=0;
&&& public double normalRelativeAngle(double angle)
&&&&& if (angle & -180 && angle &= 180)
&&&& while (angle &= -180)
&&&&&&&&& angle += 360;
&&&&&&&&&&&
&&&&&& while (angle & 180)
&&&&&&&&&&& angle -= 360;
&&& public double format(double arg)
&&&&&& while(arg&Math.PI)
&&&&&&& arg=arg-Math.PI*2.0;
&&&&&& while(arg&-Math.PI)
&&&&&&& arg=arg+Math.PI*2.0;
&&& public void getTarget(ScannedRobotEvent e)
&&&&&&& double maxDegree=0;
&&&&&&& degree=getGunHeading()-getRadarHeading();
&&&&&&& double bearing = (getHeading() + e.getBearing()) % 360;
&&&&&&& double distance = e.getDistance();
&&&&&&& System.out.println(&bearing&+bearing);
&&&&&&& bearing = Math.toRadians(bearing);
&&&&&&& point[curP].x=Math.round(getX() + Math.sin(bearing) * distance);
&&&&&&& point[curP].y=Math.round(getY() + Math.cos(bearing) * distance);
&&&&&&& System.out.println(&e.getBearing()&+e.getBearing());
&&&&&&&&&&& System.out.println(&heading &+getHeading());
&&&&&&&&&&& System.out.println(&getRadarHeading()&+getRadarHeading());
&&&&&&& if(point[curP].x!=-1&&
&&&&&&&&&& point[curP].y!=-1&&
&&&&&&&&&& point[prevP()].x!=-1&&
&&&&&&&&&& point[prevP()].y!=-1&&
&&&&&&&&&& (point[prevP()].x!=point[curP].x||
&&&&&&&&&& point[prevP()].y!=point[curP].y))
&&&&&&&&&&& double timeB=e.getDistance()/(20-3*firePower);
&&&&&&&&&&& double t=timeB;
&&&&&&&&&&& double v0=Math.abs(e.getVelocity());
&&&&&&&&&&& double moveD=0;
&&&&&&&&&&&
&&&&&&&&&&& if(v0+1*timeB&8)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& moveD=(8*8-v0*v0)/2/1+8*(timeB-(8-v0)/1);
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& moveD=v0*timeB+1*timeB*timeB/2;
&&&&&&&&&&& }
&&&&&&&&&&&
&&&&&&&&&&& double moveS=getD(point[prevP()].x,point[prevP()].y,point[curP].x,point[curP].y);
&&&&&&&&&&&
&&&&&&&&&&& long maxX=Math.round(moveD/moveS*(point[curP].x-point[prevP()].x)+point[curP].x);
&&&&&&&&&&& long maxY=Math.round(moveD/moveS*(point[curP].y-point[prevP()].y)+point[curP].y);
&&&&&&&&&&&
&&&&&&&&&&& maxDegree=Math.acos((e.getDistance()*e.getDistance()+getD(maxX,maxY,Math.round(getX()),Math.round(getY()))*getD(maxX,maxY,Math.round(getX()),Math.round(getY()))-moveD*moveD)/2/e.getDistance()/getD(maxX,maxY,Math.round(getX()),Math.round(getY())));
&&&&&&&&&&& /*double minDegree=-v0*v0/4+8*8/2/1;
&&&&&&&&&&&
&&&&&&&&&&& if(v0/2&t)
&&&&&&&&&&&&&&& minDegree=0;
&&&&&&&&&&& else if(v0/2+8/1&t)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& minDegree=-v0*v0/4+1*(t-v0/2)*(t-v0/2)/2;
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& if(minDegree&0)
&&&&&&&&&&&&&&&&&&& minDegree=0;
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& minDegree=getCos();
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& minDegree+=(t-v0/2-8/1)*8;
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& minDegree=getCos();
&&&&&&&&&&& }*/
&&&&&&&&&&& //System.out.println(&maxDegree:&+maxDegree/Math.PI*180);
&&&&&&&&&&& //System.out.println(&getRadarHeading()&+getRadarHeading());
&&&&&&&&&&& //System.out.println(&preHeading&+preHeading);
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&& maxDegree=maxDegree/Math.PI*180*Math.abs(e.getVelocity())/8*(firePower/5+1)/1.1764;
&&&&&&&&&&& //System.out.println(&maxDegree:&+maxDegree);&&
&&&&&&&&&&&&&&&
&&&&&&&&&&& double curHeading=(getHeading() + e.getBearing()) % 360;
&&&&&&&&&&&
&&&&&&&&&&& if(preHeading&0)
&&&&&&&&&&&&&&& ;
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& if(curHeading-preHeading&0||curHeading-preHeading&-180)
&&&&&&&&&&&&&&&&&&& gunOffdir=-1;
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&& gunOffdir=1;
&&&&&&&&&&& }
&&&&&&&&&&&&&&& /*if(e.getVelocity()&0)
&&&&&&&&&&&&&&& {//getRadarHeading()-preHeading&0
&&&&&&&&&&&&&&&&&&& maxDegree=-Math.abs(maxDegree);
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&& maxDegree=Math.abs(maxDegree);*/
&&&&&&&&&&&&&&&
&&&&&&& setTurnGunLeft(normalRelativeAngle(degree)+maxDegree*gunOffdir);
&&&&&&& setFire(firePower);
&&&&&&& curP=nextP();
&&& public int nextP()
&&&&&&& if(4==curP)
&&&&&&&&&&& return 0;
&&&&&&& else
&&&&&&&&&&& return curP+1;
&&& public int prevP()
&&&&&&& if(0==curP)
&&&&&&&&&&& return 4;
&&&&&&& else
&&&&&&&&&&& return curP-1;
&&& public double getD(long x1,long y1,long x2,long y2)
&&&&&&& return Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
&&& /*public double getCos(double minDegree,double moveS)
&&&&&&& long minX=Math.round(point[curP].x-minDegree/moveS*(point[curP].x-point[prevP()].x));
&&&&&&& long minY=Math.round(point[curP].y-minDegree/moveS*(point[curP].y-point[prevP()].y));
class RSpoint
&&& public long x=-1;
&&& public long y=-1;
class RStarget
&&& public double X=0.0;
&&& public double Y=0.0;
&&& public double distance=3000;
&&& public double heading=0.0;
&&& public double direction=0.0;//0 2.0*PI
&&& public double bearing=0.0;
&&& public double preEnergy=100.0;
&&& public double Energy=100.0;
&&& public double V=8.0;
&&& public double gettime=0.0;
&&& public void update(ScannedRobotEvent e,AdvancedRobot me)
&&&&&& gettime=e.getTime();
&&&&&& preEnergy=E
&&&&&& Energy=e.getEnergy();
&&&&&& bearing=e.getBearingRadians();
&&&&&& heading=e.getHeadingRadians();
&&&&&& Energy=e.getEnergy();
&&&&&& distance=e.getDistance();
&&&&&& V=e.getVelocity();
&&&&&& direction=me.getHeadingRadians()+
&&&&&& if(this.direction&0.0)
&&&&&&& direction+=2.0*Math.PI;
&&&&&& if(this.direction&=2.0*Math.PI)
&&&&&&& direction-=2.0*Math.PI;
&&&&&& Y=me.getY()+distance*Math.cos(direction);
&&&&&& X=me.getX()+distance*Math.sin(direction);
&&& public static double normalizeBearing( double angle )
&&&&& if ( angle & -Math.PI )
&&&&&&&&& angle += 2*Math.PI;
&&&&& if ( angle & Math.PI )
&&&&&&&&& angle -= 2*Math.PI;
public static double getAngle(double x1, double y1, double x2, double y2)
&&&&& return Math.atan2( x2 - x1, y2 - y1 );
更多相关文章
写这个游戏已经有一段时间了,一直在实现各种新功能,从最开始的地图上只有坦克,发子弹还是一个大问题到现在可以两个人一起玩,还是花了不少心思的,现在坦克的速度更快,电脑坦克也不会撞墙.虽然游戏性没有经典坦克大战那么强,但是还是可以用来休闲娱乐一下,这个用了很多最近学到的新知识,模仿俄罗斯方块,还有一些小 ...
前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面向对象的程度也是要花一点功夫的,特别是初学的同学往往意识不到面向对象的好处,因为我们编码的流程是这样 ...
还是决定写点东西简单记录下这次编码. 一.想法
还没放假的时候只想着用C#实现,算法图论方面觉得图论方向会靠谱些,但一直没有什么好点子.C#以前也没学过,自信来源于MFC的学习经历(以前也是用它做了C语言课设).C#应该是没有MFC那么复杂的,心想看几天应该就可以上手一些 ...
对战坦克大战 转载请注明出处 本文章的下载地址,请单击此链接 本节将介绍一个和FC(FamilyComputer)上的经典游戏&坦克大战&类似的游戏--对战坦克 大战.这是一个4 人对战的坦克游戏,4个玩家两两一组,率先攻击到对 ...
用前面介绍的方法,创建一个cocos2d-x项目,可以看到新项目内容如下图:我看查看 HelloWorldScene.cpp中的函数bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( ...
DP 对于第i个状态(房子),有两种选择:偷(rob).不偷(not rob) 递推公式为: f(i)=max?????{f(i-1)+vali,f(i-2)+vali,robi-1==0robi-1==1f(i-1 ...
以下内容摘自正在全面热销的最新网络设备图书&豪华四件套&之一&C ...
题目链接 题意:求出在a到b之间的数中,有多少个0. 思路:组合数学问题.能够枚举每一个位置上的数i,如果i之前的数为left,后面的为right,后面有num位数.当i != 0时,将i置为0,所以组合数为left ...
今天开始打算总结一下在iOS开发中的网络部分 NSURLConnection 这个访问网络的方式最简单,但功能也是最少的因此只有很简单的网络访问才会用到; 使用NSURLConnection访问网络大致分为四个步骤
在bash shell中提供在if-then语句中使用的高级功能: 1.双圆括号表示数学表达数 2.双方括号表示高级字符串处理函数 使用双圆括号 双圆括号命令允许在比较中包含高级数学公式.test命令只允许在比较中进 ...
友情链接:
管理员邮箱:info@1069人阅读
机器学习与神经网络算法(2)
遗传算法(Genetic Algorithm, GA)是近几年发展起来的一种崭新的全局优化算法。本文将讲解这种算法,并介绍如何 Robocode Java 坦克机器人中采用此算法以实现机器人进化。
遗传算法(Genetic Algorithm, GA)是近几年发展起来的一种崭新的全局优化算法。1962年霍兰德(Holland)教授首次提出了GA算法的思想,它借用了仿真生物遗传学和自然选择机理,通过自然选择、遗传、变异等作用机制,实现各个个体的适应性的提高。从某种程度上说遗传算法是对生物进化过程进行的数学方式仿真。
这一点体现了自然界中&物竞天择、适者生存&进化过程。与自然界相似,遗传算法对求解问题的本身一无所知,它所需要的仅是对算法所产生的每个染色体进行评价,把问题的解表示成染色体,并基于适应值来选择染色体,使适应性好的染色体有更多的繁殖机会。在算法中也即是以二进制编码的串。并且,在执行遗传算法之前,给出一群染色体,也即是假设解。然后,把这些假设解置于问题的“环境”中,也即一个适应度函数中来评价。并按适者生存的原则,从中选择出较适应环境的染色体进行复制, 淘汰低适应度的个体,再通过交叉,变异过程产生更适应环境的新一代染色体群。对这个新种群进行下一轮进化,至到最适合环境的值。
遗传算法已用于求解带有应用前景的一些问题,例如遗传程序设计、函数优化、排序问题、人工神经网络、分类系统、计算机图像处理和机器人运动规划等。
由于遗传算法是由进化论和遗传学机理而产生的搜索算法,所以在这个算法中会用到很多生物遗传学知识,下面是我们将会用来的一些术语说明:
一、染色体(Chronmosome)
染色体又可以叫做基因型个体(individuals),一定数量的个体组成了群体(population),群体中个体的数量叫做群体大小。
二、基因(Gene)
基因是串中的元素,基因用于表示个体的特征。例如有一个串S=1011,则其中的1,0,1,1这4个元素分别称为基因。它们的值称为等位基因(Alletes)。
三、基因地点(Locus)
基因地点在算法中表示一个基因在串中的位置称为基因位置(Gene Position),有时也简称基因位。基因位置由串的左向右计算,例如在串 S=1101 中,0的基因位置是3。
四、基因特征值(Gene Feature)
在用串表示整数时,基因的特征值与二进制数的权一致;例如在串 S=1011 中,基因位置3中的1,它的基因特征值为2;基因位置1中的1,它的基因特征值为8。
五、适应度(Fitness)
各个个体对环境的适应程度叫做适应度(fitness)。为了体现染色体的适应能力,引入了对问题中的每一个染色体都能进行度量的函数,叫适应度函数. 这个函数是计算个体在群体中被使用的概率。
霍兰德(Holland)教授最初提出的算法也叫简单遗传算法,简单遗传算法的遗传操作主要有三种:选择(selection)、交叉(crossover)、变异(mutation)这也是遗传算法中最常用的三种算法:
1.选择(selection)
选择操作也叫复制操作,从群体中按个体的适应度函数值选择出较适应环境的个体。一般地说,选择将使适应度高的个体繁殖下一代的数目较多,而适应度较小的个体,繁殖下一代的数目较少,甚至被淘汰。最通常的实现方法是轮盘赌(roulette wheel)模型。令Σfi表示群体的适应度值之总和,fi表示种群中第i个染色体的适应度值,它被选择的概率正好为其适应度值所占份额fi/Σfi。如下图表中的数据适应值总和Σfi=6650,适应度为2200变选择的可能为fi/Σfi=.394.
Fitness 值:
选择概率:
2.交叉(Crossover)
交叉算子将被选中的两个个体的基因链按一定概率pc进行交叉,从而生成两个新的个体,交叉位置pc是随机的。其中Pc是一个系统参数。根据问题的不同,交叉又为了单点交叉算子(Single Point Crossover)、双点交叉算子(Two Point Crossover)、均匀交叉算子 (Uniform Crossover),在此我们只讨论单点交叉的情况。
单点交叉操作的简单方式是将被选择出的两个个体S1和S2作为父母个体,将两者的部分基因码值进行交换。假设如下两个8位的个体:
产生一个在1到7之间的随机数c,假如现在产生的是2,将S1和S2的低二位交换:S1的高六位与S2的低六位组成数串,这就是S1和S2的一个后代P1个体;S2的高六位与S1的低二位组成数串,这就是S1和S2的一个后代P2个体。其交换过程如下图所示:
3.变异(Mutation)
这是在选中的个体中,将新个体的基因链的各位按概率pm进行异向转化,最简单方式是改变串上某个位置数值。对二进制编码来说将0与1互换:0变异为1,1变异为0。
如下8位二进制编码:
1 1 1 0 1 1 0 0
随机产生一个1至8之间的数i,假如现在k=6,对从右往左的第6位进行变异操作,将原来的1变为0,得到如下串:
1 1 0 0 1 1 0 0
整个交叉变异过程如下图:
4.精英主义 (Elitism)
仅仅从产生的子代中选择基因去构造新的种群可能会丢失掉上一代种群中的很多信息。也就是说当利用交叉和变异产生新的一代时,我们有很大的可能把在某个中间步骤中得到的最优解丢失。在此我们使用精英主义(Elitism)方法,在每一次产生新的一代时,我们首先把当前最优解原封不动的复制到新的一代中,其他步骤不变。这样任何时刻产生的一个最优解都可以存活到遗传算法结束。
上述各种算子的实现是多种多样的,而且许多新的算子正在不断地提出,以改进GA某些性能。比如选择算法还有分级均衡选择等等。
说简单点遗传算法就是遍历搜索空间或连接池,从中找出最优的解。搜索空间中全部都是个体,而群体为搜索空间的一个子集。并不是所有被选择了的染色体都要进行交叉操作和变异操作,而是以一定的概率进行,一般在程序设计中交叉发生的概率要比变异发生的概率选取得大若干个数量级。大部分遗传算法的步骤都很类似,常使用如下参数:
Fitness函数:见上文介绍。
Fitnessthreshold(适应度阀值):适合度中的设定的阀值,当最优个体的适应度达到给定的阀值,或者最优个体的适应度和群体适应度不再上升时(变化率为零),则算法的迭代过程收敛、算法结束。否则,用经过选择、交叉、变异所得到的新一代群体取代上一代群体,并返回到选择操作处继续循环执行。
P:种群的染色体总数叫种群规模,它对算法的效率有明显的影响,其长度等于它包含的个体数量。太小时难以求出最优解,太大则增长收敛时间导致程序运行时间长。对不同的问题可能有各自适合的种群规模,通常种群规模为 30 至 160。
pc:在循环中进行交叉操作所用到的概率。交叉概率(Pc)一般取0.6至0.95之间的值,Pc太小时难以向前搜索,太大则容易破坏高适应值的结构。
Pm:变异概率,从个体群中产生变异的概率,变异概率一般取0.01至0.03之间的值变异概率Pm太小时难以产生新的基因结构,太大使遗传算法成了单纯的随机搜索。
另一个系统参数是个体的长度,有定长和变长两种。它对算法的性能也有影响。由于GA是一个概率过程,所以每次迭代的情况是不一样的,系统参数不同,迭代情况也不同。
了解了上面的基本参数,下面我们来看看遗传算法的基本步骤。
基本过程为:
对待解决问题进行编码,我们将问题结构变换为位串形式编码表示的过程叫编码;而相反将位串形式编码表示变换为原问题结构的过程叫译码。随机初始化群体P(0):=(p1, p2, … pn);计算群体上每个个体的适应度值(Fitness)评估适应度,对当前群体P(t)中每个个体Pi计算其适应度F(Pi),适应度表示了该个体的性能好坏按由个体适应度值所决定的某个规则应用选择算子产生中间代Pr(t)依照Pc选择个体进行交叉操作仿照Pm对繁殖个体进行变异操作没有满足某种停止条件,则转第3步,否则进入9输出种群中适应度值最优的个体
程序的停止条件最简单的有如下二种:完成了预先给定的进化代数则停止;种群中的最优个体在连续若干代没有改进或平均适应度在连续若干代基本没有改进时停止。
根据遗传算法思想可以画出如右图所示的简单遗传算法框图:
下面伪代码简单说明了遗传算法操作过程:
choose an intial population
For each h in population,compute Fitness(h)
While(max Fitness(h) & Fitnessthreshold)
do selection
do crossover
do mutation
update population
For each h in population,compute Fitness(h)
Return best Fitness
能有效实现遗传算法的应用例子有很多,像西洋双陆棋、国际名模等等都是遗传程序设计学习的工具,但是 Robocode 有着其他几个无可比拟的优势:
它是基于面向对象语言 Java 开发,而遗传算法本身的思想也是存在继承等面向对象概念;Robocode 是一种基于游戏与编程语言之间的平台,有一个充满竞技与乐趣的坦克战斗平台,你能很快的通过与其他坦克机器比赛而测试自己的遗传算法;Robocode 社群有 4000 个左右各种策略的例子机器人可供你选择,这些机器人足以让我们模拟真实的遗传环境。而且很多代码可直接开放源代码供我们借鉴 ;Robocode 是一个开源软件,你可直接上Robocode控制器上加入自己的遗传特点,而加快遗传过程的收敛时间;Robocoe是一个很容易使用的机器人战斗仿真器,您在此平台上创建自己的坦克机器人,并与其它开发者开发的机器人竞技。以得分排名的方式判定优胜者。每个 Robocode 参加者都要利用 Java 语言元素创建他或她的机器人,这样就使从初学者到高级黑客的广大开发者都可以参与这一娱乐活动。如果您对Robocode不是很了解,请参考 developerWorks 网站 Java 技术专区文章:“”;
在 Robocode 中其实有很多种遗传算法方法来实现进化机器人,从全世界的 Robocode 流派中也发展几种比较成熟的方法,比如预设策略遗传、自开发解释语言遗传、遗传移动我们就这几种方法分别加以介绍。由于遗传算法操作过程都类似,所以前面二部分都是一些方法的介绍和部分例子讲解,后面部分会给出使用了遗传算法的移动机器人人例子。 在附录中,也提供了机器人仓库中有关遗传算法机器人的下载,大家可参考。
Robocode 坦克机器人所有行为都离不开如移动、射击、扫描等基本操作。所以在此把这些基本操作所用到的策略分别进化如下编码:移动策略move-strategy (MS), 子弹能量bullet-power-strategy (BPS), 雷达扫描radar-strategy (RS), 和瞄准选择策略target- strategy (TS)。由于Robocode爱好者社群的发展,每一种基本操作都发展了很多比较成熟的策略,所有在此我们直接在下面预先定义的这些策略如下表:
distance-based
always-turn
light-fast
target-focus
Powerful-slow
target-scope-focus
Perpendicular
nearest robot
hit-rate based
anti gravity
Bullet avoid
wall avoid
Oscillators
下面是基本移动策略的说明:
Random:随机移动主要用来混乱敌人的预测,其最大的一个缺点是有可能撞击到其他机器人Linear:直线移动,机器人做单一的直线行走 circular:圆周移动,这种移动是以某一点为圆心,不停的绕圈Perpendicular:正对敌人移动,这是很多人采用的一种移动方式,这在敌人右边, 以随时调整与敌人的相对角Arbitrary:任意移动AntiGravity:假设场地有很多力点的反重力移动,本方法是模拟在重力场作用下,物体总是远离重力势高的点,滑向重力势低的点,开始战场是一个平面然后生成一些势点重力势大的势点的作用就像是一个山(起排斥作用),其衰减系数与山的坡度对应。重力势小的势点的作用就像是一个低谷(起吸引作用),其衰减系数与谷的坡度对应。这样使本来的平面变得不平了,从来物体沿着最陡的方向向下滑动Track:跟踪敌人,敌人移动到哪,机器人也移动到哪,但是总与敌人保持一定最佳躲避子弹距离和角度Oscillators:重复做一振荡移动Bullet avoid:每当雷达觉察到敌人时有所动作。机器人保持与敌人成30度倾向角。自身成 90 度角静止并逐渐接近目标。如果机器人觉察到能量下降介于 0.1 和 3.0 之间(火力范围),那么机器人就立即切换方向,向左或向右移动。wall avoid:这是一种使自己的机器人不会被困在角落里或者不会撞墙的移动方式
瞄准策略说明如下:
Headon:正对瞄准Linear:直线瞄准circular:圆周瞄准nearest robot:接近机器人瞄准Log:保存每次开火记录Statistic:统计学瞄准,分析所有打中及未打中的次数,以其中找出最高打中敌人的概率为准则Angular:找到最佳角度瞄准Wave:波形瞄准,子弹以波的方式进行探测
坦克的主要都定义在一个主循环中,我们在程序中定义为上面四个策略定义四种战略如Move,Radar,Power,Target,当某一事件发生,基于这个事件而定的行为就会触发。而每个战略中都有不同的行为处理方式。这些行为通过遗传算法触发,遗传算法将调用这些基本动作并搜索这些策略的最佳组合。基于这些基本动作将有4224 (=4*11*4*3*8)种可能发生。在Robocode AdvancedRobot 类下有如下的移动函数:
setAhead和ahead:让机器人向前移动一定距离.setBack和back:让机器人向后移动一定距离setMaxTurnRate:设置机器人最大的旋转速度setMaxVelocity:设置机器人最大的运动速度setStop和stop:停止移动或暂停机器人,并记住停止的位置setResume和resume:重新开始移动停止的机器人setTurnLeft和turnLeft:向左旋转机器人setTurnRight和turnRight:向右旋转机器人
下面是 doMove 移动方法中使用部分程序代码:
switch(Math.random()*2) {
case 0: setTurnRight(Math.random()*90);
case 1: setTurnLeft(Math.random()*90);
execute();
ahead(200);
setBack(200);
Circular:
setTurnRight(1000);
setMaxVelocity(4);
ahead(1000);
anti gravity:
double forceX = 0;
double forceY = 0;
for (int i=0; i&targetInfo.size(); i++){
TargetInformation ti = (TargetInformation)targetInfo.get(i);
double targetToMeX = getX()-ti.x;
double targetToMeY = getY()-ti.y;
double targetDistance = Math.sqrt(ti.x * ti.x + ti.y * ti.y);
forceX += (targetToMeX/(ti.distance * ti.distance));
forceY += (targetToMeY/(ti.distance * ti.distance));
forceX += 1/(getX());
forceY += 1/(getY());
forceX += 1/(getX()-getBattleFieldWidth());
forceY += 1/(getY()-getBattleFieldHeight());
double forceMagnitude = Math.sqrt(forceX*forceX+forceY*forceY);
forceX*=8/forceM
forceY*=8/forceM
desiredX = getX() + forceX;
desiredY = getY() + forceY;
这里我们用遗传算法来控制机器人移动位置。这些策略是基于下面几点:机器人人自己的位置、速度和方位;对手的位置(x,y坐标)、速度、方位以及相对角;所有机器人和子弹位置,方位及速度;场地大小等参数。
当上面的信息在下一回移动中使用时,出输出一对坐标值,根据这对坐标在Robocode就能得到距离和角度。要想让移动实现遗传必须要让它实现在线学习:所以我们的代码必须做下面几件事:要有一个函数收集适应度值,在Robocode运行过程中要运用到遗传操作,遗传后代要在Robocode运行中产生,而不是事后由手写入代码。
本例中遗传算法为实现移动用到两个类GA和MovePattern。此处的GA比较简单主要完成数据和群体的定义,以及这些定义的读写文件操作。基中包括如下参数:群体大小、交叉概率、变异概率、精英概率(既告诉从当前群体到下一代中有多少移动不需要改变)、方程式中使用的加权系数大小,它通过一个主循环完成MovePattern的封装。MovePattern类中实现交叉、变异方法等方法,完成移动模式操作。而所有的输出保存在一个vector函数当中。Vector函数拥有一对实数数组,一个用于计算x坐标,另一个用于计算y坐标。通过对x,y坐标的计算,从而得到距离、角度等值,并产生相就在移动策略。如下,MovePattern包含三个参数,grad表示vector函数排列顺序,input即表示算法给出的输入编号,rang是加权的范围。
public class MovePatteren implements Comparable {
private int grad,
protected double fitness=0;
protected double[] weightsX, weightsY;
交叉操作:每一个交叉操作执行如下步骤,先在交叉操作中产生一个特征码。这个特征码是个0到1之间的变量数组。有关交叉的基本原理可参考上面部分。最后通过遍历vector函数,把相应的加权值进行交叉操作。
protected MovePatteren crossOver(MovePatteren mate, boolean[] maskx, boolean[] masky) {
double[] wx= new double[weightsX.length];
double[] wy= new double[weightsX.length];
for(int mask=0; mask&maskx. mask++) {
for(int g=0; g&= g++) {
int i=mask*(grad+1)+g;
wx[i]=(maskx[mask]?this:mate).weightsX[i];
wy[i]=(masky[g]?this:mate).weightsY[i];
return new MovePatteren(grad, input, range, wx, wy);
这里的变异操作比较简单。把加权范围内的随机数值去代替0到数组长之间的随机数并保存到移动模式中。则完成整个数组的变异过程:
protected void mutate() {
weightsX[(int)(Math.random()*weightsX.length)]=Math.random()*range*2-
weightsY[(int)(Math.random()*weightsX.length)]=Math.random()*range*2-
从上面的例子我们知道了遗传算法的大概实现,但并没有告诉我们这些组件是如何一起工作的。当Robocode开始时,如果文件中没有数据,所以系统会依照输入的策略随机生成一个移动模式,如果文件中有数据,则加载这些数据。每一个移动模式在开始都会给出了一个适应度值。当所有的移动模式都接收到适应度值,并完成各自的编号后,下面的操作将开始执行:
对所有的移动模式依据它们的适应度值进行分级处理执行精英操作执行交叉操作应用变异操作保存加权算法重新开始
适应度值在进行运算过程中由机器人程序不断调整,以找到最优适应度。
限于篇副其他的一些策略本文不与详细说明,上面所有提到的策略和行为程序都可在网上或IBM的开发杂志上找到成熟的讲解和例子机器人。有兴趣的朋友可以把这些策略都加入到自己的遗传算法中来。我们取群体大小为50,选择概率为0.7,交叉概率为0.6,变异概率为0.3,与Robocode部分例子机器人测试,经过150代后你会发现系统产生了很多有趣的策略。比如撞击策略,这些策略都不在我们定义的策略之中。
遗传算法可被看做任意基因组字符串。但是你必须决定这些字符所代表的意义,也就是说如何解释每一个基因组。最简单的方法是把每一个基因组视为java代码,编译并运行它们。但是这些程序编译都很困难,所以也就有可能不能工作。Jacob Eisenstein设计了一种机器翻译语言TableRex来解决这个问题。在java中,TableRex被用于进化和解释动行时的Robocode机器人。通过测试,只要我把TableRex解释程序作为文件放入Robocode控制器目录中,这些控制器就会读取文件并开始战斗。TableRex是一些最适合遗传算法的二进制编程。只要符合TableRex程序文法,每个程序都能被解释。
下表中显示了TableRex编码结构,它由一个行动作函数,二个输入和一个输出组成。如行6的值 ,这是个布尔型的表达式“值 line4 小于 90”,这个结果会在最后一行输出布尔为1的值。
3. Greater Than
4. Normalize Angle
Enemy bearing
5. Absolute Value
6. Less Than
8. Multiply
9. Less Than
Enemy distance
11. Multiply
Turn gun left
输入的函数我们依照Robocode定义而定。如下表:
gunHeading
distance to west wall
distance to north wall
distance to east wall
distance to south wall
constant: 1
constant: 2
constant: 10
constant: 90
enemyVelocity
enemyEnergy
enemyHeading
enemyBearing
enemyDistance
TableRex有三个设计标准:
它是一种解释程序,能更快的进化程序,基于TableRex设计的机器人能有效的读写遗传数据;拥有一个容易编码的固定基因组,使遗传中更容易交叉操作;只要给TableRex一个简单的输入,它就很容易通过操作命令输出要的命令序列。如上表的最后输出左转炮管;
而整个TableRex解释程序由三部分组成:
SmallBrain:TableRex的实现部分,此部分直接写在例子机器人处,也即自己写的测试机器人;BrainWorld:这是实现遗传算法的主方法,直接写入Robocode控制器当中,在Robocode运行当中运行;GeneticAlgorithm:这是遗传算法的定义部分,里面直接定义了所要用到的遗传操作函数;
下面我们来分析一个机器人如何通过TableRex达到遗传。
主要是声明选择、交叉、变异的方法。
GeneticAlgorithm是一个静态类,其中定义了遗传所要的基本参数,如下:
public abstract class GeneticAlgorithm {
public int population_
// 群体长度
public int genome_
//基因个体长度
public GFPair population[];
//产生的群体
public int best_
public double best_fitness = Double.MIN_VALUE;
//最优适应度
public double mutation = 0.03;
//变异概率
public double crossover = 0.9;
//交叉概率
public double copy = 0.1;
public int tourney_size = 3;
其中变异概率取0.03, 交叉概率取0.9,最优适应度为实型的最小。此部分是从保存的文件中读取各个基本参数遗传初始化群体。
依照适应度值选择群体中个体:
public String tourneySelect (){
double best_fit = -1;
int best_guy = -1;
for (int i = 0; i & tourney_ i++){
int cur_guy = (int) (Math.random() * population.length);
if (population[cur_guy].fitness & best_fit){
best_fit = population[cur_guy].
best_guy = cur_
return population[best_guy].
交叉操作:通过从字符串中取子串的方法达到交叉操作:
public static String crossover (String g1, String g2){
int num_points = (int) Math.round (Math.random() * 4f);
int point = (int) (g1.length() * Math.random());
return g1.substring (0, point) + g2.substring (point);
变异操作:此部分先把基因转换为字符串流,通过setCharAt函数从指定的位置取反字符而达到变异:
public static String mutate (String genome, double p_mutation){
StringBuffer genome_b = new StringBuffer (genome);
if (genome_b.charAt (point) == '1'){
genome_b.setCharAt(point, '0');
genome_b.setCharAt (point, '1');
return new String (genome_b);
BrainWorld直接嵌入到Robocode控制器中,通过实现RobocodeListener接口来完成遗传的实例化。其最重要的有两个方法,计算最优适应度和产生遗传后代。
1. 实例化 GeneticAlgorithm:
genome_size = num_events * num_boxes * (input_bits * 2 + func_bits);
int population_size = Integer.parseInt (in.readLine());
ga = new GeneticAlgorithm (population_size, genome_size);
2. 通过文件读取操作从遗传保存文件中读取参数到遗传类中,文件格式如下所示:
Robocode Location
Storage_directory
population_size
base_mutation
3. 计算最优适应度:
protected void evaluateAll (){
ga.best_fitness = Double.MIN_VALUE;
ga.worst_fitness = Double.MAX_VALUE;
for (int i = 0; i & ga.population_ i++){
ga.population[i].fitness = 0;
for (int j = 0; j & rspecs. j++){
ga.population[i].fitness +=
Math.pow (2.0, (all_results[i][j] - all_means[j]) / all_stdevs[j]);
ga.mean_fitness += ga.population[i].
if (ga.population[i].fitness & ga.best_fitness) {
ga.best_fitness = ga.population[i].
ga.best_index =
通过三个循环遍历整个群体,对各个适应度进行比较后找出最优适应度。
4. 产生遗传后代
public void newGeneration (){
String copy_pop[] = ga.copy (ga.population, ga.copy);
String cross_pop[] = ga.crossover (ga.population, ga.crossover);
copy_pop = ga.mutate (copy_pop, ga.mutation);
cross_pop = ga.mutate (cross_pop, ga.mutation);
for (int i = 0; i & copy_pop. i++){
ga.population[i+elite_pop.length].genome = copy_pop[i];
for (int i = 0; i & cross_pop. i++){
ga.population[i+elite_pop.length+copy_pop.length].genome = cross_pop[i];
current_generation++;
evaluateAll();
通过复制(ga.copy)、交叉(ga.crossover)、变异(ga.mutate)操作,产生出遗传后代。
SmallBrain也即我们写的利用遗传算法的例子机器人,它开始读取遗传文件&genome.dat&,产生新的编码,当扫描到敌人时把所有相关的信息写入数组robot_data,再通过循环操作进化写入输入运算,最后遍历输入运算决定输出机器人的动作。
public void parseGenome (String genome){
functions = new int [num_boxes][num_events];
inputs1 = new int [num_boxes][num_events];
inputs2 = new int [num_boxes][num_events];
robot_data = new double [num_boxes + num_system_inputs][num_events];
通过parseGenome方法,设置function,input1,input2等数组的参数,对要操作的机器人进行编码。这部分和最上面提来的TableRex编码表是一致的。
2.写入状态信息
public void onScannedRobot (ScannedRobotEvent e){
robot_data[0][kSCAN_EVENT] = getVelocity();
robot_data[1][kSCAN_EVENT] = getEnergy();
robot_data[2][kSCAN_EVENT] = getHeading();
3.根据函数数组写入输入运算
for (int i = 0; i & num_ i++){
switch (functions[i][event_num]){
case 0: //greater than
robot_data [i + num_system_inputs][event_num] =
robot_data[inputs1[i][event_num]][event_num] &
robot_data[inputs2[i][event_num]][event_num]?1f:0f;
case 2: //equal to
handleOutput (inputs1[i][event_num], robot_data [inputs2[i][event_num]][event_num]);
此处注意最后是根据写入的操作运算进行输出
4.输出机器人动作命令
public void handleScanOutput (int outputType, double value){
switch (outputType % 16){
ahead (value);
back (value);
//maybe shouldn't use mod here
fire (value % 3);
最后我们可以看出TableRex程序中,smallBrain和BrainWorld之间以文件方式并行交互,smallBrain扫描信息,写入文件。BrainWorld根据文件数据进化机器人,并把进化结果写入文件,smallBrain根据进化后的数据产生机器人的动作。
Geep 的机器人GPBot系统正是采用了TableRex解释程序的简单例子。
GPBot仅由四行代码组成(每行都以分号结束),它做了如下一些定制达到代码最优化:忽略雷达旋转,让它直接随着炮管而转动TurnGunRight(INFINITY);把行为做为常量来实现,让它们能显示在进化代码序列的任意点。
OnScannedRobot() {
MoveTank(&GP#1&);
TurnTankRight(&GP#2&);
TurnGunRight(&GP#3&);
GPBot所有事件都写在ScannedRobotEvent事件。每个方法都利用到了遗传算法进化机器人。第一行代码移动系统进化,适应度值依照个体躲避子弹,避墙和敌人的能力而设置;第二行代码指示坦克旋转指定的方向角。第三行代码瞄准系统进化指示炮管旋转指定的方向角, 适应度值依照个体打中敌人概率来设置。GPBot群体大小为256个个体,变异、交叉概率分别为0.9,选择长度为5。在最附录中提供了例子机器人人下载。
最后我们给出一些测试数据,看看我们的程序不同的测试结果。
变异概率变化测试:
群体大小: 25
变异概率(Mutation): tested
精英概率(Elitism): 0.1
比赛回合: 20 rounds
我们选择变异概率分级从0.01到0.5这间。依照上面的遗传算法介绍,0.01的概率是比较合理的,所以我们以此为初始化值,下图中显示了所有的测试概率数据,从下图我们可以看出,开始一个很小的适应度值,从6代开始图形就增长很慢了,在13代的时候,有一个小的变化,到最后每个后代都相当逼近。
测试说明:
我们从上可以看出当我们给出初始的适应度在很小时,在第一代增长很多,经过一定数量的后代开始汇聚到一些最大的适应度值。由此我们得到证明,机器人在我们的学习环境中聪明的开始躲避子弹、墙、和其他机器人。而且它自己找到一个很好的瞄准位置给与敌人打击。
最后不能不说一下Jgap的使用, JGAP 是一款用Java编写的遗传算法包,由sourceforce上开发而来。它提供了基本的遗传算法,你可以使用它来解决一些适合用遗传算法解决的问题。而且它给出了很多例子程序,可用于我们一些遗传算法的测试工作。由于它来自于开源组织sourceforce,所以开源的遗传功能将是研究简单遗传算法很好工具。
近来在研究人工智能过程和坦克机器人时,发现国内也开发出了一个类似于 Robocode 仿真器的平台 AI-CODE,其思想延用 Robocode,但在 Robocode 基础上做了很多的改进,封装了一些函数模块,让开发R者更侧重于算法和程序设计的学习。最有意思的这个平台能同时支持 Java,C,C++,C# 语言,从理论上看它支持任何语言。美中不足的是国内应用的例子还不是很多,远没有 Robocode 那么多可参考的例子。如果大家有兴趣可尝试在 AI-CODE 平台上用不同语言做一些遗传算法的测试。我想能帮助更多人工智能爱好者。其相关网站大家可到
麻省理工大学 Jacob Eisenstein 关于 TableRex 的详细说明论文” ” 及 ;
geep关于 TableRex 的文章说明及 ;
Jin-Hyuk Hong and Sung-Bae Cho 关于 Robocode 策略进化机器人论文” ”;
关于AI-CODE高级应用;
SourceForce 上关于 JGAP 的;
大量测试机器人下载 ;
developerWordk 网站上的 ;
Robocool,编程游戏爱好者,自由撰稿人。您可以通过联系到他。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:438083次
积分:6933
积分:6933
排名:第2941名
原创:238篇
转载:195篇
评论:29条
(7)(1)(1)(1)(4)(13)(32)(24)(31)(39)(32)(21)(25)(70)(46)(5)(2)(12)(5)(35)(21)}

我要回帖

更多关于 robocode怎么玩 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信