イヤイヤするたまごっち applet

このページはヒントです。各自が考えなければ いけないところは ■■■■ となっています。 このまま入力しても動かないので注意して下さい。

画面の layout を考える

まず、画面の構成を考えましょう。 button を 1 個と絵が一つだけある applet を作ることを考えます。 作るべき applet を iyaiya.java に記述することにすると 書き出しは以下のようになるでしょう。
import java.awt.*;
import java.applet.*;

public class iyaiya extends Applet implements Runnable{
  Button gohan_bottun;
  Image img[] = new Image[2];
もちろん
Image img[];
としておいて、init() method のところで、
public void init() {
   img[] = new Image[2];
のようにしてもよいです。Image[2] の 2 は、画像が 2 枚(0 番めの絵と 1 番めの絵、2 枚の絵を連続的に提示することで「イヤイヤ」を表現するわけ です)であることを表しています。

課題では button の位置などの指定がありませんから、 とりあえず button を作っておきましょう。 作る場所はこの applet が最初に起動した直後に実行される init() method がよいです。作るための命令は GUI の章を参考に して下さい。作ったら add するのを忘れずに。

public void init() {
  gohan_button = new ■■■■;
  add(gohan_button);

動画の準備

init() の中では、animation に使うための 2 枚の画像を読み込んで おくことにしましょう。画像の読み込みに関しては、 GIF file の読み込みや、 Media Tracker が参考になるでしょう。 Media tracker を利用するためには、MediaTracker 用の変数を用意しておか なければならないので、init() method の前に、(すなわち object 変数とし て) MediaTracker 用の変数を用意しておきます。 すると以下のようになります。
import java.awt.*;
import java.applet.*;

public class iyaiya extends Applet implements Runnable{
  Button gohan_button;
  Image img[] = new Image[2];
  MediaTracker ■■■■; 

  public void init() {
    gohan_button = new ■■■■;
    add(gohan_button);

    ■■■■ = new MediaTracker(■■■■);
MediaTracker 用に変数が用意できたので、実際の画像を読み込んでおきます。
   for ( int i=0; i<2; i++ ){
     img[i] = getImage(getDocumentBase(), "iyaiya" + i + ".gif");
     ■■■■.addImage(img[i], 0);
     try {
            ■■■■.waitForID(0);
     } catch (InterruptedException e) {
            return;
     }
   }
本当は 2 枚しかない画像なので、 for 〜 loop を使っても使わなくてもどちらでもかまいません。

どうやって望む動作をさせるのか?

問題は button を押した時に、イヤイヤさせるわけですが、 パッと考えてもいくつかの解決策が思い浮かびます。
  1. thread の suspend(), resume() を使う。
  2. いつもは同じ絵を提示させておいて、特定の条件のときだけ動く ようにする
どっちでも正解です。ここでは、後者による解決策をとってみましょう。

Flag と呼ばれる boolean 型の object 変数を用意することで、 この変数が「真」であれば、ずっと同じ絵を表示し続け、 「偽」になった時に、あらかじめ決められた回数だけ、別の絵 と交替させるようにするわけです。 仮に、この object 変数を gokigen と名付けることにすると…

変数 gokigen が true ならば、止まっている。
変数 gokigen が false な間だけイヤイヤをする
となるわけです。最初は動かない(すなわちイヤイヤをしていない)わけだから、 この変数 gokigen は true に初期化しておくのがよいです。

さらに、何回「イヤイヤ」して首を振るかですが、実際には iyaiya0.gif と iyaiya1.gif を何回交替させるか、という問題になります。 首を振る回数を覚えておく int 型の変数 turned を導入しておく必要があり そうです。

もうひとつ imgID という int 型の変数も導入します。
iyaiya0.gif なら 0
iyaiya1.gif なら 1
を値として保持する変数だとしましょう。この変数を導入するメリットは paint() method が極端に簡単になるからです。

  public void paint(Graphics g) {
    g.drawImage(■■■■, 10, 30, this);
  }
以上で必要な object 変数が出そろいました。program の冒頭部分を まとめておくと以下のようになるでしょう。
import java.awt.*;
import java.applet.*;

public class iyaiya extends Applet implements Runnable {
  Thread th;
  Button gohan_button;
  Image img[] = new Image[2];
  MediaTracker ■■■■;

  boolean gokigen = ■■■■;
  int imgID = 0;
  int turned = 0;

Button の振舞いを決める

すると button の振舞いは、gokigen を false にする 仕事をすればよいだけです。
  public boolean action(Event e, Object arg) {
    if (e.target instanceof ■■■■) {
      String str = ((Button)e.target).getLabel();
      if ("gohan".equals(■■■■) ) {
	gokigen = ■■■■;
      }
      return true;
    } else
      return false;
  }

run() method の中身

run() の中では、変数 gokigen の真偽によって動作を変える 必要があるわけです。今まで学習してきた run() method では、
  public void run() {
    while (true) {
      try {
	Thread.sleep(1000);
      } catch (InterruptedException e) {
	break;
      }
      repaint();
    }
  }
のようになっていたわけですが、 (thread をよく調べておくように!) 変数 gokigen の状態によって動作を変えるために if 文が必要になります。
  public void run() {
    while (true) {
      if (■■■■) { 
	if (■■■■) {
	  turned = 0;
	  gokigen = ■■■■;
	}
        /* 
	この部分には…
        もし imgID が 0 だったら imgID を 1 にし、
        もし imgID が 1 だったら imgID を 0 にする、
        ような記述が必要です。うまく書くとたった一行です
        */
	repaint();
      }
      try {
	Thread.sleep(1000);
      } catch (InterruptedException e) {
	break;
      }
    }
最初の if 文の条件節内には、もし「ご機嫌斜め」だったら、 という意味の if 文になります。

次の if 文の条件節は、 続く{} の中で、イヤイヤをした回数 turned を 0 にしている ことから、 もし「イヤイヤを決められた回数だけ行った」のであれば、 という意味になりるようにすればよいのです。 ただし、同時に回数を一だけ増加させてしまうには、 どうすればよかったかを考えてください。 {} 内では、イヤイヤするのをやめるために gokigen をよくしておいてください。

本当は、イヤイヤしただけで gokigen がよくなってしまうのは ほんものの「たまごっち」とは異なるわけです。

program 全体の構造

まとめとして
public class iyaiya extends Applet implements Runnable {
には、いくつの method が必要なのかを書き出しておきます。
  1. public void init()
  2. public void run()
  3. public void start()
  4. public void stop()
  5. public void paint(Graphics g)
  6. public boolean action(Event e, Object arg)
当然、上記の method はどのような順番であっても正しく動作するはずです。 蛇足ですが…
<applet code=iyaiya.class width=150 height=120>
</applet>
という html file も必要です。

こんな感じに仕上がれば…



独力で作ろうとせず、このヒントを最後まで読んでしまった

あなた

には、素敵な present を差し上げましょう。
今回の課題は「ごはん」button を押すと、必ずイヤイヤをする 困った子だったわけです。 いつもイヤイヤして御飯をたべないと、おおきくなれないし、 お腹も減ってしまいます。 そこで...
  1. trained という int 型の変数と
  2. hungry という int 型の変数とを
導入してください。この2つの変数は、別の method が 変更してくれるように設計した方がよいですが、ここでは 次のようにしておきましょう。
まず、開始時に乱数を用いて trained は 0 から 4 までの 5 段階。同様に、hungry も 0 から 4 までの 5 段階で 初期化しておきます。
このような準備をしておいてから、 もし「ごはん」button がおされたら、0 から 8 までの乱数を 1 個発生させて、その値が hungry + trained より 大きければ、「イヤイヤ」する、ように progam を改造してみてください。
乱数を使うためには、
import java.util.Random;
というように、乱数用の package を import しておく必要があります。 それから、
Random rnd = new Random();
のように初期化してから使います。具体的に1個の乱数をとりだす 方法については、自分で調べましょう。

この課題は、出席率や課題提出率に不安がある人を救済するためのものです。