プログラムの基本方針
(畑さん)
めだかクラス:
<変数>
・めだかの位置
・めだかの色
・めだかの形
<メソッド>
・めだかクラスの生成(コンストラクタ)
- めだかの位置の決定
- めだかの色の決定(任意の色生成クラスのメソッドで作る)
・めだかを描画(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();
全体のソースは今回は載せません。試してみたい方は、説明を理解
した上で、自分で改造してみて下さいね。