プログラミング実習I : 課題 R6

目次

目標

  • 教科書の 5 章の内容を理解し,Java によるアニメーションの方法を知る

R6_1

準備

  • 教科書 p.86 から p.100 までをよく読み,5 章の内容を理解する

課題

  • 以下の質問とその回答( 1 〜 3 行程度 )をレポートにまとめよ(プログラムの作成は行わなくてよい).
    1. sleep とはどのようなメソッドか? 引数や動作について簡潔に答えよ.
    2. clear とはどのようなメソッドか? 引数の有無や動作について簡潔に答えよ.
    3. break とはどのような命令か? 動作や用途について簡潔に答えよ.
    4. デバッグとは何か? 教科書にどのように書かれてあったか簡潔に答えよ.

R6_2

準備

  • リスト 5.1 およびリスト 5.2 の内容に基づく DisplayRectsSlow.java を作成し,実行せよ
    • ※ リスト 5.2 の Start.java にある main メソッドは,DisplayRectsSlow クラスに含めること
    • ※ MyFrame クラスではなく MyFrame2 クラスを用いること

課題

  • 準備で作成した DisplayRectsSlow.java を修正し,図 1 に示すような 20 個の四角形を 1 秒ごとに描画するプログラム(DisplayRectsSlow.java) を作成せよ
    • この条件 を満たすように DisplayRectsSlow.java を修正すること

R6_2.gif

図1: R6_2 で作成するプログラム(DisplayRectsSlow.java) で表示されるアニメーション(2倍速,ループ再生)の例 (w = 10)

条件

  • i 番に描画される四角形(以下,1 番目の四角形)は,プログラム開始から \(i\) 秒後に描画される
    • ※ \(i = 0, 1, ... , 19\) (以降も同様)
  • i 番の四角形の色は以下を満たす(※ カッコ内は RGB 値)
    • (a) i が 3 で割り切れる場合 → 赤(255,0, 0)
    • (b) i が 3 で割った時の余りが 1 である場合 → 黄緑(0,255, 0)
    • (c) i が 3 で割った時の余りが 2 である場合 → 青(0,0, 255)
  • i 番の四角形の左上の座標は (18*i + 10, 80) である
  • すべての四角形の幅 \(w\) は 5 から 15 の範囲で変えられるようにすること
    • レポートには,\(w\) を上記の範囲で好きな値に設定した場合の実行結果(スクリーンショット)を貼り付けること
  • i 番の四角形の高さ \(h\) は以下である
    • (d) i が 10 で割り切れる場合 → h = 100
    • (e) i が条件 (d) を満たさず,i が 5 で割り切れる場合 → h = 50
    • (f) i が条件 (d) および (e) を満たさず,\(i\) が 2 で割り切れる場合 → h = 20
    • (g) 条件 (d) 〜 (f) の全てを満たさない場合 → h = 10
  • i 番の四角形の上に i の値を描画すること
    • 文字の色は,白以外の好きな色でよい
      • 1 では,黒(0, 0, 0) を用いている

R6_3

準備

  • Animation.java のサンプルコード を持つ Animation.java を作成する
  • Animation.java にある fillCircleWithCC メソッドを fillCircleWithCC メソッドの仕様 を満たすように完成させよ
    • 完成させると,図 2 のように,円が左右に移動するアニメーションが表示される
      • 注意事項
        • 2 ではサンプルプログラムの理解のしやすさのために,以下を描画している
          • アニメーションの時刻 \(t\) (コマ番号)
            • コマが進む度に,時刻が 1 つ増える
            • ※ 以下のサンプルプログラムのままだと描画されないことに注意すること
          • 移動する円の中心座標 (x, y)
            • ※ 以下のサンプルプログラムのままだと描画されないことに注意すること
            • x は,55 〜 345 の間で変化する
            • y は,105 から変化しない
          • 移動する円が描画される範囲を示す以下の四角形
            • 左上 xy 座標 : (bx, by) = (50, 100)
            • 幅: w = 300
            • 高さ: h = 2*r

anime.gif

図2: 上記のサンプルプログラム(Animation.java)で表示されるアニメーション(ループ再生)

Animation.java のサンプルコード

public class Animation extends MyFrame2 {
    public static void main(String[] args) {
        new Animation();
    }

