Robocode ワークショップ ~Javaに触れてみよう~

イントロダクション

Robocodeを使用して、Javaプログラミングを始めるきっかけとしてほしい、もしくはJavaという言語で遊べるということを紹介しようと考えました。

以前、Robocodeを紹介する記事を書きました。のでよかったらご覧ください。
そして、実際にワークショップを開きたいと考えております。そのために必要なことをまとめました。

ワークショップを開くための実行準備メモといったところです。

アジェンダ

そもそも「アジェンダ」って何よ?と思い、調べました。

会議で論ずる事項(議題)の表。比喩的に、課題項目。

つまり、「やることリスト」という理解です。

Robocodeアジェンダ

Robocodeのワークショップとして実行しようと考えているのは以下のものです。

  1. PCにRobocodeをインストールする
  2. サンプルバトルの起動、およびゲームの内容確認
  3. 自分のRoboの作成(コードは自動生成される)
    4.自分のRoboをバトルに参加させてみる
  4. Roboの動きとコードの内容を見比べて内容を大まかに理解する
  5. Javaコードを書いて、動きを変えてみる
  6. 動きを定義するメソッド「run」「onScannedRobot」「onHitByBullet」「onHitWall」の改造をしてみる
  7. 起動確認と実装アイディアの話し合い
  8. みんなで作成したRoboで対決する
  9. ワークショップの感想と今後の目標や、やりたいことの発表

この様なワークフローでワークショップを開こうと考えておりますが、必要になるものや、前もって調べておく(理解しておく)必要があるものがあるので、それを以下に記載いたします。

1.Robocodeをインストール

RobocodeのダウンロードはSourceForgeからできます。

そして、細かい情報はWikiがあります。

プログラミングに詳しくなくても、まったく問題ありません。このレベルのプログラミングは「アイディア」が最も重要です。

プログラムの細かい部分に関しては調べて理解すればよいし、もっと本格的な改造などを使用と考えなければJavaプログラミングをイチから学習する必要はありません。

もし、イチから学習したいと思ったらぜひやってください。
自分のお勧めする学習手順は以下のリンクにあります。よかったらどうぞ。

Java はじめて 学習フロー

2.サンプルバトルの起動、およびゲームの内容確認

実際にサンプルバトルを起動したときの画像が下のものになります。

早い話が、最後まで生き残ることがこのゲームの勝利条件です。

そのために、以下のメソッドに定義する処理(動き)を工夫して、他のプレーヤーに負けないようにすることが主な目的になります。

3.自分のRoboの作成(コードは自動生成される)

やり方に関しては、こちらの記事の「Roboを作る」に記載していますが、この部分は、チュートリアル的に作業を行う感じになります。

4.自分のRoboをバトルに参加させる

これは画面操作のみです。

  1. 新しバトルを開く

  2. 自作のRoboをバトルに追加する

5.Roboの動きとコードの内容を見比べて内容を大まかに理解する

Roboを動かす処理は大きく4つあります。

  1. 通常(デフォルト)の動き(run)
  2. 敵Roboをスキャンしたときの処理(onScannedRobot)
  3. 弾に当たったときの処理(onHitByBullet)
  4. 壁にぶつかったときの処理(onHitWall)

それぞれの動きを定義しているのが、上の強調表示している名前がそうです。この名前は、メソッドというものの名前になります。

Javaプログラミングのルール

Javaはプログラムをすべて「クラス」で表現します。そして、クラスの中には「フィールド変数(属性というときもあります)」と「メソッド(振る舞いを示す)」を定義することができ、「{}」で囲った部分がクラスとメソッドの範囲を示します。

クラスの書き方

/**
  * 「/**」出始めるコメント部分をJavaDocコメントといいます。
  */
public class クラス名 {
    /** JavaDocコメント */
    int 変数名;
    /**
     * JavaDocコメント、メソッドの説明
     */
    public 返り値 メソッド名(引数) {
        // 通常のコメント部分
        /*
         * 「/*」で始まるコメント部分は通常のコメントとして扱います。
         */
         // メソッドの処理を書きます。
    }
}

