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

目次

目標

  • 教科書にはない番外編として,自作関数(自分で作ったメソッド)に関する理解を得る
    • メソッドとは?
      • 与えられた値(引数)をもとに,定められた独自の処理を実行し,その結果を返す命令
      • 例: fillRect や fillOval など
        • fillRect メソッドの引数
          • 描画する四角形の左上の座標や幅,高さ
        • fillRect メソッドの独自の処理
          • 引数で指定されたウィンドウ内の位置に,指定された大きさの四角形を描画
        • fillRect メソッドで返されるもの(戻り値)
          • なし
    • メソッド(命令)は,自分で定義して使う(呼び出す)ことができる
      • メリット
        • 複数の命令を一つの命令にまとめることができ,(1) プログラムが分かりやすくなるだけでなく,(2) 同じような処理を何度も繰り返して書く必要がなくなる
    • メソッドは,引数の有無や戻り値の型などで分類される
      • 様々なメソッドを定義したり,使用したりできるようになるのが R5 の目標

メソッド(引数なし,戻り値なし)

定義と呼び出し方

  • Test クラス内に,引数と戻り値が共にないメソッドを定義する際には,以下の 2 行目のように書く
    • 「実行する命令(※)」の部分で,定義したメソッドを呼び出した際に実行される命令を書く

       1: public class Test {
       2:     public void メソッド名() {
       3:           実行する命令(※)
       4:     }
       5: 
       6:     public void run() {
       7:         ...
       8:         メソッド名();
       9:         ...
      10:     }
      11: }
      
  • 別のメソッド(例えば,run メソッド)から,定義したメソッドを呼び出すには,↑の例の 8 行目のように書けばよい

具体例

  • 以下のサンプルプログラムでは,以下を行っている

    • 引数と戻り値がない drawNumbers メソッドを Sample クラス内に定義している
    • 定義した drawNumbers メソッドを run メソッドから呼び出している
    public class Sample extends MyFrame2 {
    
        /** 0 から 9 までをウィンドウに表示するメソッドの定義(引数なし,戻り値なし) */
        public void drawNumbers() {
    
            int n = 10;    // 表示する数字の最大値 + 1
            int x = 50;    // 文字描画の左下 x 座標
            int y = 100;   // 文字描画の左下 y 座標
            int s = 20;    // 文字のサイズ
    
            for (int i = 0; i < n; i++) {
                drawString("" + i, x, y, s); // ウィンドウに i が表示される
                x += 25;
            }
        }
    
        public void run() {
            drawNumbers();  // 定義したメソッドを呼び出す
        }
    
        public static void main(String[] args) {
            new Sample();
        }
    }
    

    sample01.png

    図1: ↑のサンプルプログラムで表示されるウィンドウ

メソッド(引数あり,戻り値なし)