    /** 中心座標 (cx, cy) および半径 r の円を描画(色を整数 c = 0, 1, 他で指定)*/
    public void fillCircleWithCC(int cx, int cy, int r, int c) {
        // TODO
    }

    public void run() {

        int r = 5;     // 移動する円の半径
        int c = 1;     // 移動する円の色(0 → 赤, 1 → 黄緑, 他 → 青)

        int bx = 50;   // 四角形の左端の x 座標
        int by = 100;  // 四角形の上端の y 座標
        int w = 300;   // 四角形の幅
        int h = 2*r;   // 四角形の高さ

        int x0 = bx + r;      // 移動する円の中心 x 座標の最小値
        int x1 = bx + w - r;  // 移動する円の中心 x 座標の最大値
        int x = bx + r;      // 移動する円の中心 x 座標
        int y = by + r;      // 移動する円の中心 y 座標

        int dx = 5;    // 単位時間あたりの x 座標の変化量

        int animeT = 150;   // アニメーションの総コマ数
        double wtime = 0.1; // sleep に与える待機時間(コマの切り替えの間隔)

        for (int t = 0; t <= animeT; t++) {
            clear();   

            setColor(225, 225, 225);
            fillRect(bx, by, w, h);  // 円が移動する範囲を示す四角形を描画

            fillCircleWithCC(x, y, r, c);  // 中心座標(x, y) および半径 r の円を描画(色の設定が変わるので注意)
            x += dx;  // x 座標の変化

            if (x >= x1) {       // 右端に到達
                dx = -5;         // 移動方向を右から左に変更
            } else if (x <= x0){ // 左端に到達
                dx = 5;          // 移動方向を左から右に変更
            }

            sleep(wtime);
        }
    }
}

サンプルコードの解説

  • 円が四角形(灰色)の右端に到達した時の条件 (x >= x1) の可視化

    • 条件 (x >= x1) は,下図の青で描画された領域に対応する
      • ウィンドウの左に行くほど x 座標が小さくなることに注意
    • サンプルプログラムでは,円が青の領域に入ったら四角形(灰色)の右端に到達したと判断

    anime_right.png

    図3: 円が右端に到達した時の条件 (x >= x1) を可視化した図

  • 円が左端に到達した時の条件 (x <= x0) の可視化

    • 条件 (x <= x0) は,下図の赤で描画された領域に対応する
    • サンプルプログラムでは,円が赤の領域に入ったら四角形(灰色)の左端に到達したと判断

    anime_left.png

    図4: 円が左端に到達した時の条件 (x <= x0) を可視化した図

fillCircleWithCC メソッドの仕様

  • 概要
    • 中心座標 (cx, cy) を持つ半径 r の円を描画
  • 引数
    • cx : 円の中心 \(x\) 座標(int)
    • cy : 円の中心 \(y\) 座標(int)
    • r : 円の半径(int)
    • c : 円の色(int)
  • 動作
    • 中心座標 (cx, cy) および半径 r の円を fillOval を用いて描画する
      • ただし,色は以下とすること(※ カッコ内は RGB 値)
        • c が 0 の時 → 赤(255, 0, 0)
        • c が 1 の時 → 黄緑(0, 255, 0)
        • c が上記以外の時 → 青(0, 0, 255)
      • ※ fillOval に与える幅と高さは,ともに,2*r となることに注意

課題

  • 準備で作成した Animation.java を修正し,図 5 のように円が四角形の辺の内側を周回するアニメーションプログラム(Animation.java) を作成せよ
    • Animation.java は,この条件 を満たすように修正すること
    • 5 には,実行結果の理解のしやすさのために以下を描画している
      • アニメーション時刻 t
      • 円の中心座標 (x, y)
      • ※ 作成するプログラムでは,これらを描画する必要はない
  • 補足
    • 以下をノートに整理してから,プログラムの作成を始めること
      • 周回する円の中心座標 (x, y) の最小値および最大値
        • 図を書いて整理するとよい
      • 4 隅に到達した時に座標の変化量 (dx, dy) の値をどのように変えるべきか

R6_3.gif

図5: R6_3 で作成するプログラム(Animation.java) で表示されるアニメーション(2倍速,ループ再生)の例 (n = 5)

