用遊戲來學習java技術

Robocode(用遊戲來學習Java技術仍是用Java來玩遊戲?)
用你的JAVA編程技術來玩遊戲吧!不會JAVA?那就用遊戲來學習JAVA吧!
什麼是Robocode?html

其實我對機器人一直很感興趣。我記得在我仍是初中的時候,就知道 AplleⅡ上有一個程序,用它來編寫簡單的機器人程序,而後相互做戰。當時本身還徹底不懂編程,老是嚮往着,那神祕的編程高手玩的遊戲是怎樣的?java

Robocode就是這樣一個東西,可是更好一些。它是一個基於Java語言的機器人做戰遊戲。 其代碼的編寫和建模都不錯,玩起來也頗有趣。Robocode是不少"編程遊戲"軟件中的一個,他們共同的特徵是在沒有用戶輸入的狀態下許多機器人在一個及競技場中比賽,用戶必須編制一個高效的機器人來取勝。Robocode特別的像一場機器人坦克的大混戰,它們互相開火直到只剩一個勝利者。程序徹底是由JAVA編寫,而且玩家必需要創造一個繼承自Robot類的類。算法

你但願在玩遊戲的過程當中、在閃躲炮彈、執行精確攻擊的演練中學會Java編程的 繼承、多態性、事件處理以及內部類這些內容嗎?Robocode 這個遊戲爲全世界的 Java 開發者實現這個願望,它把遊戲風潮變成了教學工具,人們對它的上癮程度使人吃驚。下面,我參考網友 Sing Li 之前寫的文章,讓咱們一塊兒來拆解 Robocode,同時着手建造屬於本身的、定製的、小而精悍的戰鬥機器吧!shell

Robocode 是一個很容易使用的機器人戰鬥仿真器,能夠在全部支持 Java 2 的平臺上運行。您建立一個機器人,把它放到戰場上,而後讓它同其餘開發者們建立的機器人對手拼死戰鬥到底。Robocode 裏有一些預先作好的機器人對手讓你入門,但一旦您再也不須要它們,就能夠把您本身建立的機器人加入到正在世界範圍內造成的某個聯盟裏去和世界最強手對陣。編程

每一個 Robocode 參加者都要利用 Java 語言元素建立他或她的機器人,這樣就使從初學者到高級黑客的廣大開發者均可以參與這一娛樂活動。初級的 Java 的開發者們能夠學習一些基礎知識:調用 API 代碼、閱讀 Javadoc、繼承、內部類、事件處理等等。高級開發者們能夠在構建「最優品種」的軟件機器人全球競賽中提升他們的編程技巧。在本文中,咱們將介紹 Robocode,並指導您從構建您生平第一個 Robocode 機器人開始征服世界。咱們還將看一下迷人的「後臺」機制,正是它使得 Robocode 起做用。dom

首先固然是下載和安裝 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很是適合看成初學語言

原文出處:http://www.iplaysoft.com/robocode.html

相關文章
相關標籤/搜索