プログラムの基本方針
(畑さん) めだかクラス: <変数> ・めだかの位置 ・めだかの色 ・めだかの形 <メソッド> ・めだかクラスの生成(コンストラクタ) - めだかの位置の決定 - めだかの色の決定(任意の色生成クラスのメソッドで作る) ・めだかを描画(draw()メソッド) - インスタンス変数の「めだかの色」でめだかを描画 めだかアプレットクラス: <変数> ・めだか(Medakaクラス) <メソッド> ・初期化(めだかの生成 init()メソッド) - めだかクラスのインスタンスの生成 ・描画(めだかの描画 paint()メソッド) - めだかを描画する。(Medakaクラスのdraw()メソッドの呼び出し) 任意の色生成クラス: <変数> ・Randomクラス <メソッド> ・RGB値の決定 (このクラス内のみで利用されるメソッド ramdomRGBValue()メソッド) - インスタンス変数であるRandomクラスのインスタンスメソッドを 利用して0〜255までのあいだの任意の整数値を取得する。 ・任意の色の作成(randomColor()メソッド) - randomRGBValue()メソッドを利用して色の合成に必要なRGB値 を取得し、任意の色を作成する。
(しらかみさん) > Medaka(int x, int y) { > position = new Point(x, y); > } これが気持ち悪いです。 めだかが生まれる時に位置が決まるものでしょうか? とあるめだかが生まれる そのめだかを水槽に入れてあげる そのときにめだかの水槽内位置が決まる というのが自然な気がしませんか。 public class MedakaApplet extends java.applet.Applet { Medaka medaka; public void init() { medaka = new Medaka(100, 100); setBackground(Color.white); } public void paint(Graphics g) { medaka.draw(g); } } 随分すっきりしましたね。 これなら、めだかを2匹にするとかも簡単にできそう。
(中野さん) 位置は、めだかが属する世界のものなので、実際はその外の世界から 必要な時に与えられるものではないかと思われます。 私の考えていたモデルでは、メダカは自立して行動するものですから (最終的には、細かい形式はどうあれスレッドで実装する事になるはず です。) 表に対して見えているメソッドは、action()のみだろうと考えていました。 #便宜上、描画したりするためのメソッドは別の場合もある。 #本来なら、メダカが action() したと同時に、world の更新を行う #わけだが、その際、action() そのものに、(例えば)メダカを描画する #ルーチンと比べて時間がかかりすぎる場合は、恐らく、描画する #ルーチンを切り離して public で実装する事になるはず。 そのなかで、最初に perceive()して、内部的な action() を決定すると。 それに対して、表の世界は行動後のメダカの位置を要求するので #ここらへんは、意見の別れるところだと思います。 結局 class Medaka { public 3DPosition action(WORLD world); // もろもろの private なメソッド }; class WORLD { // メダカが存在している空間にあるオブジェクトへのリスト。 // または、メダカが存在している空間そのもの。 // 現在のメダカの空間相対な位置情報は、このクラスが保持している。 }; class 3DPosition { int x; int y; int z; // 他の座標系へのマッピング等のメソッド群 }; wG赴wN他の座標系へのマッピング等 めだかが返せる、3DPosition は、もちろん、前回に観察された時からの 相対位置情報です。ありていに言えば、前回観察された位置を原点とする ベクトルで表現するわけです。
めだかに色を付けたいので、ちょっと改造しました。(畑さん) 以下のようなソースにしました。 import java.awt.*; import java.applet.Applet; import java.util.Random; class Medaka { private Point position; private Color color; private String figure = ">^)))><"; Medaka(int x, int y) { position = new Point(x, y); Random random = new Random(); // *1 int red = random.nextInt() % 256; // *2 int green = random.nextInt() % 256; int blue = random.nextInt() % 256; if( red < 0 ) { // *3 red = -red; } if( green < 0 ) { green = -green; } if( blue < 0 ) { blue = -blue; } color = new Color(red, green, blue); // *4 } public void draw(Graphics g) { Color current = g.getColor(); g.setColor(color); g.drawString(figure,position.x,position.y); g.setColor(current); } } public class MedakaApplet extends Applet { Medaka medaka; public void init() { medaka = new Medaka(100, 100); setBackground(Color.cyan); } public void paint (Graphics g) { medaka.draw(g); } } *1 Randomクラス: 乱数を発生させることができるクラスです。めだかの色を指定 するために今回は乱数を使うことにしてます。 正確にいうと、めだかの色のを構成する光の3原色を乱数で 設定するためにRandomクラスを利用します。 *2 random.nextInt()メソッド: -2147483648〜214783647までの間の任意の整数値を返すメソッド random.nextInt % 256 の意味: 色を構成する3原色は、それぞれ0〜255までの256の値を持つこと が可能です。発生した値を0〜255の範囲の整数の値にするために % 256としています。なんで、色の範囲が256なのかはJDKのAPI ドキュメントに0〜255までと書いてたので。(^^;; %というのは、演算子で、例えば、10 % 3 とした場合、10を3で 割った場合の余りはいくらかを計算してくれる演算子です。 *3 if( red < 0 )の意味: 各原色の値は、正の整数値しか認めません。しかし、 red = random.nextInt() % 256では、-255〜255までの値になる可能性 があります。ゆえに、もしredが0以下の数値の場合は正の値にして あげる必要があります。ここでは、redの値が0より小さいかを比べて います。でもって、if(red < 0){・・・}の { 〜 }の間に、もし、 redが0より小さい場合の処理を記述します。ここでは、 if( red < 0 ) { // もし、redの値が0より小さい場合 red = -red; // redの値に-1をかけた値をredの値にする。 } という風になります。 *4 乱数で獲得した、各原色を元にしてColorクラスのインスタンスを生成 しています。
ここで畑さんがのせていたソースに自分なりにアレンジをしてみました。 (美里さん) import java.awt.*; import java.util.*; public class ColorMedaka{ private String figure = ">^)))><"; private Point position; private Color color; private int red, green, blue; ColorMedaka( int x, int y ){ position = new Point( x, y ); setColor(); } private void setColor(){ //1 Random random = new Random(); red = random.nextInt() % 256; green = random.nextInt() % 256; blue = random.nextInt() % 256; if( red < 0 ) { red = -red; } if( green < 0 ) { green = -green; } if( blue < 0 ) { blue = -blue; } color = new Color(red, green, blue); } private boolean match(){ //2 if( red == 0 && green == 255 && blue == 255 ){ return ( true ); } return ( false ); } public void DrawMedaka( Graphics g ){ Color current = g.getColor(); while( match() ){ //3 setColor(); } g.setColor( color ); g.drawString( figure, position.x, position.y ); g.setColor( current ); } } public class ColorMedakaApplet extends java.applet.Applet{ ColorMedaka medaka1, medaka2, medaka3; public void init(){ medaka1 = new ColorMedaka( 100, 100 ); medaka2 = new ColorMedaka( 100, 150 ); medaka3 = new ColorMedaka( 100, 200 ); resize( 300, 300 ); repaint(); setBackground( Color.cyan ); } public void paint( Graphics g ){ medaka1.DrawMedaka( g ); medaka2.DrawMedaka( g ); medaka3.DrawMedaka( g ); } } 1ですが、めだかの色をメソッドで行いました。 そのときのrandom, red, green, blueは局所変数ではなく インスタンス変数にしました。なぜなら、背景の色と めだかの色が一緒の時はめだかの色を再設定したかったからです。 そこで2で背景の色とめだかの色が等しいかをチェックしています。 背景の色は僕の場合init()でcyanに設定しているので、その色の RGB値と比較しています。 3で背景とめだかの色が等しければ何回でも再設定を行うように しています。(そんなことは起こらないとおもうんw注sうように =$N?' これで、万が一背景の色とめだかの色が一致したときの対処が できたと思います。
(佐藤さん) この「適当に色を決めてくれる物」を、RandomColorGeneratorとし ますと、めだかのコンストラクタはこのクラスのインスタンスを使っ て、適当な色を一つもらう、とすればすむ気がします。そして、こ のクラスは、他の適当な色が必要となる場面でも、そのまま利用す ることができるわけです。 というわけで、これをクラスとして定義してみると、こんなかんじ。 色の決め方は畑さんが示した方法と基本的に一緒です。 なお、import文は省略してありますので、適宜追加するか、Medaka アプレットのソースに組み込む必要が有ります。 class RandomColorGenerator { private Random randomNumberGenerator = new Random(); private randomRGBValue() { int value = randomNumberGenerator.nextInt() % 256; if (value < 0) { value = -value; } return value; } Color randomColor() { int red = randomRGBValue(); int green = randomRGBValue(); int blue = randomRGBValue(); return new Color(red, green, blue); } } red, green, blueの各値を決める部分も「RGBの値を適当に決める」 メソッドrandomRGBValueとしました。すると、「適当に色を決める」 方法は、「red, green, blueをそれぞれ適当に決めて、Colorのイ ンスタンスを作る」という一言で表せることになります。「RGBの 値を適当に決める」というのが、「0-255の範囲の乱数を得る」と いうことなのですが、それが「適当な整数の乱数を256で割った余 りを得て、絶対値を取る」という風に実現される、と。これまた一 言で言い表せるというわけですね。 これを使うと、先のコンストラクタはこんな感じになります。 Medaka(int x, int y) { position = new Point(x, y); color = generator.randomColor(); } この中で参照しているgeneratorは、staic変数で、内容は RandomColorGeneratorのインスタンス。つまり、Medakaクラスの定 義に、次の文が必要ということです。 private static RandomColorGenerator generator = new RandomColorGenerator(); 全体のソースは今回は載せません。試してみたい方は、説明を理解 した上で、自分で改造してみて下さいね。