条件

  • 円に関して
    • 円の半径 r は 5 とすること (サンプルプログラムと同じ)
    • 中心座標 (x, y) の初期値は,(50 + r, 100 + r) とすること (サンプルプログラムと同じ)
    • 中心座標 (x, y) の変化量(dx, dy) の初期値は,(5, 0) とすること(初期の移動方向は「→」となる)
      • ※ dx は,中心 \(x\) 座標 x の変化量
      • ※ dy は,中心 \(y\) 座標 y の変化量
    • 円が四角形の 4 隅に到達したら円の移動方向が以下に変わるように,(dx, dy) の値を適切に変えること
      • 右上 : 「→」から「↓」
      • 右下 : 「↓」から「←」
      • 左下 : 「←」から「↑」
      • 左上 : 「↑」から 「→」
      • ※ 移動方向が変わっても,単位時間あたりの円の移動量は変化しないものとする
        • 単位時間あたりの円の移動量 = |dx| + |dy|
    • 円が四角形の 4 隅に到達したら,円の色を別の色に変化させること
      • 5 では,赤(c=0) → 黄緑(c=1) → 青(c=2) → 赤(c=0) → … と周期的に変化している
        • ただし,c は fillCircleWithCC メソッドの第 4 引数に与える値を格納した変数
      • ※ この図と同じように変化させる必要はない
  • 四角形に関して
    • 左上の座標 (bx, by) は (50, 100) とすること (サンプルプログラムと同じ)
    • 幅 w は 300 とすること (サンプルプログラムと同じ)
    • 高さ h は 230 とすること
    • 描画する際の色は,好きなものでよい
      • ただし,円の色と背景色(白)とは異なる色とすること
  • アニメーションに関して
    • アニメーションの総コマ数 animeT は 300 とすること
    • sleep に与える待機時間 wtime は 0.1 とすること (サンプルプログラムと同じ)
      • 注意: wtime を 0.05 などとすれば,プログラム作成時の動作確認を速く終えられるので,適宜,異なる wtime の値を用いてよい
        • ただし,プログラムを提出する際には,wtime を 0.1 に戻すこと

ヒント

  • 下図の 4 隅の青の領域に到達したことをそれぞれ判定すればよい
    • 右上隅の青の領域は 「x >= x1 かつ y <= y0」 で表現される
      • ウィンドウの上に行くほど y 座標が小さくなることに注意
    • 他の青の領域は,どのように表現されるか考えてみよ

R6_3_hint.png

図6: R6_3 で作成するプログラム(Animation.java) のヒント

R6_4

課題

  • R6_3 で作成した Animation.java を修正し,図 7 のように,円が四角形の辺にぶつかると跳ね返るアニメーションプログラム(Animation.java) を作成せよ.
    • 7 には,実行結果の理解のしやすさのために以下を描画している
      • アニメーション時刻 t
      • 円の中心座標 (x, y)
      • ※ 作成するプログラムでは,これらを描画する必要はない
    • Animation.java は,この条件 を満たすように修正すること
    • 補足
      • 円は,四角形内だけを移動するものと仮定してよい
      • 以下のことをノートに整理してから,プログラムの作成を始めること
        • 円と四角形の辺との当たり判定をどのように行えばよいか(円がどのような領域に入ったら当たったと判定するのか)
          • 円の中心座標 (x, y) の最小値および最大値は,R6_3 と同じであることに注意すること
        • 円が辺に跳ね返ってみえるようにするためには,どのように (dx, dy) を変えたらよいか

R6_4.gif

図7: R6_4 で作成するプログラム(Animation.java) で表示されるアニメーション(2倍速,ループ再生)の例 (n = 5)

