Robocode学习Java
Robocode
(用游戲來學習Java技術還是用Java來玩游戲?)
用你的JAVA編程技術來玩游戲吧!不會JAVA?那就用游戲來學習JAVA吧!
什么是Robocode?
其實我對機器人一直很感興趣。我記得在我還是初中的時候,就知道 AplleⅡ上有一個程序,用它來編寫簡單的機器人程序,然后相互作戰。當時自己還完全不懂編程,總是向往著,那神秘的編程高手玩的游戲是怎樣的?
Robocode就是這樣一個東西,但是更好一些。它是一個基于Java語言的機器人作戰游戲。 其代碼的編寫和建模都不錯,玩起來也很有趣。Robocode是很多"編程游戲"軟件中的一個,他們共同的特征是在沒有用戶輸入的狀態下許多機器人在一個及競技場中比賽,用戶必須編制一個高效的機器人來取勝。Robocode特別的像一場機器人坦克的大混戰,它們互相開火直到只剩一個勝利者。程序完全是由JAVA編寫,并且玩家必須要創造一個繼承自Robot類的類。
你希望在玩游戲的過程中、在閃躲炮彈、執行精確攻擊的演練中學會Java編程的 繼承、多態性、事件處理以及內部類這些內容嗎?Robocode 這個游戲為全世界的 Java 開發者實現這個愿望,它把游戲風潮變成了教學工具,人們對它的上癮程度令人吃驚。下面,我參考網友 Sing Li 以前寫的文章,讓我們一起來拆解 Robocode,同時著手建造屬于自己的、定制的、小而精悍的戰斗機器吧!
Robocode 是一個很容易使用的機器人戰斗仿真器,可以在所有支持 Java 2 的平臺上運行。您創建一個機器人,把它放到戰場上,然后讓它同其他開發者們創建的機器人對手拼死戰斗到底。Robocode 里有一些預先做好的機器人對手讓你入門,但一旦您不再需要它們,就可以把您自己創建的機器人加入到正在世界范圍內形成的某個聯盟里去和世界最強手對陣。
每個 Robocode 參加者都要利用 Java 語言元素創建他或她的機器人,這樣就使從初學者到高級黑客的廣大開發者都可以參與這一娛樂活動。初級的 Java 的開發者們可以學習一些基礎知識:調用 API 代碼、閱讀 Javadoc、繼承、內部類、事件處理等等。高級開發者們可以在構建“最優品種”的軟件機器人全球競賽中提高他們的編程技巧。在本文中,我們將介紹 Robocode,并指導您從構建您平生第一個 Robocode 機器人開始征服世界。我們還將看一下迷人的“后臺”機制,正是它使得 Robocode 起作用。
首先當然是下載和安裝 Robocode 啦
Robocode 是 Mathew Nelson 的智慧之作,他是 IBM Internet 部門 Advanced Technology 的軟件工程師。現在Robocode的主頁已經搬遷到sourceforge這個開源網站上了,大家可以在這里下載RobotCode的最新版http://robocode.sourceforge.net/?到3月21日為止最新版本是1.0.7,大小為3.2M。
好了,下載回來后當然還要在你的電腦上安裝JAVA運行庫才行的哦~地址是http://java.sun.com/getjava
1.先安裝好JAVA運行庫,好像需要重啟的?忘記了……
2.把下載回來的robocode-setup.jar復制到c盤根目錄
3.打開 開始菜單 的“運行”,輸入 java -jar "c:\robocode-setup.jar" 進行安裝
4.安裝完后就可以在開始菜單中找到Robocode的菜單了,來~我們進入戰場咯!
安裝完成后,您也可以通過 shell 腳本(robocode.sh)、批處理文件(robocode.bat)或桌面上的圖標來啟動 Robocode 系統。此時,戰場將會出現。在此,您可以通過菜單調用 Robot Editor 和 compiler。
Robocode 系統組件
當您啟動 Robocode 時,將看到兩個GUI窗口,這兩個窗口構成了 Robocode 的 IDE:
圖 1. Robocode IDE
戰場是機器人之間進行戰斗直至分出勝負的場地。主要的仿真引擎被置于其中,并且允許您在這里創建戰斗、保存戰斗以及打開新建的或現有的戰斗。通過界面區域內的控件,您可以暫停或繼續戰斗、終止戰斗、消滅任何機器人個體或獲取任何機器人的統計數據。此外,您可以在此屏幕上激活 Robot Editor。
Robot Editor 是一個定制的文本編輯器,它可以用于編輯生成機器人的 Java 源文件。在它的菜單里集成了 Java 編譯器(用于編譯機器人代碼)以及定制的 Robot 打包器。由 Robot Editor 創建并成功編譯的所有機器人都會處于戰場上一個部署就緒的位置。
Robocode 里的每個機器人都由一個或多個 Java 類構成。這些類可以被壓縮成一個 JAR 包。為此,Robocode 的最新版本提供了一個可以在戰場 GUI 窗口中激活的“Robot Packager”。
對 Robocode 機器人的詳細分析
在寫這篇文章時,Robocode 機器人是一個圖形化的坦克。圖 2 是一個典型的 Robocode 機器人的圖解。
圖 2. 對 Robocode 機器人的詳細分析
請注意,機器人有一門可以旋轉的炮,炮上面的雷達也是可以旋轉的。機器人坦克車(Vehicle)、炮(Gun)以及雷達(Radar)都可以單獨旋轉,也就是說,在任何時刻,機器人坦克車、炮以及雷達都可以轉向不同的方向。缺省情況下,這些方向是一致的,都指向坦克車運動的方向。
我們先不考慮怎么編程來實現機器人戰斗,我們先用自帶的例子機器人來一場戰斗吧
單擊菜單上的Battle,然后選New,出現了New Battle對話框
圖 3. New Battle 對話框
左邊的框是Packages,相當于一個文件夾,里面包含多個Robots(機器人)
我們選擇sample這個包,里面有Corners、Crazy、Fire等等很多例子的機器人了
隨便選擇幾個你喜歡的,然后按Add添加到Selected Robots框,進了這個框就是準備要上戰場的機器人了~選擇好后,按 StartBattle 開戰吧!
現在你已經知道怎樣可以使用機器人去戰斗并且也構建好你的戰場了,好,下面我們學習怎樣來編寫屬于自己的戰斗機器人!!
戰場是機器人之間進行戰斗直至分出勝負的場地。主要的仿真引擎被置于其中,并且允許在這里創建戰斗、保存戰斗以及打開新建的或現有的戰斗。通過界面區域內的控件,可以暫停或繼續戰斗、終止戰斗、消滅任何機器人個體或獲取任何機器人的統計數據。此外,我們可以在此屏幕上的Robot菜單打開 Editor,就是我們機器人的代碼編輯器了!Robot Editor 是一個定制的文本編輯器,它可以用于編輯生成機器人的 Java 源文件。在它的菜單里集成了 Java 編譯器(用于編譯機器人代碼)以及定制的 Robot 打包器。由 Robot Editor 創建并成功編譯的所有機器人都會處于戰場上一個部署就緒的位置。我們就是要在這里編寫機器人了。
選擇“File”》“New”》“Robot”來新建一個機器人。它會首先要你輸入這個機器人的名字(注意名字首字母要大寫哦),然后要你輸入包的名字(就是保存這個機器人的文件夾名稱),這樣就生成了一個蠢蠢的機器人XForce的代碼了~因為我們還沒替它加上人工智能,呵呵!
現在單擊菜單的Complie下的Complie進行編譯,保存好,我們的機器人已經生產出來咯~
現在關閉Editor,在進入New Battle,Pakeage下選擇你剛才的包的名字,Robot下就有了我們新建的XForce機器人了~添加進去吧,然后選擇多幾個其他的機器人,開始戰斗!
看~我們的XForce在戰斗了!
是否覺得它太蠢了點呢?來,繼續來學習~~
Robocode 機器人是一個圖形化的坦克,請注意,機器人有一門可以旋轉的炮,炮上面的雷達也是可以旋轉的。機器人坦克車(Vehicle)、炮(Gun)以及雷達(Radar)都可以單獨旋轉,也就是說,在任何時刻,機器人坦克車、炮以及雷達都可以轉向不同的方向。缺省情況下,這些方向是一致的,都指向坦克車運動的方向。
附:Robot 命令
Robocode 機器人的命令集都收錄在 Robocode API Javadoc 中。這些命令都是 robocode.Robot 類的公共方法。
(1)移動機器人、炮和雷達
移動機器人及其裝備的基本命令:
- turnRight(double degree) 和 turnLeft(double degree) 使機器人轉過一個指定的角度。
- ahead(double distance) 和 back(double distance) 使機器人移動指定的像素點距離;這兩個方法在機器人碰到墻或另外一個機器人時即告完成。
- turnGunRight(double degree) 和 turnGunLeft(double degree) 使炮可以獨立于坦克車的方向轉動。
- turnRadarRight(double degree) 和 turnRadarLeft(double degree) 使炮上面的雷達轉動,轉動的方向也獨立于炮的方向(以及坦克車的方向)。
這些命令都是在執行完畢后才把控制權交還給程序。此外,轉動坦克車的時候,除非通過調用下列方法分別指明炮(和雷達)的方向,否則炮(和雷達)的指向也將移動。
- setAdjustGunForRobotTurn(boolean flag):如果 flag 被設置成 true,那么坦克車轉動時,炮保持原來的方向。
- setAdjustRadarForRobotTurn(boolean flag):如果 flag 被設置成 true,那么坦克車(和炮)轉動時,雷達會保持原來的方向。
- setAdjustRadarForGunTurn(boolean flag):如果 flag 被設置成 true,那么炮轉動時,雷達會保持原來的方向。而且,它執行的動作如同調用了 setAdjustRadarForRobotTurn(true)。
(2)獲取關于機器人的信息
- getX() 和 getY() 可以捕捉到機器人當前的坐標。
- getHeading()、getGunHeading() 和 getRadarHeading() 可以得出坦克車、炮或雷達當前的方向,該方向是以角度表示的。
- getBattleFieldWidth() 和 getBattleFieldHeight() 可以得到當前這一回合的戰場尺寸。
(3)射擊命令
一旦掌握了移動機器人以及相關的武器裝備的方法,我們就該考慮射擊和控制損害的任務了。每個機器人在開始時都有一個缺省的“能量級別”,當它的能量級別減小到零的時候,我們就認為這個機器人已經被消滅了。射擊的時候,機器人最多可以用掉三個能量單位。提供給炮彈的能量越多,對目標機器人所造成的損害也就越大。 fire(double power) 和 fireBullet(double power) 用來發射指定能量(火力)的炮彈。調用的 fireBullet() 版本返回 robocode.Bullet 對象的一個引用,該引用可以用于高級機器人。(也就是說,當你確定能擊中對方,火力越大越好咯^_^)
(4)事件
每當機器人在移動或轉動時,雷達一直處于激活狀態,如果雷達檢測到有機器人在它的范圍內,就會觸發一個事件。作為機器人創建者,我們有權選擇處理可能在戰斗中發生的各類事件。基本的 Robot 類中包括了所有這些事件的缺省處理程序。但是,們可以覆蓋其中任何一個“什么也不做的”缺省處理程序,然后實現自己的定制行為。下面是一些較為常用的事件:
- ScannedRobotEvent。通過覆蓋 onScannedRobot() 方法來處理 ScannedRobotEvent;當雷達檢測到機器人時,就調用該方法。
- HitByBulletEvent。通過覆蓋 onHitByBullet() 方法來處理 HitByBulletEvent;當機器人被炮彈擊中時,就調用該方法。
- HitRobotEvent。通過覆蓋 onHitRobot() 方法來處理 HitRobotEvent;當您的機器人擊中另外一個機器人時,就調用該方法。
- HitWallEvent。通過覆蓋 onHitWall() 方法來處理 HitWallEvent;當您的機器人撞到墻時,就調用該方法。
很多研究Robocode的 玩家都被其中的方向及坐標弄糊涂了。整個屏幕哪個是0度角,整個是坐標原點呢? 順時針與逆時針的方向如何區分?
一段英文的翻譯及說明:
- heading - absolute angle in degrees with 0 facing up the screen, positive clockwise. 0 <= heading < 360.
- bearing - relative angle to some object from your robots heading, positive clockwise. -180 < bearing <= 180
- heading:是機器人方向與屏幕正上方的角度差,方向在0到360之間.
- bearing:是機器人的某個部件如雷達發現的目標與方向的角度差,順時針為正角度在-180到180之間
幾個在Robocode中很重要的概念:
- 坐標系:Robocode整個坐標系都是戰場屏幕以左下角為原點
- 絕對方向系:Robocode中不管機器人在哪個方向都是以靜態戰場屏幕為參照的絕對角度(也即大家說的Heading),正上方為0度角。也即不管是Robot,Gun,Radar向北為0,向東為90,向南為180,向西為270。
- 相對方向系:相對方向是Robot,Gun,Radar以機器人的動態heading角度為參照的角度差不再以整個靜態屏幕為參照了,叫它相對因為機器人的heading是隨著機器人移動而不停的在改變,heaing只是個相對物體。
- 順時針和逆時針是看另一機器人是在你的Heading角度的(0,180)還是(-180,0)之間。
再次提醒:Heading是個靜態角度,正上方總為0.不管是取Heading,還是取方向。Bearing是個角度差值,是由參照的Heading和發現時的Heading的差值。方向的問題就說到這,歡迎大家討論。
我看了Robocode的基礎知識,自己寫了個bot,放到BattleField上卻是屢戰屢敗……傷心ing。
Bot對于周圍環境的了解非常有限。它可以知道其它機器人的距離、方位、方向、速度和能量等級。但是,它看不到子彈。怎么才可以有效的躲避對方的子彈呢?
Bot雖然看不到子彈,但是對方的能量等級還是可以scan到了。對方只要發射子彈就會耗損能量,并且耗損的能量介于0和3之間。根據這些線索,如何發現其它機器人正向它開炮對于“笨笨”的Bot不就易如反掌了? ^_^
當Bot檢測到對方發射子彈的信息時,向左或向右移動一小步,嘿嘿,子彈就打不到咯~并且大多數Bot的瞄準方法是要么直接向目標開炮,要么試著根據Bot的速度和方向來推算位置。如果我的Bot不移動,兩種算法都會正好沖著這個Bot的當前位置開炮。哈哈哈,這時我的Bot再移動,不就全部都打不到啦。(是不是頗有武俠小說里以靜制動的高手味道?^_^)
下面是部分代碼和注釋:
double previousEnergy = 100;?//初始狀態對方能量為100
int movementDirection = 1;?//移動方向
int gunDirection = 1;?//炮管方向
/**
* 當檢測到對方Bot,觸發事件
* @param e
*/
public void onScannedRobot(ScannedRobotEvent e) {
//調整自己和對方之間的角度
setTurnRight(e.getBearing()+90-30*movementDirection);
//如果對方的能量損耗一定值,進行躲避動作
double changeInEnergy = previousEnergy - e.getEnergy();
if (changeInEnergy>0 && changeInEnergy<=3) {
//躲避!
movementDirection = -movementDirection;?//和上次的躲避方向相反
setAhead((e.getDistance()/4+25)*movementDirection);
}
//將炮管指向對方當前位置
gunDirection = -gunDirection;
setTurnGunRight(99999*gunDirection);
//射擊
fire(1);
//重新設置對方能量
previousEnergy = e.getEnergy();
}
是不是很簡單?這個技巧還存在問題。子彈一發射,我的Bot就移動,所以它最終可能會移回炮彈軌跡之內。最好是在估計子彈要到達時再移動。
我有個更大膽的假設:因為現在我的Bot命中率還不高,那么如果我的Bot一直不開火,只是躲避對方的子彈的話,能不能拖到對方的能量為0呢?確實存在一點問題。對方子彈一發射,我的Bot就移動,并且這個移動是規律的來回移動。如果移動距離短了,就可能在回來的時候撞到對方的子彈;如果移動距離長了,就等于做一個直線運動,對方很容易計算得到Bot的運動軌跡。還有一個問題,躲避的時候很有可能撞到墻上……(撞墻是要減energy的:~()
針對以上的問題,我另寫了一個Bot。代碼如下:
import robocode.*;
public class HanicBot extends AdvancedRobot{
private double eDist; //對方的距離
private double move; //移動的距離
private double radarMove = 45; //雷達移動的角度
private double dFirePower; //火力
/**
* main func run()
*/
public void run() {
eDist = 300;
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)超過指定的范圍,則反向移動move
if(x < 30 || x > dWidth-30 || y < 30 || y > dHeight-30){
setBack(move);
}
turnRadarLeft(radarMove); //轉動雷達
}
}//end run()
/**
* 當檢測到對方Bot,觸發事件
* @param e
*/
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);
}
}
首先,為了迷惑對方,不讓對方容易的得到Bot的移動規律,Bot就要在一定的時間內做出隨機的運動,這個很容易辦到。并且,我給Bot的運動改變時間規定了周期。這個周期隨離對方的距離改變,敵人越接近,周期越短,移動越頻繁。
double period = 4*((int)(eDist/80));
if(getTime()%period == 0){
move = (Math.random()*2-1)*(period*8 - 25);
setAhead(move + ((move >= 0) ? 25: -25));
}
其次,Bot的運動不是呈直線的。而是以對方為圓心的圓周運動。
setTurnGunRightRadians(robocode.util.Utils.normalRelativeAngle(
getHeadingRadians() + eBearing - getGunHeadingRadians()));
最后是如何避免撞墻。這里要用到點三角函數-_-!! 原理就是,計算Bot一次運動后將要達到的坐標是不是位于規定的危險區域。如果是,則立即反方向運動。
double heading = getHeadingRadians();
double x = getX() + move*Math.sin(heading);
double y = getY() + move*Math.cos(heading);
double dWidth = getBattleFieldWidth();
double dHeight = getBattleFieldHeight();
if(x < 30 || x > dWidth-30 || y < 30 || y > dHeight-30){
setBack(move);
}
這個Bot的威力如何?呵呵,我去測試一下先~
好了,就說到這里了,歡迎各大高手來踩……
關于其它的一些"編程游戲"?
有許多軟件是基于這種思想的,Robocode它自己就是來源于機器人大戰Robot Battle(http://www.robotbattle.com/)這款軟件。其它的編程游戲還包括:?
· AI Fleet Commander?
· AI Wars?
· AT-Robots?
· Bolo?
· BotWarz?
· C-Robots?
· Cadaver?
· CodedWombat?
· Colobot?
· Corewars?
· CybWar?
· GRobots?
· DroidBattles?
· Karel the Robot?
· Mindrover?
· IntelliBots?
· Omega?
· RealTimeBattle?
· Robot Wars?
· RoboWar?
· SRobots?
· VBRobots?
就我所看過的"編程游戲",Robocode是最簡單上手的。
· 它非常容易上手,是特別為教學而設計的?
· 它具有平滑且吸引人的圖形?
· 它完全地將編輯器,編譯器和運行環境集成在了一起。?
· 它是由JAVA編寫的,且JAVA非常適合當作初學語言
轉載于:https://www.cnblogs.com/jackrex/archive/2013/03/22/3001295.html
總結
以上是生活随笔為你收集整理的Robocode学习Java的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: web版本 开源压测工具_siege--
- 下一篇: st-link v2怎么连接_三相交流电