robocode机器人案例
1、游戲規則:
生命規則:
? 相撞損失:撞到墻時,生命點損傷度=Math.abs (velocity) * 0.5 -1。撞到另一個坦克時,移動停止,生命點損失6點,扣除積分1.2分。
 ? 擊中損失:當子彈能量為1時,我們生命點損失=4 * power,如果子彈能量大于1,那么我們的生命損失+= 2 * (power-1)。
 ? 發射損失:如果我們的子彈打中別的坦克,我們可以從子彈那竊取到3*power的能量。
炮彈規則:
? 子彈能量:子彈能量是通過凼數getPower()得到的。它大于等于0.1,小于等于3。
 ? 子彈速度:每一顆子彈有著自身的速度,這在處理敵人向你開炮前的秱動策略可是很有幫助的。子彈的速度也和它的能量有關: speed = 20 - 3 * power。由于能量范圍在0.1到3之間我們可求得子彈的速度范圍:11 <= bullet speed <= 19.7。
炮管規則:
? 旋轉速率:炮管在每一個時間周期內旋轉速率=20 度/幀(frame)
 ? 炮管熱量:當我們開火時,炮管產生的熱量由子彈開火時的能量決定。即:熱量=1+(firepower/5), 利用凼數 getGunHeat()可以得到炮管當時的熱量,只有當getGunHeat恒等于0時,我們才能再次發射子彈。
 ? 冷卻度:有熱度當然就有冷卻度,丌冷卻我們的炮管會永遠丌會開火的。系統設定的默認冷卻速度是0.1/tick(時間周期),我們可通過凼數 getGunCoolingRate()得到這個參數值。
雷達規則:
? 旋轉速度:雷達以每時間周期45度的速度旋轉。也即45 degrees/frame.
 ? 掃描面積: 雷達掃描是呈扇形的,它的開始位置到終止位置的長度大約為1200。只要我們放大屏幕可以通過眼睛估算出這個面積。
 ? 掃描排列:掃描到的數據有墻,目標,子彈等等。這些是按掃描距離來排列,從離雷達最近的物體開始到最后掃描到的物體。
運行規則:
? 前進速度:坦克最大的速度(Velocity)為8,凼數getVelocity()迒回了坦克當前的速度。
 ? 加/減速度:加速度為 1 像素(pixel)/幀frame ,減速度為 2 pixel/frame。
 ? 參考公式: 設s為距離,Vt為終速度,Vo為初速度,t為時間,a 為加速度:
 ? 位秱公式 s=Vot+att/2
 ? 速度公式 Vt =Vo +at
 ? 平均速度公式 v=(Vt + Vo)/2=s/t
 ? 加速度公式 a=(Vt - Vo)/t
 ? (這些公式大家都學過吧?)
旋轉規則:
? 旋轉速度:機器人的旋轉速度和當前的速度有關即旋轉速度=10 - 0.75 * getVelocity()。
 ? 相互作用參數:雷達安裝在炮上,炮安裝在機器人上,它們會相互影響。如果我們向左轉動炮管,而使雷達向右轉動,那么雷達只會向右轉動(45-20) =25度;如果兩者都向右轉動,雷達將向右轉(45+20)=65度。同樣的道理炮和機器人也是方向同相加,方向反相減。
積分規則:
? Robot Name - 機器人的名字;
 ? Total Scroe - 為這次比賽你的總共得分;
 ? Survival - 是你存活率的得分;
 ? Last Survivor Bonus:你是贏的次數相對對手的分紅得分;
 ? Bullet Dmg:是你的子彈損失得分也即發射的子彈數的得分;
 ? Bonus:是子彈數的分紅得分;
 ? Ram Dmg *2是你的撞擊得分;
 ? Bonus:是你撞擊得分分紅;
 ? 最后兩項Survival 1sts,是你贏的次數,丌算做分數。