条件

  • 円に関して
    • 円の半径 r は 5 とすること (R6_3 と同じ)
    • 中心座標 (x, y) の初期値は,(50 + r + 5*n, 100 + r + 5*n) とすること
      • ただし \(n\) は学籍番号の下 1 ケタ
      • ※ 図 7 には n = 5 の結果を示している
    • 中心座標 (x, y) の変化量(dx, dy) の初期値は,(5, 5) とすること
    • 四角形の辺に円がぶつかったら円が跳ね返ってみえるように,中心座標 (x, y) の変化量(dx, dy) を適切に変化させること
      • ただし,跳ね返った後に,円の移動量は変化しないものとする
    • 四角形の辺に円がぶつかったら,円の色を別の色に変化させること
      • 7 では,赤(c=0) → 黄緑(c=1) → 青(c=2) → 赤(c=0) → … と周期的に変化している
        • ただし,c は fillCircleWithCC メソッドの第 4 引数に与える値を格納した変数
      • ※ R6_3 で作成したプログラムと同じように変化させればよい
  • 四角形に関して (すべて R6_3 と同じ)
    • 左上の座標 (bx, by) は (50, 100) とすること
    • 幅 w は 300 とすること
    • 高さ h は 230 とすること
    • 描画する際の色は,好きなものでよい
      • ただし,円の色と背景色(白)とは異なる色とすること
  • アニメーションに関して (すべて R6_3 と同じ)
    • アニメーションの総コマ数 animeT は 300 とすること
    • sleep に与える待機時間 wtime は 0.1 とすること

R6_5 (オプション)

課題

  • R6_4 で作成した Animation.java を修正し,図 8 のように,円が 2 つの四角形(外側と内側)のどちらかの辺にぶつかると跳ね返るアニメーションプログラム(Animation.java) を作成せよ.
    • 8 には,実行結果の理解のしやすさのために以下を描画している
      • アニメーション時刻 t
      • 円の中心座標 (x, y)
      • ※ 作成するプログラムでは,これらを描画する必要はない
    • Animation.java は,この条件 を満たすように修正すること
    • 補足
      • 円は,外側の四角形内だけを移動するものと仮定してよい
      • 以下のことをノートに整理してから,プログラムの作成を始めること
        • 円と内側の四角形の辺との当たり判定をどのように行えばよいか
          • 外側の四角形の辺は内側からぶつかるのに対し,内側の四角形の辺は外側からぶつかることに注意しなければならない

R6_5.gif

図8: R6_5 で作成するプログラム(Animation.java) で表示されるアニメーション(2倍速,ループ再生)の例 \((n = 5)\)

条件

  • 円に関して
    • 円の半径 r は 5 とすること (R6_4 と同じ)
    • 中心座標 (x, y) の初期値は,(50 + r + 5*n, 100 + r + 5*n) とすること (R6_4 と同じ)
      • ただし n は学籍番号の下 1 ケタ
      • ※ 図 8 には n = 5 の結果を示している
    • 中心座標 (x, y) の変化量(dx, dy) の初期値は,(5, 5) とすること (R6_4 と同じ)
    • 外側と内側のどちらかの四角形の辺にぶつかったら円が跳ね返ってみえるように,中心座標 (x, y) の変化量(dx, dy) を適切に変化させること
      • ただし,跳ね返った後に,円の移動量は変化しないものとする
    • 外側と内側のどちらかの四角形の辺にぶつかったら,円の色を別の色に変化させること
      • 8 では,赤(c=0) → 黄緑(c=1) → 青(c=2) → 赤(c=0) → … と周期的に変化している
        • ただし,c は fillCircleWithCC メソッドの第 4 引数に与える値を格納した変数
      • ※ R6_4 で作成したプログラムと同じように変化させればよい
  • point に関して
    • point の初期値は 6 とすること
    • 内側の四角形の辺にぶつかったら,point を 1 つ減らすこと
    • 内側の四角形の中に,現在の point の値を表示すること
  • 外側の四角形に関して (すべて R6_4 と同じ)
    • 左上の座標 (bx, by) は (50, 100) とすること
    • 幅 w は 300 とすること
    • 高さ h は 230 とすること
    • 描画する際の色は,好きなものでよい
      • ただし,円の色と背景色(白)とは異なる色とすること
  • 内側の四角形に関して
    • 左上の座標は (w/2 - 45 , 100 + h/2 - 45) とすること
      • ※ w と h は,それぞれ外側の四角形の幅と高さ
    • 幅と高さは,ともに 90 とすること
    • 描画する際の色は,好きなものでよい
      • ただし,円の色と背景色,外側の四角形の色とは異なる色とすること
  • アニメーションに関して
    • アニメーションは,point が 0 以下になったら終了すること
    • sleep に与える待機時間 wtime は 0.1 とすること (R6_4 と同じ)

R6_6 (オプション)