これはJavaプログラミングのルールなので、どんなクラスでも「フィールド変数」と「メソッド」の2つの要素が存在します。※必ずでこの2つがある必要はありません。

具体的には、下のようなコードです。※抜粋しています。

クラスの定義:作成したRoboの名前は「FirstRobot」

/**
 * FirstRobot - a robot by (your name here)
 */
public class FirstRobot extends Robot
{
   // 4つの動きを定義しているメソッドの定義があります。
}

そして、4つの動きにに対応する処理(メソッド)は以下のようになっています。

メソッドの定義:各アクションの定義

  1. 通常(デフォルト)の動き(run): ゲーム開始時のデフォルトの動きを定義します。

    /**
    * run: FirstRobot's default behavior
    */
    public void run() {
    aliveTime = 0;
    // Initialization of the robot should be put here
    showStatus();
    // After trying out your robot, try uncommenting the import at the top,
    // and the next line:
    
    // setColors(Color.red,Color.blue,Color.green); // body,gun,radar
    aliveTime = 0;
    // Robot main loop
    while(true) {
        // Replace the next 4 lines with any behavior you would like
        ahead(10);
        turnGunRight(360);
    }
    }
  2. 敵Roboをスキャンしたときの処理(onScannedRobot)

    /**
    * onScannedRobot: What to do when you see another robot
    */
    public void onScannedRobot(ScannedRobotEvent e) {
    // Replace the next line with any behavior you would like
    fireBullet(120);
    }
  3. 弾に当たったときの処理(onHitByBullet)

    
    /**
    * onHitByBullet: What to do when you're hit by a bullet
    */
    public void onHitByBullet(HitByBulletEvent e) {
    // Replace the next line with any behavior you would like

}