部分接口:
部分重要的接口函數介紹(全部函數參考安裝文件夾下的Javadoc文件夾):坦克屬性:double getBattleFieldHeight() 戰場高度double getBattleFieldWidth() 戰場寬度 double getHeight() 坦克高度String getName() 坦克名稱double getWidth() 坦克寬度 double getGunHeading() 炮管角度double getHeading() 坦克角度double getRadarHeading() 雷達角度 double getX() 坐標Xdouble getY() 坐標Y double getGunHeat() 炮管熱量double getEnergy() 能量數值double getGunCoolingRate() 炮管冷卻比例 double getVelocity() 坦克速度運行控制:void ahead(double distance) 前進void back(double distance) 后退void doNothing() 空void fire(double power) 開火 void setAdjustGunForRobotTurn(boolean independent) 炮/車同向void setAdjustRadarForGunTurn(boolean independent) 炮/雷達同向void setAdjustRadarForRobotTurn(boolean independent) 雷達/車同向 void turnRadarLeft(double degrees) 雷達左轉角度void turnRadarRight(double degrees) 雷達右轉角度void turnGunLeft(double degrees) 炮左轉角度void turnGunRight(double degrees) 炮右轉角度void turnLeft(double degrees) 車左轉角度void turnRight(double degrees) 車右轉角度戰斗事件:void onBulletHit(BulletHitEvent event) 子彈擊中坦克void onBulletHitBullet(BulletHitBulletEvent event) 子彈擊中子彈void onBulletMissed(BulletMissedEvent event) 子彈沒有擊中目標void onDeath(DeathEvent event) 坦克被消滅的時候void onHitByBullet(HitByBulletEvent event) 被子彈擊中void onHitRobot(HitRobotEvent event) 被坦克撞擊void onHitWall(HitWallEvent event) 撞墻void onRobotDeath(RobotDeathEvent event) 坦克死亡void onScannedRobot(ScannedRobotEvent event) 掃描到坦克void onWin(WinEvent event) 勝利 void run() 運行 voidscan() 掃描ScannedRobotEvent –雷達掃描:double getBearing() 獲得相對自己坦克方向的角度double getBearingRadians() 獲得相對自己坦克方向的弧度double getDistance() 獲得距離double getEnergy() 獲得運行能量double getHeading() 獲得方向角度double getHeadingRadians() 獲得方向弧度String getName() 獲得坦克名稱double getVelocity() 獲得運行速度構造坦克的方式:Robot (常用) –支持較為全面的簡單控制邏輯;TeamRobot –支持團隊作戰模式;AdvancedRobot –支持自定義事件.[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uDgVfsQd-1573645318604)(C:\Users\root\Desktop\assets\1573610781554.png)]
2、機器人Demo
import robocode.*;import java.awt.Color;/*** SnippetBot - a robot by Alisdair Owens* This bot includes all sorts of useful snippets. It is not* designed to be a good fighter (although it does well 1v1),* just to show how certain things are done* Bits of code lifted from Nicator and Chrisbot* Conventions in this bot include: Use of radians throughout* Storing absolute positions of enemy bots rather than relative ones* Very little code in events* These are all good programming practices for robocode* There may also be methods that arent used; these might just be useful for you.*/public class SnippetBot extends AdvancedRobot{/*** run: SnippetBot's default behavior*/Enemy target; //our current enemy 代表對手,包括了對手的所有有用參數final double PI = Math.PI; //just a constant int direction = 1; //direction we are heading...1 = forward, -1 = backwards//我們坦克車頭的方向double firePower; //the power of the shot we will be using - set by do firePower() 設置我們的火力public void run() {target = new Enemy(); //實例化Enemy()類target.distance = 100000; //initialise the distance so that we can select a targetsetColors(Color.red,Color.blue,Color.green); //sets the colours of the robot//the next two lines mean that the turns of the robot, gun and radar are independant//讓gun,radar獨立于坦克車setAdjustGunForRobotTurn(true);setAdjustRadarForGunTurn(true);turnRadarRightRadians(2*PI); //turns the radar right around to get a view of the field 以弧度計算旋轉一周while(true) {doMovement(); //Move the bot 移動機器人doFirePower(); //select the fire power to use 選擇火力doScanner(); //Oscillate the scanner over the bot 掃描doGun(); //move the gun to predict where the enemy will be 預測敵人,調整炮管out.println(target.distance); fire(firePower); //所有動作完成后,開火execute(); //execute all commands 上面使用的都為AdvancedRobot類中的非阻塞調用//控制權在我們,所有這里用阻塞方法返回控制給機器人}}/** This simple function calculates the fire power to use (from 0.1 to 3)* based on the distance from the target. We will investigate the data structure* holding the target data later.*/void doFirePower() {firePower = 400/target.distance;//selects a bullet power based on our distance away from the target //根據敵人距離來選擇火力,因為本身前進,后退為300,所以火力不會過大}/** This is the movememnt function. It will cause us* to circle strafe the enemy (ie move back and forward,* circling the enemy. if you don't know what strafing means* play more quake.* The direction variable is global to the class. Passing a* negative number to setAhead causes the bot to go backwards* 以目標主中心來回擺動*/void doMovement() {if (getTime()%20 == 0) //?過20的倍數時間就反轉方向{//every twenty 'ticks'direction *= -1; //reverse directionsetAhead(direction*300); //move in that direction}setTurnRightRadians(target.bearing + (PI/2)); //every turn move to circle strafe the enemy //每一時間周期以敵人為中心繞圓運動}/** this scanner method allows us to make our scanner track our target.* it will track to where our target is at the moment, and some further* in case the target has moved. This way we always get up to the minute* information on our target 雷達鎖定目標*/void doScanner() {double radarOffset; //雷達偏移量if (getTime() - target.ctime > 4) //???why來回掃了4個回合都沒掃到意味失去了目標,再全掃一遍{//if we haven't seen anybody for a bit....radarOffset = 360; //rotate the radar to find a target} else {//next is the amount we need to rotate the radar by to scan where the target is now//通過掃描決定雷達旋轉的弧度,"見基本原理方向剖析及目標鎖定www.robochina.org".雷達弧度-敵人角度得到兩者相差為旋轉值radarOffset = getRadarHeadingRadians() - absbearing(getX(),getY(),target.x,target.y);//this adds or subtracts small amounts from the bearing for the radar to produce the wobbling//and make sure we don't lose the target//在得到的角度中加或減一點角度,讓雷達很小的范圍內擺而不失去目標if (radarOffset < 0)radarOffset -= PI/8; //(0.375)elseradarOffset += PI/8; }//turn the radarsetTurnRadarLeftRadians(NormaliseBearing(radarOffset)); //左轉調整轉動角度到PI內}/** This simple method moves the gun to the bearing that we predict the* enemy will be by the time our bullet will get there.* the 'absbearing' method can be found in the helper functions section* the nextX and nextY method can be found in the 'Enemy' class description*/void doGun() {//works out how long it would take a bullet to travel to where the enemy is *now*//this is the best estimation we have //計算子彈到達目標的時間長speed = 20 - 3 * power;有計算公式,距離除速度=時間long time = getTime() + (int)(target.distance/(20-(3*firePower)));//offsets the gun by the angle to the next shot based on linear targeting provided by the enemy class//以直線為目標,偏移子彈下一次發射的角度。(這樣讓子彈射空的幾率減少。但對付不動的和做圓運動的機器人有問題)//target.guesssX(),target.guessY()為目標移動后的坐標double gunOffset = getGunHeadingRadians() - absbearing(getX(),getY(),target.guessX(time),target.guessY(time));setTurnGunLeftRadians(NormaliseBearing(gunOffset)); //調整相對角度到2PI內}/** This set of helper methods. You may find several of these very useful* They include the ability to find the angle to a point.*///if a bearing is not within the -pi to pi range, alters it to provide the shortest angledouble NormaliseBearing(double ang) {if (ang > PI)ang -= 2*PI;if (ang < -PI)ang += 2*PI;return ang;}//if a heading is not within the 0 to 2pi range, alters it to provide the shortest angledouble NormaliseHeading(double ang) {if (ang > 2*PI)ang -= 2*PI;if (ang < 0)ang += 2*PI;return ang;}//returns the distance between two x,y coordinates '**'//以兩邊長求得與對手之間的距離public double getrange( double x1,double y1, double x2,double y2 ){double xo = x2-x1;double yo = y2-y1;double h = Math.sqrt( xo*xo + yo*yo ); return h; }//gets the absolute bearing between to x,y coordinates//根據x,y的坐標求出絕對角度,見"坐標鎖定"利用直角坐標系來反求出角度。???public double absbearing( double x1,double y1, double x2,double y2 ){double xo = x2-x1;double yo = y2-y1;double h = getrange( x1,y1, x2,y2 );if( xo > 0 && yo > 0 ){//反正弦定義,對邊除斜邊得弧度.以robocode中的絕對方向系及坐標系參照//x,y為正右上角為0-90,x正y負右下角為90-180,x,y負左下角180-270,x負,y正右上角270-360//此處要理解robocode中的絕對角度是上為0,下為180,如以中心為點劃分象限則得到下面的結果return Math.asin( xo / h );}if( xo > 0 && yo < 0 ){return Math.PI - Math.asin( xo / h ); //x為正,y為負第二象限角}if( xo < 0 && yo < 0 ){return Math.PI + Math.asin( -xo / h ); //第三象限內180+角度}if( xo < 0 && yo > 0 ){return 2.0*Math.PI - Math.asin( -xo / h ); //四象限360-角度}return 0;}/*** onScannedRobot: What to do when you see another robot* 掃描事件,也是初始化目標數據的過程*/public void onScannedRobot(ScannedRobotEvent e) {//if we have found a closer robot....if ((e.getDistance() < target.distance)||(target.name == e.getName())) {//the next line gets the absolute bearing to the point where the bot is//求得對手的絕對弧度double absbearing_rad = (getHeadingRadians()+e.getBearingRadians())%(2*PI);//this section sets all the information about our targettarget.name = e.getName();//求得對手的x,y坐標,見"robocode基本原理之坐標鎖定"文章target.x = getX()+Math.sin(absbearing_rad)*e.getDistance(); //works out the x coordinate of where the target istarget.y = getY()+Math.cos(absbearing_rad)*e.getDistance(); //works out the y coordinate of where the target istarget.bearing = e.getBearingRadians();target.head = e.getHeadingRadians();target.ctime = getTime(); //game time at which this scan was produced 掃描到機器人的游戲時間target.speed = e.getVelocity(); //得到敵人速度target.distance = e.getDistance();}}public void onRobotDeath(RobotDeathEvent e) {if (e.getName() == target.name)target.distance = 10000; //this will effectively make it search for a new target} }/** This class holds scan data so that we can remember where enemies were* and what they were doing when we last scanned then.* You could make a hashtable (with the name of the enemy bot as key)* or a vector of these so that you can remember where all of your enemies are* in relation to you.* This class also holds the guessX and guessY methods. These return where our targeting* system thinks they will be if they travel in a straight line at the same speed* as they are travelling now. You just need to pass the time at which you want to know* where they will be.* 保存我們掃描到的目標的所有有用數據,也可用hashtable,vector方法處理所有和我們有關的目標數據(用于群戰)* 中間的guessX,guessY方法是針對做直線均速運動機器人一個策略*/class Enemy {/** ok, we should really be using accessors and mutators here,* (i.e getName() and setName()) but life's too short.*/String name;public double bearing;public double head;public long ctime; //game time that the scan was producedpublic double speed;public double x,y;public double distance;public double guessX(long when){//以掃描時和子彈到達的時間差 * 最大速度=距離, 再用對手的坐標加上移動坐標得到敵人移動后的坐標long diff = when - ctime;return x+Math.sin(head)*speed*diff; //目標移動后的坐標}public double guessY(long when){long diff = when - ctime;return y+Math.cos(head)*speed*diff;}}3、機器人強化版
import robocode.*; import java.awt.*;import java.awt.Event;import javax.lang.model.element.ExecutableElement;import javax.swing.text.Document;import robocode.AdvancedRobot;import robocode.HitByBulletEvent; import robocode.HitWallEvent; import robocode.Robot;import robocode.ScannedRobotEvent;public class YanAn extends AdvancedRobot{private double eDist; //對方的距離private double move; //移動的距離private double radarMove = 45; //雷達移動的角度private double dFirePower; //火力boolean movingForward;/**- run: Crazy's main run function*/public void run() {eDist = 300;// 顏色setColors(Color.ORANGE, Color.BLUE, Color.RED, Color.WHITE, Color.GRAY);while(true){//每過一個周期,運動隨機的距離double period = 4*((int)(eDist/80)); //周期;敵人越接近,周期越短,移動越頻繁//周期開始,則移動if(getTime()%period == 0){move = (Math.random()*2-1)*(period*8 - 25);setAhead(move + ((move >= 0) ? 25: -25));}//避免撞墻double heading = getHeadingRadians(); //取得bot方向的弧度數double x = getX() + move*Math.sin(heading); //移動move后將要達到的x坐標double y = getY() + move*Math.cos(heading); //移動move后將要達到的y坐標double dWidth = getBattleFieldWidth(); //戰場的寬度double dHeight = getBattleFieldHeight(); //戰場的長度//當(x,y)超過指定的范圍,則反向移動moveif(x < 30 || x > dWidth-30 || y < 30 || y > dHeight-30){setBack(move);}turnRadarLeft(radarMove); //轉動雷達execute();}}public void onHitWall(HitWallEvent e) {// Bounce off!reverseDirection();}public void reverseDirection() {if (movingForward) {setBack(40000);movingForward = false;} else {setAhead(40000);movingForward = true;}}/**- onScannedRobot: Fire!*///onScannedRobot()每當?在一個動作中?看到另一個機器人時,游戲就會調用您的方法。它會發送一個事件,該事件可以告訴我們有關機器人的信息-機器人的名稱,壽命,位置,前進方向,運行速度等。public void onScannedRobot(ScannedRobotEvent e) {eDist = e.getDistance(); //取得對方距離radarMove = -radarMove; //設置雷達double eBearing = e.getBearingRadians(); //取得和對方相對角度的弧度數//將bot轉動相對的角度,以后bot的運動將是以對方為圓心的圓周運動setTurnLeftRadians(Math.PI/2 - eBearing);//轉動炮管指向對方setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(getHeadingRadians() + eBearing - getGunHeadingRadians()));//根據對方距離射擊dFirePower = 400/eDist;if (dFirePower > 3){dFirePower = 3;}fire(dFirePower);}/**- onHitRobot: Back up!*/public void onHitRobot(HitRobotEvent e) {// If we're moving the other robot, reverse!if (e.isMyFault()) {reverseDirection();}}}4、網站
機器人官網https://robocode.sourceforge.io/IDEA環境開發機器人https://my.oschina.net/kanlianhui/blog/1556868ve = -radarMove; //設置雷達double eBearing = e.getBearingRadians(); //取得和對方相對角度的弧度數//將bot轉動相對的角度,以后bot的運動將是以對方為圓心的圓周運動setTurnLeftRadians(Math.PI/2 - eBearing);//轉動炮管指向對方setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(getHeadingRadians() + eBearing - getGunHeadingRadians()));//根據對方距離射擊dFirePower = 400/eDist;if (dFirePower > 3){dFirePower = 3;}fire(dFirePower);}/**- onHitRobot: Back up!*/public void onHitRobot(HitRobotEvent e) {// If we're moving the other robot, reverse!if (e.isMyFault()) {reverseDirection();}}}4、網站
機器人官網https://robocode.sourceforge.io/IDEA環境開發機器人https://my.oschina.net/kanlianhui/blog/1556868總結
以上是生活随笔為你收集整理的robocode机器人案例的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: [pytorch、学习] - 3.10
- 下一篇: 十天学会PHP(第五版),十天学会php