課題

  • R6_4 で作成した Animation.java を修正し,図 9 のように,無限大を示す記号(∞)のような軌道上を円が移動しつつ,周期的に円の数が増えるアニメーションを表示するプログラム(Animation.java) を作成せよ
    • ※ 図 9 には,実行結果の理解のしやすさのために以下を描画している
      • アニメーション時刻 t
      • 原点を通過する水平線・垂直線
      • ※ 作成するプログラムでは,これらを描画する必要はない
    • Animation.java は,以下の 条件 を満たすように修正すること

R6_6.gif

図9: R6_6 で作成するプログラム(Animation.java) で表示されるアニメーション(2倍速,ループ再生)の例 \((n = 0)\)

条件

  • 円に関して
    • プログラム起動時には,円の数 ne は 0 とする
    • すべての円の半径 r は 5 とすること (R6_4 と同じ)
    • 時刻 \(t\) における \(i\) 番目の円の中心座標 \((x, y)\) は次式で与えられるとする(無限大のような軌道上を移動させるため)
      • ※ 説明のために,円には,生成された順に 0 番,1 番, … ne - 1 番の番号が付けられているとする

        \begin{align} x &= A \,\sin\left(\frac{\pi}{T} (t - i)\right) + ox\\ y &= A \,\sin\left(\frac{2\,\pi}{T} (t - i)\right) + oy\\ \end{align}
      • \(A\) は軌道の大きさを表す
      • \((ox, oy)\) は,軌道の中心座標
      • \(T\) は,\((ox, oy)\) を離れてから再び戻ってくるまでの時間(半周期)
      • \(i\) は円の番号でもあるが,移動の遅れの大きさでもある
        • 番号 i+1 の円は,常に,番号 i の後ろに位置することになる
    • 時刻 0, T+1, 2*(T+1), … で,新たな円を生成すること
      • ※ T は 50 とすること
      • すなわち,時刻 T+1 ごとに,円の数 ne が一つ増える
        • 例えば
          • t = 0 の時に,ne が 0 → 1 に変化する
          • t = 51 の時に,ne が 1 → 2 に変化する
          • t = 102 の時に,ne が 2 → 3 に変化する
    • ※ 生成された円は,円の列の最後尾に追加されることになる
      • 円が新たに生成された時,全ての円の色を別の色に変えること
        • 9 では,赤(c=0) → 黄緑(c=1) → 青(c=2) → 赤(c=0) → … と周期的に変化している
        • ※ 色の初期値は好きに決めてよい
        • ※ R6_4 で作成したプログラムと同じように変化させればよい
  • 式 (1) および式 (2) に関して
    • 軌道の中心座標 (ox, oy) は (200, 200) とすること
    • すべての円に対する軌道の大きさ \(A\) は,10*n + 100 とすること
      • ただし n は「学籍番号を 5 で割った余り」とすること
        • 9 では n = 0 の結果を描画している
  • アニメーションに関して
    • アニメーションの総コマ数 animeT は 500 とすること
    • sleep に与える待機時間 wtime は 0.04 とすること

R6_7 (オプション)

課題

  • R5_7 で作成した CircleAndLine.java を修正し,図 10 のような時計のアニメーションを実行するプログラム(CircleAndLine.java) を作成せよ
    • その際に,CircleAndLine.java に秒針の描画を追加すること
    • ※ 図 10 では,説明のしやすさのために時計で描画する時刻を表示しているが,作成するプログラムでは描画しなくてもよい
    • 時針・分針・秒針ともに,時計っぽく動くようになるべく工夫すること
      • アナログ時計をよく観察すること
      • 秒針は 1 秒ごとに動くが,分針や時針はどのようなタイミングで動くか? よく考えること.
      • 工夫したポイントをレポートの方法にまとめること
    • アニメーションでは,\(h\) 時 \(m\) 分 0 秒の状態で時計が開始し,その 5 分後の状態で時計が終了すること
      • ただし
        • \(h\) : 学籍番号を 12 で割った余り
        • \(m\) : 学籍番号を 60 で割った余り
    • 注意事項
      • 正確に時を刻む必要はない

R6_7.gif

図10: R6_7 で作成するプログラム(Animation.java) で表示されるアニメーション(5倍速,ループ再生)の例

著者: Yusuke Sakumoto

Created: 2023-10-25 水 16:20

Validate