4. 壁にぶつかったときの処理(onHitWall)
```java
/**
 * onHitWall: What to do when you hit a wall
 */
public void onHitWall(HitWallEvent e) {
    // Replace the next line with any behavior you would like
    turnRight(90);
}

ちなみに、「弾に当たったとき」「壁にぶつかったとき」「スキャンしたとき」のように「~のとき」処理が動くような仕組みのことを「イベントハンドラ」と呼び、よく「~のイベントを受け取ったとき。。。」などのように話をします。

6.Javaコードを書いて、動きを変えてみる

上に示した、各イベントに対応するメソッド=「run」「onScannedRobot」「onHitByBullet」「onHitWall」に定義してある処理を変更してみます。
実際に使用できるコードはある程度決まっていて詳細に関しては、こちらのJavaDocというドキュメントに記述があります。

JavaDocとは

JavaDocはプログラムを書くときにクラスやメソッドの説明を書くときに使用するコメント文です。

そして、Roboを動かすために使用できるメソッドはこのリンク先に記載があります。

表にまとめると以下のようになります。

表A

返り値 メソッド名 振る舞い(処理の内容)
void ahead(double distance) ロボットを前方に移動させます。
void back(double distance) ロボットを後方に移動させます。
void doNothing() このロボットの今回の順番では、何も動作を行いません。
void finalize() システムによって呼び出され、ロボットのクリーンアップ (終結処理) を行います。
void fire(double power) 弾丸を発射します。
Bullet fireBullet(double power) 弾丸を発射します。
double getBattleFieldHeight() 現在のバトルフィールドの高さを取得します。
double getBattleFieldWidth() 現在のバトルフィールドの幅を取得します。
double getEnergy() ロボットの現在のエネルギーを戻します。
double getGunCoolingRate() 大砲の冷却速度を戻します。
double getGunHeading() 大砲の向きを 360 度形式で戻します。
double getGunHeat() 大砲の現在の熱さを戻します。
double getHeading() ロボットの現在の向きを 360 度形式で戻します。
double getHeight() ロボットの高さを戻します。
String getName() ロボットの名前を戻します。
int getNumRounds() 現在のバトルのラウンド数を戻します。
int getOthers() 敵ロボットの残り台数を戻します。
double getRadarHeading() レーダーの向きを 360 度形式で戻します。
int getRoundNum() 現在のラウンドが、 バトルの第何ラウンドかを戻します (1~getNumRounds() の範囲)
long getTime() 現在のゲーム時刻を戻します。
double getVelocity() このロボットの移動速度を戻します。
double getWidth() ロボットの幅を戻します。
double getX() ロボットの X 座標の位置を戻します。
double getY() ロボットの Y 座標の位置を戻します。
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 resume() stop() による停止中の動作があれば、その動作を再開します。
void run() 各ロボットのメイン・メソッド。
void scan() 他のロボットを探します。
void setAdjustGunForRobotTurn(boolean newAdjustGunForRobotTurn) ロボットが回転するときに、 大砲が自動的に逆方向に回転するように設定します。
void setAdjustRadarForGunTurn(boolean newAdjustRadarForGunTurn) 大砲が回転するときに、 レーダーが自動的に逆方向に回転するように設定します。
void setAdjustRadarForRobotTurn(boolean newAdjustRadarForRobotTurn) ロボットが回転するときに、 レーダーが自動的に逆方向に回転するように設定します。
void setColors(Color robotColor, Color gunColor, Color radarColor) このメソッドは、ロボットの色を設定するために呼び出します。
void stop() 動作をすべて停止し、 後で resume() 呼び出しを使って再開できるよう、保存します。
void stop(boolean overwrite) 動作をすべて停止し、 後で resume() 呼び出しを使って再開できるよう、保存します。
void turnGunLeft(double degrees) ロボットの大砲を回転させます。
void turnGunRight(double degrees) ロボットの大砲を回転させます。
void turnLeft(double degrees) ロボットを回転させます。
void turnRadarLeft(double degrees) ロボットのレーダーを回転させます。
void turnRadarRight(double degrees) ロボットのレーダーを回転させます。
void turnRight(double degrees) ロボットを回転させます。

JavaDocには詳細な情報が記述されているので、このドキュメントを読んで理解できるとかなり強いプログラマーとして君臨できます(笑)

とりあえずは、JavaDocにあるメソッドを実装して動かしてみるのが、一番です。

7. 動きを定義するメソッド「run」「onScannedRobot」「onHitByBullet」「onHitWall」の改造をしてみる

具体的に実装を行います。JavaDocを参考に、各メソッドにそれぞれのメソッドを実装し、プログラムを実行して動きを確認してみます。

以前作成した動画で丁度良いのがあったのでそれを載せます。

具体的には、デフォルトの動き「run()」メソッドの定義と動きを確認してモノです。

ポイントとしては以下の通りです。上に記載した表Aから抜粋しました。 返り値 メソッド名 振る舞い(処理の内容)
void ahead(double distance) ロボットを前方に移動させます。
void back(double distance) ロボットを後方に移動させます。

コードとしては、次のようなものです。

while(true) {
   ahead(100);
   turnGunRight(360);
   back(100);
   turnGunRight(360);
}

下の「while(true)」と書いてある部分は次に書いてある「{」から「}」までの間を無限ループする処理を書いています。デフォルトの動きなので、無限ループしている処理なのでしょう。

8. 起動確認と実装アイディアの話し合い

上の表Aから各メソッドの中に、それぞれのコードを書いたり消したりしながら、Roboを最強な動きにできるように、アイディアを出し合ったり、プログラムの内容を理解したり、みんなでワイワイやると面白いだろうな、というのが自分の思惑ですが、果たしてどうなるでしょうか?

9. みんなで作成したRoboで対決する

この部分に関しては、Robocodeのウェブサーバーがあるのでそれをダウンロード、起動といった準備が必要になります。

この部分に関しては、後日追記します。

でわでわ。。。

Robocodeの記事はこちらです。

投稿者:

takunoji

音響、イベント会場設営業界からIT業界へ転身。現在はJava屋としてサラリーマンをやっている。自称ガテン系プログラマー(笑) Javaプログラミングを布教したい、ラスパイとJavaの相性が良いことに気が付く。 Spring framework, Struts, Seaser, Hibernate, Playframework, JavaEE6, JavaEE7などの現場経験あり。 SQL, VBA, PL/SQL, コマンドプロント, Shellなどもやります。

コメントを残す