定義と呼び出し方

  • Test クラス内に,2 つの引数を持つメソッド(戻り値なし)を定義する際には,以下の 2 行目のように書く
    • 「実行する命令(※)」の部分で,定義したメソッドを呼び出した際に実行される命令を書く

       1: public class Test {
       2:     public void メソッド名(引数1の型 引数1, 引数2の型 引数2) {
       3:           実行する命令(※)
       4:     }
       5: 
       6:     public void run() {
       7:         ...
       8:         メソッド名(値1, 値2);
       9:         ...
      10:     }
      11: }
      
    • ※ 3 つの引数を持つメソッドを定義する際には,2 行目を以下のように書き換えればよい

      public void メソッド名(引数1の型 引数1, 引数2の型 引数2, 引数3の型 引数3) {
      
  • 別のメソッド(例えば,run メソッド)から,定義したメソッドを呼び出すには,↑の例の 8 行目のように書けばよい
    • 定義したメソッドを呼び出した際に,「値1」と「値2」がそれぞれ「引数1」と「引数2」に代入される
    • 注意:定義された引数の数だけ,値を指定して呼出さないとエラーとなる
      • ↑の例では,2つの引数のメソッドを定義しているので,値を 2 つ指定している

具体例

  • 以下のサンプルプログラムでは以下のメソッドを定義している
    • drawNumbers : n (int 型)を引数として持ち,0 から n-1 までの数字をウィンドウに表示する
    • drawNumbersWithSize : n (int型) と s (int型) の 2 つを引数として持ち,大きさ s で 0 から n-1 までの数字をウィンドウに表示する
  • また,定義した drawNumbers メソッドを run メソッドを呼び出している
    • 呼び出しの際に 8 が drawNumbers に与えられている
      • 0 から 7 までの数字がウィンドウに表示される(図 2)
    • 注意:以下のサンプルプログラムでは同じ名前の変数が定義されている
      • 例えば,以下の変数
        • drawNumbers メソッドの変数 x
        • drawNumberslWithSize メソッドの変数 x
      • このことに関しては,変数のスコープについて の項目を参考にすること

        public class Sample extends MyFrame2 {
        
            /** 0 から n-1 までの数字をウィンドウに表示するメソッドの定義(引数あり,戻り値なし) */
            public void drawNumbers(int n) {
        
                int x = 50;    // 文字描画の左下 x 座標 (★1)
                int y = 100;   // 文字描画の左下 y 座標
                int s = 20;    // 文字のサイズ
        
                for (int i = 0; i < n; i++) {    // △△
                    drawString("" + i, x, y, s); // ウィンドウに数字 i が表示される
                    x += 25;
                }
                // ★1 で定義されている変数 x のスコープはここまで (★2)
            }
        
            /** 大きさ s で 0 から n-1 までの数字をウィンドウに表示するメソッドの定義(引数あり,戻り値なし) */
            public void drawNumbersWithSize(int n, int s) {
        
                int x = 50;    // 文字描画の左下 x 座標 (★★1)
                int y = 100;   // 文字描画の左下 y 座標
        
                for (int i = 0; i < n; i++) {    
                    drawString("" + i, x, y, s); // ウィンドウに数字 i が表示される
                    x += 25;
                }
                // ★★1 で定義されている変数 x のスコープはここまで (★★2)
            }
            public void run() {
                drawNumbers(8);   // 定義したメソッドを呼び出し,0 から 7 までの数字を表示
            }
        
            public static void main(String[] args) {
                new Sample();
            }
        }
        

        sample02.png

        図2: ↑のサンプルプログラムで表示されるウィンドウ

参考:メソッド内で定義された変数の使用可能範囲(スコープ) について

  • それぞれの変数は,プログラムの中で使用できる範囲が決まっています
    • この範囲のことを「スコープ」と言います
    • Java では,ある変数のスコープの中に同じ名前の変数を定義することはできません
      • 逆にスコープが違っていれば,同じ名前の変数を定義して使用することができます
    • ここでは,いくつかのよくある変数のスコープについて簡単に説明します
  • メソッド内で定義された変数のスコープ
    • ↑のサンプルプログラムでは,以下の変数がメソッド内で定義された変数になります
      • drawNumbers メソッドの変数 n, x, y, s
      • drawNumbersWithSize メソッドの変数 n, s, x, y
    • スコープの始まり → 変数を定義した場所
    • スコープの終わり → メソッドの終わり
    • スコープの例
      • drawNumbers メソッドの変数 x のスコープは,★1〜★2
      • drawNumbersWithSize メソッドの変数 x のスコープは,★★1〜★★2
    • 別のメソッドで定義された変数はスコープが異なるため,変数名が同じでも問題ない
      • drawNumbers と drawNumbersWithSize のそれぞれのメソッドで変数 x が定義されていても問題ない
  • for 文のカウンタ変数のスコープ
    • 例:↑のサンプルプログラムにおける for 文のカウンタ変数 i
      • drawNumbers の △△ にある for 文の i など
    • スコープの始まり → for 文の始まり
    • スコープの終わり → for 文の終わり
    • △△ にある for 文のカウンタ変数 i を,この for 文の外で使用することはできない

メソッド(引数あり,戻り値あり)

定義と呼び出し方

  • Test クラス内に,2 つの引数を持つメソッド(戻り値あり)を定義する際には,以下の 2 行目のように書く
    • 「実行する命令(※)」の部分で,定義したメソッドを呼び出した際に実行される命令を書く

      • 最後に実行される命令として「return 戻り値;」を書く
        • 定義したメソッドの処理は,return 命令で終わる
        • 定義したメソッドの実行結果として,ここで書いた値が返される
       1: public class Test {
       2:     public 戻り値の型 メソッド名(引数1の型 引数1, 引数2の型 引数2) {
       3:           実行する命令(※)
       4: 
       5:           return 戻り値;
       6:     }
       7: 
       8:     public void run() {
       9:         ...
      10:         変数 = メソッド名(値1, 値2);
      11:         ...
      12:     }
      13: }
      
  • 別のメソッド(例えば,run メソッド)から,定義したメソッドを呼び出すには,↑の例の 10 行目のように書けばよい
    • 定義したメソッドを呼び出した際に,「値1」と「値2」がそれぞれ「引数1」と「引数2」に代入される
    • 定義したメソッドの実行後に,その戻り値が 10 行目の左辺の変数に代入される

具体例

  • 以下のサンプルプログラムでは,以下の仕様の min メソッドを定義している
    • min メソッドの仕様
      • 引数: 整数 a と 整数 b
      • 戻り値: a と b の小さい方の値
public class Sample extends MyFrame2 {

    /** a と b のうち小さい方を返すメソッドの定義(引数あり,戻り値あり) */
    public int min(int a, int b) {
        if (a < b) {
            return a;  // a の値を返して終了
        } else {
            return b;  // b の値を返して終了
        }
    }

    public void run() {
        int val = min(10, 15);    // min メソッドの実行後に,val には 10 が代入される
        drawString("" + val, 100, 100, 20);  // ウィンドウには 10 が表示される
    }

    public static void main(String[] args) {
        new Sample();
    }
}

sample03.png

図3: ↑のサンプルプログラムで表示されるウィンドウ

R5_1

準備

  • 以下の Line.java を作成せよ
    • Line.java

      public class Line extends MyFrame2 {
      
          /** a と b のうち小さい方を返すメソッド */
          public int min(int a, int b) {
              if (a < b) {
                  return a;
              } else {
                  return b;
              }
          }
      
          /** a の絶対値を返すメソッド */
          public int abs(int a) {
              if (a < 0) {
                  return -a;
              } else {
                  return a;
              }
          }
      
          public void drawHorizontalLine(int x0, int x1, int y) {
             // TODO: 座標 (x0, y) から座標 (x1, y) に水平線を描く
          }
      
          public void drawVerticalLine(int y0, int y1, int x) {
             // TODO: 座標 (x, y0) から座標 (x, y1) に垂直線を描く
          }
      
          public void drawRect(int x, int y, int w, int h) {
             // TODO: 左上の座標が (x, y) で,幅 w および 高さ h の四角形(塗りつぶし無し)を描画する(↑の 2 つのメソッドを使うこと)
          }
      
          public void run() {
             // TODO: drawRect メソッドを呼び出す
          }
      
          public static void main(String[] args) {
              new Line();
          }
      
      }
      

課題

  • 上記の Line.java にある空のメソッド(drawHorizontalLine, drawVerticalLine および drawRect) を R5_1 で作成するメソッドの仕様 を満たすように修正せよ
    • drawHorizontalLine : 水平線を描画するメソッド
    • drawVerticalLine : : 垂直線を描画するメソッド
    • drawRect : 塗りつぶし無し の四角形を描画するメソッド
  • また,Line.java にある run メソッドを以下の条件を満たすように修正し,図 4 に示すような \(n\) 個の四角形(塗りつぶし無し)を描画するプログラム(Line.java) を作成せよ
    • ※ 説明のために,四角形(塗りつぶし無し) には左上から順番に,0 番, 1 番, … \(n-1\) 番の番号が付けられているとする
    • 満たすべき条件
      • 描画する四角形の個数 \(n\) を変更できるようにすること
      • for 文を用い,その中でのみ drawRect を呼び出すこと
      • \(i\) 番目の四角形の左上の座標が \((10*i +20, 10*i + 80)\) となること
        • ※ \(i = 0, 1, ..., n-1\) とする
      • 全ての四角形の幅 \(w\) および高さ \(h\) は 50 とすること
    • レポートには,\(n\) を以下で与えた実行結果のスクリーンショットを貼り付けること
      • \(n\) = 「学籍番号の下 1 ケタ」 + 3
        • 例えば,学籍番号が 12345678 である時,\(n = 8 + 3 = 11\) となる

R5_1_3.png

図4: R5_1 で表示されるウィンドウの例 (\(n = 12\) の場合)

R5_1 で作成するメソッドの仕様

public void drawHorizontalLine(int x0, int x1, int y)

  • 引数
    • x0 : 始点の \(x\) 座標(int)
    • x1 : 終点の \(x\) 座標(int)
    • y : 始点と終点の \(y\) 座標(int)
  • 動作
    • 座標 (x0, y) から座標 (x1, y) までの水平線を描画する
      • fillRect を用いて,幅 |x0 - x1| + 1 で高さが 1 の四角形を表示すればよい
        • ※ fillRect には,四角形の左上の座標を指定する必要があることに注意せよ
          • 左上の座標はどのような座標か?
        • ※ filRect(x, y, w, 1) を呼出した時,座標 (x+w, y) は塗りつぶされないことに注意せよ
          • (x+w, y) まで塗りつぶすためには,fillRect の第 3 引数 に w+1 を指定しないといけない
  • 戻り値
    • なし

R5_1_1.png

図5: drawHorizontalLine メソッドで描画される水平線の例

public void drawVerticalLine(int y0, int y1, int x)

  • 引数
    • y0 : 始点の \(y\) 座標(int)
    • y1 : 終点の \(y\) 座標(int)
    • x : 始点と終点の \(x\) 座標(int)
  • 動作
    • 座標 (x, y0) から座標 (x, y1) までの水平線を描画する
      • fillRect を用いて,幅 1 および高さ |y0 - y1| + 1 の四角形を表示すればよい
  • 戻り値
    • なし

R5_1_2.png

図6: drawVerticalLine メソッドで描画される垂直線の例

public void drawRect(int x, int y, int w, int h)

  • 引数
    • x : 四角形の左上の \(x\) 座標(int)
    • y : 四角形の左上の \(y\) 座標(int)
    • w : 四角形の幅(int)
    • h : 四角形の高さ(int)
  • 動作
    • drawHorizontalLine メソッドと drawVerticalLine メソッドを呼び出して,四角形の水平線および垂直線を描画する
      • ただし,drawRect で描画する四角形の右下の座標は,fillRect と同様に (x+w-1, y+h-1) とすること
      • ※ 図 7 に示すような四隅の座標間に水平線や垂直線を引けばよい
  • 戻り値
    • なし

drawRect.png

図7: drawRect を描画する際に描画する水平線や垂直線の四隅の座標

R5_2

準備

  • 以下の Circle.java を作成する
    • Circle.java

      public class Circle extends MyFrame2 {
      
          public void fillOvalWithBorder(int x, int y, int r, int w) {
              // TODO: 枠線がある円(塗りつぶし有り)を描画
          }
      
          public void run() {
             // TODO: fillOvalWithBorder メソッドを呼び出す
          }
      
          public static void main(String[] args) {
              new Circle();
          }
      
      }
      

課題

  • 上記の Circle.java にある空の fillOvalWithBorder メソッドを R5_2 で作成するメソッドの仕様 を満たすように修正せよ
    • fillOvalWithBorder: 枠線がある円(塗りつぶしあり)を描画するメソッド
  • また,Circle.java にある run メソッドを以下の条件を満たすように修正し,図 8 に示すような \(n\) 個の円(塗りつぶしあり)を描画するプログラム(Circle.java) を作成せよ
    • ※ 説明のために,円(塗りつぶしあり) には左上から順番に,0 番, 1 番, … \(n-1\) 番の番号が付けられているとする
    • 満たすべき条件
      • 描画する円(塗りつぶしあり)の個数 \(n\) を変更できるようにすること
      • for 文を用い,その中でのみ fillOvalWithBorder を呼び出すこと
      • \(i\) 番目の円の左端と上端が \((45*i + 20, 80)\) となること
        • 枠線の太さ \(w\) は \(i+1\) とすること
        • ※ \(i = 0, 1, ..., n-1\) とする
      • 全ての円の半径 r は 20 とすること
    • レポートには,\(n\) を以下で与えた実行結果のスクリーンショットを貼り付けること
      • \(n\) = 「学籍番号を 5 で割った余り」 + 3
        • 例えば,学籍番号が 12345678 である時,\(n = 3 + 3 = 6\) となる

R5_2.png

図8: R5_2 で表示されるウィンドウの例 \((n = 8)\)

R5_2 で作成するメソッドの仕様

public void fillOvalWithBorder(int x, int y, int r, int w)

  • 引数
    • x : 円の左端の \(x\) 座標(int)
    • y : 円の上端の \(y\) 座標(int)
    • r : 円の半径(int)
      • ※ 枠線を含んだ半径とすること
    • w : 枠線の太さ(int)
  • 動作
    • 枠線の太さが w で半径 r の円(塗りつぶしあり)を描画する
      • ※ 以下の色で描画すること
        • 枠線の色 → 黒
        • 円の中を塗りつぶす色 → 白
      • fillOval を 2 回呼びだして,半径 r と半径 r-w の同心円を 2 つ描画すればよい
        • 半径 \(r-w\) の円を描画する時に,fillOval に指定する左上の座標をいくつにしたらよいか,ノートによく整理してからプログラムを作成すること

R5_3

準備

  • 以下の Digit.java を作成する
    • Digit.java

      public class Digit extends MyFrame2 {
      
          public int getDigit(int n, int k) {
              // TODO: 正の整数 n の k 桁目を数字返す(※桁 k は 1 オリジン)
          }
      
          public void run() {
             // TODO: getDigit メソッドを呼び出す
          }
      
          public static void main(String[] args) {
              new Digit();
          }
      
      }
      

課題

  • 上記の Digit.java にある空の getDigit メソッドを R5_3 で作成するメソッドの仕様 を満たすように修正せよ
    • getDigit: 与えられた正の整数 \(n\) を 10 進数で表記した際の下から \(k\) 桁目の数字(0〜9)を返すメソッド
      • ※ 例えば,\(n = 12345678\) で \(k = 2\) の時,getDigit(n, k) は 7 を返す
      • ※ 桁 \(k\) は 1 オリジンである(1 桁,2 桁,3 桁,… と数える)
  • また,Digit.java にある run メソッドを以下の条件を満たすように修正し,図 9 のように,整数 n を 10 進数で表記した際の各桁が逆順で表示されるプログラム(Digit.java) を作成せよ
    • 満たすべき条件
      • \(n\) を変更できるようにすること
      • for 文を用い,その中でのみ getDigit を呼び出すこと
        • for 文は k = 1, 2, …, 10 と変化させること
        • getDigit(n, k) の返り値 \(d\) を,drawString を用いて描画すること
          • ただし,drawString に与える左下の座標を \((30*k + 20, 80)\) とする
          • ※ drawString の第 1 引数を 「"" + d」 とすれば,返り値 \(d\) を描画できる
          • ※ drawString に与える文字サイズは 20 とすること
    • レポートには,\(n\) を以下で与えた実行結果のスクリーンショットを貼り付けよ
      • n = 自身の学籍番号

R5_3.png

図9: R5_3 で表示されるウィンドウの例 (n = 17045623 の場合)

R5_3 で作成するメソッドの仕様

public int getDigit(int n, int k)

  • 引数
    • n : 正の整数(int)
    • k : 桁(int)
  • 動作
    • 1. n を 10 で k-1 回割った値 \(m\) を求める
      • 割り算での小数点以下は切り捨てる
    • 2. \(m\) が 0 かどうかを調べる
      • \(m = 0\) ならば,\(k\) は \(n\) の桁数よりも大きいので \(-1\) (エラー)を return 命令で返す
      • \(m > 0\) ならば,\(m\) を 10 で割った余り \(r\) を計算し,\(r\) を return 命令で返す

R5_4 (オプション)

準備

  • 以下の Circle.java を作成する
    • Circle.java

      public class Circle extends MyFrame2 {
      
          public void drawCircle(int cx, int cy, int r) {
              // TODO: メソッドの中身を書く
          }
          public void run() {
              // TODO: drawCircle を呼出して,半径が異なる n 個の同心円を表示
          }
      
          public static void main(String[] args) {
              new Circle();
          }
      }
      

課題

  • Circle.java の中にある空の drawCircle メソッドを R5_4 で作成するメソッドの仕様 を満たすように修正せよ
    • drawCircle メソッド: 円(塗りつぶし無し) を描画する
  • また,Circle.java にある run メソッドを以下の条件を満たすように修正し,図 10 のように,半径が異なる \(n\) 個の同心円を描画するプログラム(Circle.java) を作成せよ
    • ※ 説明のために,円(塗りつぶし無し) には中心から外側に向けて,0 番, 1 番, … \(n-1\) 番の番号が付けられているとする
    • 満たすべき条件
      • \(n\) を変更できるようにすること
      • for 文を用い,その中でのみ drawCircle を呼び出すこと
      • すべての円の中心の座標が \((150, 150)\) となること
      • \(i\) 番目の円の半径 \(r\) が \((i+1)*10\) となること
        • ※ \(i = 0, 1, ..., n-1\) とする
    • レポートには,\(n\) を以下で与えた実行結果のスクリーンショットを貼り付けよ
      • \(n\) = 「学籍番号の下 1 ケタ」 + 3

R5_4.png

図10: R5_4 で作成するプログラムで表示されるウィンドウの例

R5_4 で作成するメソッドの仕様

public void drawCircle(int cx, int cy, int r)

  • 引数
    • cx : 円の中心 x 座標(int)
    • cy : 円の中心 y 座標(int)
    • r : 円の半径(int)
  • 動作
    • 座標 (cx, cy) を中心とした半径 r の円(塗りつぶし無し)を描画する
      • そのための簡易的な方法として,deg = 0°,1°,2°,3°, …, 359°の角度にある円周上の座標に点(1×1の正方形)を一つずつ描画していくものがある
        • ※ 別の方法で描画していってもいいが,この方法を用いたほうが R5_6 で作成するプログラムに変更しやすい
      • \(\theta\) [rad] の角度にある円周上の座標 \((x, y)\) に,1×1の正方形を描画するためには,どうしたらよいか?
        • 以下の式で座標 \((x, y)\) (実数)を計算し,fillRect((int)x, (int)y, 1, 1) を呼び出せばよい

          \begin{align} x &= r \cos \theta + cx \\ y &= r \sin \theta + cy \end{align}
          • ただし,\((cx, cy)\) および \(r\) はそれぞれ円の中心座標および半径である

          drawCircle_1.png

          図11: 円の円周上の座標 \((x, y)\) の計算式

    • 注意事項
      • \(\cos(x)\) および \(\sin(x)\) を計算する際ためには,Java ではそれぞれ Math.cos(x) および Math.sin(x) と書けばよい
        • この時,\(x\) の単位はラジアンであることに注意
          • deg [°] (0°〜 360°) から \(\theta\) [rad] (0 〜 \(2\pi\)) に Java で変換するには, Math.toRadians(deg) を用いればよい
      • 普段よく見る \(xy\) 座標とウィンドウの \(xy\) 座標では,\(y\) 軸が反転しているため,以下の図のような違いがあることに注意すること

        • ウィンドウの \(xy\) 座標では,上が 270°,角度の増加方向は時計回りである

        drawCircle_2.png

        図12: 普段よく見る \(xy\) 座標とウィンドウの \(xy\) 座標

  • 戻り値
    • なし

R5_5 (オプション)

課題

  • R5_4 で作成した Circle.java に,R5_5 で作成するメソッドの仕様 を満たす drawSpiral メソッドを追加せよ
    • drawSpiral メソッド: 渦巻を描画する
  • また,Circle.java にある run メソッドを以下の条件を満たすように修正し,図 13 のような渦巻を描画するプログラム(Circle.java) を作成せよ
    • 満たすべき条件
      • 合計 6 つの渦巻を 2 段に分けて描画すること
        • 上段: 左から順に,回転数 num = 1, 2, 3 の渦巻を描画すること
          • 初期角度 deg はどれも 0°
        • 下段: 左から順に,初期角度 deg = 90°,180°, 270°の渦巻を描画すること
          • 回転数 num はどれも 4
          • ただし,下段の一番左の渦巻には,参考のために,初期角度(=最終角度) deg = 90°を赤で示している

R5_5.png

図13: R5_5 で作成するプログラムで表示されるウィンドウの例

R5_5 で作成するメソッドの仕様

public void drawSpiral(int cx, int cy, int dist, int num, int deg)

  • 引数
    • cx : 渦巻の中心 x 座標(int)
    • cy : 渦巻の中心 y 座標(int)
    • dist : 渦巻の一番外側の座標と中心座標の距離(int)
    • num : 渦巻の回転数(int)
    • deg : 渦巻の初期角度(int)
      • ※ 単位は 「°(度)」とする
  • 動作
    • 中心座標 (cx, cy) から渦巻を描画していく
      • ヒント
        • drawCircle メソッドの仕様で説明した動作では,円周上の座標に点を描画していく際に半径 rad を固定していた
          • 角度の変化とともに,半径 rad を徐々に大きくしていったらどうなるか?
      • 渦巻の中心からの距離が dist となったら,描画を終わること
      • 描画を始めてから終わるまでの渦巻の回転数が num となること
        • そのため,初期角度で指定した deg が,描画の終了角度と一致する
  • 戻り値
    • なし

R5_6 (オプション)

準備

  • R5_1 で作成した Line.java をコピーする

課題

  • コピーした Line.java に,R5_6 で作成するメソッドの仕様 を満たす drawLine メソッドおよび drawDiamond メソッドを追加せよ
    • drawLine : 線分を描画するメソッド
    • drawDiamond : 菱形(塗りつぶしなし)を描画するメソッド
  • また,Line.java にある run メソッドを以下の条件を満たすように修正し,図 14 のように \(n\) 個の菱形(塗りつぶしなし)を描画するプログラム(Line.java) を作成せよ
    • ※ 説明のために,菱形(塗りつぶしなし) には中心から外側に向けて,0 番, 1 番, … \(n-1\) 番の番号が付けられているとする
    • 満たすべき条件
      • 描画する菱形の個数 \(n\) を変更できるようにすること
      • for 文を用い,その中でのみ drawDiamond を呼び出すこと
      • すべての菱形の中心の座標が \((200, 200)\) となること
      • \(i\) 番目の菱形の幅 \(w\) および高さ \(h\) がそれぞれ以下となること
        • ※ \(i = 0, 1, ..., n-1\) とする
        • 幅 \(w = 20 \times i + 50\)
        • 高さ \(h = 10 \times i + 100\)
    • レポートには,\(n\) を以下で与えた実行結果のスクリーンショットを貼り付けよ
      • \(n\) = 「学籍番号の下 1 ケタ」 + 3

R5_6.png

図14: R5_6 で表示されるウィンドウの例 \((n = 12)\)

R5_6 で作成するメソッドの仕様

public void drawLine(int x0, int y0, int x1, int y1)

  • 引数
    • x0 : 線分の端点 1 の \(x\) 座標(int)
    • y0 : 線分の端点 1 の \(y\) 座標(int)
    • x1 : 線分の端点 2 の \(x\) 座標(int)
    • y1 : 線分の端点 2 の \(y\) 座標(int)
  • 動作
    • 座標 (x0, y0) から座標 (x1, y1) までの線を描画する
      • 1×1の四角形を fillRect(x, y, 1, 1) を用いて少しづつ描画していけばいい
        • どのように描画していったらよいか自分で考え,レポートの方法にまとめよ
      • 2 つの座標間にだいたい線が引けていれば,線の綺麗さはそこまで求めない
        • もし綺麗に描画できない部分があったら,考察でどのような原因が考えられるかまとめてみよ
  • 戻り値
    • なし

public void drawDiamond(int cx, int cy, int w, int h)

  • 引数
    • cx : 菱形の中心 \(x\) 座標(int)
    • cy : 菱形の中心 \(y\) 座標(int)
    • w : 菱形の幅(int)
    • h : 菱形の高さ(int)
  • 動作
    • drawLine メソッドを 4 回呼出し,図 15 に示すような菱形を描画する
      • ※ MyFrame2 クラスに定義されている drawLine メソッドを呼び出すのは NG
  • 戻り値
    • なし

drawDiamond.png

図15: drawDiamond メソッドで描画される菱形

R5_7 (オプション)

準備

  • R5_4 (or R5_5) で作成した Circle.java と R5_6 で作成した Line.java を統合した,CircleAndLine.java を作成せよ
    • CircleAndLine.java 内で main メソッドや run メソッドが複数存在しないように気をつけること

課題

  • CircleAndLine.java に,R5_7 で作成するメソッドの仕様 を満たす drawClock メソッドを作成せよ
    • drawClock メソッド: 指定した時刻のアナログ時計を描画する
  • 作成した drawClock メソッドを run メソッドから呼び出し,指定した時刻(\(h\) 時 \(m\) 分)の状態の時計を描画するプログラム(CircleAndLine.java) を作成せよ
    • レポートには,\(h\) と \(m\) を以下で与えた実行結果のスクリーンショットを貼り付けよ
      • \(h\) : 学籍番号を 12 で割った余り
      • \(m\) : 学籍番号を 60 で割った余り

R5_7 で作成するメソッドの仕様

public void drawClock(int cx, int cy, int r, int h, int m)

  • 引数
    • cx : 時計の中心 x 座標(int)
    • cy : 時計の中心 y 座標(int)
    • r : 時計の大きさ(int)
    • h : 時間(0 〜 11 の整数) (int)
      • ※ 12時台の時刻は 0 時台の時刻とする
    • m : 分(0 〜 59 の整数) (int)
  • 動作
    • 以下の図のような時計を描画する
      • 時計の中心座標は (cx, cy) とすること
      • 時計を表す円の半径は r とすること
      • 与えられた時刻(h 時 m 分) に対応した位置に時針(短針と長針)を描画すること
        • R5_6 で作成した drawLine ではなく,MyFrame2 にある drawLine メソッドを使用してもよい
      • 時針から時刻が分かるように,時計の回りに数字の描画 or 時計に目盛の描画,を行うこと
        • 以下の図では,その両方の描画を行っている
  • 補足
    • プログラムの可読性を高めるために,以下のようなことを心掛けること
      • まず,時計の一部を描画するメソッド(例えば以下のようなメソッド)を作る
        • 円周上に 1 〜 12 の数字を描画するメソッド
        • 円周の内部に,主目盛と補助目盛の全てを描画するメソッド
        • \(h\) と \(m\) を入力として,長針と短針を描画するメソッド
      • つぎに,それらのメソッドを組み合わせて時計全体を描画する drawClock メソッドを作る

R5_7.png

図16: drawClock メソッドで描画される時計の例 (4 時 38 分の状態)

著者: Yusuke Sakumoto

Created: 2023-10-12 木 16:34

Validate