プログラミング実習I : 課題 R10
目標
- 教科書の 8 章の内容を理解し,クラスの継承に関する基礎知識を得る
R10_1
準備
- 教科書 p.146 から p.166 までをよく読み,8 章の内容を理解する
課題
- 以下の質問とその回答( 1 〜 3 行程度 )をレポートにまとめよ(プログラムの作成は行わなくてよい)
- 1. 8 章で説明されている Car クラスと Train クラスの共通する部分は何か? 教科書で挙げられているものを全て答えよ.
- 2. 教科書の説明に従って,以下のことを「継承」という言葉を使って説明するとどうなるか?
- Person クラスが持つ性質や動作を Student クラスや Teacher クラスが受け継ぐこと
- 3. 質問 2 における親クラスと子クラスは何か?
- 4. Truck クラスを新たに作成し,Vehicle クラスの子クラスとしたい.どのようにクラスの宣言(public class …) を始めればよいか? 宣言の 1 行目を答えよ.
- R10_2 に取り組みながら,以下の質問とその回答( 1 〜 3 行程度 )をレポートにまとめよ
- 5. 図 8.3 に示されているエラーの原因と解決方法は何か?
- 6. super という命令は何か? 教科書の記述に基づいて説明せよ.
- 7. 以下の (a) と (b) を比較した時,(b) が (a) より優れている点は何か?
- (a) リスト 8.9 の Vehicle.java とリスト 8.10 の Car.java, リスト 8.11 の Train.java
- (b) リスト 8.18 の Vehicle.java とリスト 8.21 の Car.java, リスト 8.22 の Train.java
- R10_3 に取り組みながら,以下の質問とその回答( 1 〜 3 行程度 )をレポートにまとめよ
- 8. リスト 8.25 で発生したエラーの原因と解決方法は何か?
- 9. リスト 8.26 で発生したエラーの原因と解決方法は何か?
R10_2
準備
- まず,以下の内容を持つ 4 つのプログラムを作成し,DisplayCarTrain.java を実行せよ
DisplayCarTrain.java (※ リスト 8.5 がベース)
public class DisplayCarTrain extends MyFrame2{ public void run() { Car car1 = new Car(10, 50, 3, 0); car1.draw(this); Train train1 = new Train(30, 150, 3, 0); train1.draw(this); } public static void main(String[] args) { new DisplayCarTrain(); } }
Vehicle.java (※ リスト 8.9 と同じ)
public class Vehicle { }
Car.java (※ リスト 8.10 がベース)
public class Car extends Vehicle { int x, y, vx, vy; public Car (int x, int y, int vx, int vy) { this.x = x; this.y = y; this.vx = vx; this.vy = vy; } public void draw(MyFrame2 frame) { frame.fillRect(x+20, y, 40, 20); frame.fillRect(x, y+20, 80, 20); frame.fillOval(x+10, y+40, 20, 20); frame.fillOval(x+50, y+40, 20, 20); } public void move() { x += vx; y += vy; } }
Train.java (※ リスト 8.11 がベース)
public class Train extends Vehicle { int x, y, vx, vy; public Train (int x, int y, int vx, int vy) { this.x = x; this.y = y; this.vx = vx; this.vy = vy; } public void draw(MyFrame2 frame) { frame.fillRect(x, y, 100, 30); frame.fillOval(x+5, y+30, 10, 10); frame.fillOval(x+15, y+30, 10, 10); frame.fillOval(x+75, y+30, 10, 10); frame.fillOval(x+85, y+30, 10, 10); } public void move() { x += vx; y += vy; } }
- 手順 1 で作成した Vehicle.java,Car.java および Train.java を 8.3.1 節〜8.3.3節の内容に従って修正せよ
- 8.3.1 節の内容: Car クラスと Train クラスで共通するフィールドを Vehicle クラスに移動
- 8.3.2 節の内容: Car クラスと Train クラスで共通する move メソッドを Vehicle クラスに移動
- 8.3.3 節の内容: Vehicle クラスにコンストラクタを作成し,そのコンストラクタを Car クラスと Train クラスから呼び出すように修正
課題
- 準備で作成した以下のプログラムを,それぞれの仕様を満たすように変更せよ
- Vehicle.java : R10_2 で作成する Vehicle クラスの仕様
- フィールドの追加とコンストラクタの修正が必要
- Car.java : R10_2 で作成する Car クラスの仕様
- コンストラクタと draw メソッドの修正が必要
- ※ R7_4 で作成した Car クラスの draw メソッドをコピー & ペーストすればよい
- コンストラクタと draw メソッドの修正が必要
- Train.java : R10_2 で作成する Train クラスの仕様
- コンストラクタ と draw メソッドの修正が必要
- 修正ができたら Train クラスのテスト を実施し,正しく動作することを確認せよ
- Vehicle.java : R10_2 で作成する Vehicle クラスの仕様
- 準備で作成した DisplayCarTrain.java を修正し,以下の図のように自動車と電車が描画されるようにせよ
- 以下の 条件 を満たすように DisplayCarTrain.java を修正すること
実行例
図1: R10_2 で作成するプログラムで表示されるウィンドウの例
条件
- 自動車(Car クラスのオブジェクト) は,以下を満たす
- 中心座標 (100, 100)
- 幅と高さ (100, 60)
- 中心座標の変化量 (0, 0)
- 電車(Train クラスのオブジェクト) は,以下を満たす
- 中心座標 (200, 200)
- 幅と高さ (80, 60)
- 中心座標の変化量 (0, 0)
- 自動車と電車の色は好きなものでよい
提出物
- 作成した Car.java
- 作成した Train.java
- 作成した Vehicle.java
- 作成した DisplayCarTrain.java
R10_2 で作成する Vehicle クラスの仕様
フィールド
- x : 乗り物の中心 \(x\) 座標(int)
- y : 乗り物の中心 \(y\) 座標(int)
- w : 乗り物の幅 (int) (※R10_2 で追加)
- h : 乗り物の高さ (int) (※R10_2 で追加)
- vx : 乗り物の中心 \(x\) 座標の変化量(int)
- vy : 乗り物の中心 \(y\) 座標の変化量(int)
コンストラクタ
- public Vehicle(int x, int y, int w, int h, int vx, int vy)
- 引数
- x : 乗り物の中心 \(x\) 座標
- y : 乗り物の中心 \(y\) 座標
- w : 乗り物の幅 (※R10_2 で追加)
- h : 乗り物の高さ (※R10_2 で追加)
- vx : 乗り物の中心 \(x\) 座標の変化量
- vy : 乗り物の中心 \(y\) 座標の変化量
- 動作
- 引数で与えられた値を,各フィールドに代入する
- 引数
メソッド
- public void move()
- 動作
- 中心座標の変化量 (vx, vy) だけ,中心座標 (x, y) を変化させる
- 動作
R10_2 で作成する Car クラスの仕様
コンストラクタ
- public Car(int x, int y, int w, int h, int vx, int vy)
- 引数 (※R7_4 と同じ)
- x : 自動車の中心 \(x\) 座標
- y : 自動車の中心 \(y\) 座標
- w : 自動車の幅
- h : 自動車の高さ
- vx : 自動車の中心 \(x\) 座標の変化量
- vy : 自動車の中心 \(y\) 座標の変化量
- 動作
- 引数で与えられた値を用いて親クラスのコンストラクタを呼び出す
- 引数 (※R7_4 と同じ)
メソッド
- public void draw(MyFrame2 frame) (※R7_4 と同じ)
- 引数
- frame : MyFrame2 クラスのオブジェクト
- 動作
- 自動車を以下の図のレイアウトで描画する
- ※ タイヤの半径は h/6
※ フィールドの (x, y) は, 自動車の中心座標 であることに注意すること!
図2: 自動車のレイアウト
- 自動車を以下の図のレイアウトで描画する
- 引数
R10_2 で作成する Train クラスの仕様
コンストラクタ
- public Train(int x, int y, int w, int h, int vx, int vy) (※R10_2 で作成する Car クラスと同じ)
- 引数
- x : 電車の中心 \(x\) 座標
- y : 電車の中心 \(y\) 座標
- w : 電車の幅
- h : 電車の高さ
- vx : 電車の中心 \(x\) 座標の変化量
- vy : 電車の中心 \(y\) 座標の変化量
- 動作
- 引数で与えられた値を用いて親クラスのコンストラクタを呼び出す
- 引数
メソッド
- public void draw(MyFrame2 frame)
- 引数
- frame : MyFrame2 クラスのオブジェクト
- 動作
電車を以下の図のレイアウトで描画する
- ※ タイヤの直径は h/6
- ※ タイヤは,中心を通る垂線を軸として左右対称に配置されている
- ※ フィールドの (x, y) は, 電車の中心座標 であることに注意すること!
図3: 電車のレイアウト
- 引数
Train クラスのテスト
- draw メソッド
Train.java に以下の main メソッド(テストコード)を追加して実行し,図 4 のように描画されれば ok
public static void main(String[] args) { int ww = 400, wh = 400; int cw = 160, ch = 120; int cx = ww/2, cy = wh/2; MyFrame2 f = new MyFrame2(); Train c = new Train(cx, cx, cw, ch, 0, 0); c.draw(f); int wu = cw/8; int hu = ch/6; f.setColor(255, 0, 0); for (int i = 0; i <= 8; i++) { f.drawLine(cx + (i-4)*wu , 0, cx+ (i-4)*wu, wh); } for (int i = 0; i <= 6; i++) { f.drawLine(0, cy + (i-3)*hu, ww, cy + (i-3)*hu); } }
テストの実行結果
図4: Train クラスの draw メソッドのテスト結果
R10_3
準備
- R10_2 で作成した以下をコピーせよ
- Car.java
- Train.java
- Vehicle.java
- DisplayCarTrain.java
課題
- R10_2 で作成した以下のプログラムを,それぞれの仕様を満たすように変更せよ
- Vehicle.java : R10_3 で作成する Vehicle クラスの仕様
- リスト 8.27 を参考にして,draw メソッドおよび changeMove メソッドの追加が必要
- changeMove メソッドとは?
- 垂直線をまたいだ時に,乗り物の移動がどのように変化するかを定義するメソッド
- Car.java : R10_3 で作成する Car クラスの仕様
- changeMove メソッドの追加が必要
- Train.java : R10_2 で作成する Train クラスの仕様
- changeMove メソッドの追加が必要
- Vehicle.java : R10_3 で作成する Vehicle クラスの仕様
- リスト 8.29 を参考に,図 5 のように,時間とともに乗り物(自動車 or 電車)が生成され,生成された乗り物の移動が垂直線を越えた際に変化するアニメーションプログラム(DisplayCarTrain.java) を作成せよ
条件
- R7_4 と R8_4 と同様に,ウィンドウの幅と高さを (600, 500) にすること
- run メソッドの冒頭で setSize(600, 500) を実行すること
- アニメーションに関して,以下とすること
- アニメーション総コマ数 = 200
- sleep に与える待機時間 = 0.1
- 垂直線(x = b) の b は 550 とすること
- drawLine を用いて,垂直線 (x = 550) を描画すること
- 色は好きな色でよい
- drawLine(550, 0, 550, 500) と書けばよい
- drawLine を用いて,垂直線 (x = 550) を描画すること
- 乗り物(Vehicle クラスのオブジェクト)に関して,以下とすること
- 生成した乗り物(Car クラスと Train クラスの両方のオブジェクト)は Vector オブジェクトで管理すること (※リスト 8.29 を参考に)
- 時刻 i が 7 の倍数である場合,「これまでに生成した乗り物の台数 nc」に応じて以下の処理を行うこと
- nc が偶数である場合,以下の自動車(Car クラスのオブジェクト)を 1 台生成する
- 自動車の中心座標の初期値を (50, 350) とすること (R8_4 でのエリア 0 で発生する自動車と同じ)
- 幅と高さ
高さと幅は (32, 24) とすること (R8_4 と同じ) - 中心座標の変化量を (10, -v) とすること
- v は,nc を 7 で割った余りとする
- nc が奇数の場合,電車(Train クラスのオブジェクト) を 1 台生成する
- 電車の情報は,↑の自動車を電車に読み替えたものとする
- nc が偶数である場合,以下の自動車(Car クラスのオブジェクト)を 1 台生成する
- それぞれの乗り物の色は好きなものでよい
提出物
- 作成した Car.java
- 作成した Train.java
- 作成した Vehicle.java
- 作成した DisplayCarTrain.java
R10_3 で作成する Vehicle クラスの仕様
フィールド
- R10_2 と同じ
コンストラクタ
- R10_2 と同じ
メソッド
- public void move()
- R10_2 と同じ
- public void draw(MyFrame2 frame)
- ※ リスト 8.27 を参考に書くこと
- 引数
- frame: MyFrame2 クラスのオブジェクト
- 動作
- なにもしない(動作は子クラスで定義)
- public void changeMove()
- ※ 乗り物が直線をまたいだ時に呼出されるメソッド
- 動作
- なにもしない(動作は子クラスで定義)
以下のように,中身のないメソッドを作ればよい
public void changeMove() { }
- なにもしない(動作は子クラスで定義)
R10_3 で作成する Car クラスの仕様
コンストラクタ
- R10_2 と同じ
メソッド
- public void draw(MyFrame2 frame)
- R10_2 と同じ
- public void changeMove()
- 動作
- 自動車の移動を停止する
以下のように,中心座標の変化量 vx および vy を 0 にすればよい
public void changeMove() { vx = 0; vy = 0; }
- 自動車の移動を停止する
- 動作
R10_3 で作成する Train クラスの仕様
コンストラクタ
- R10_2 と同じ
メソッド
- public void draw(MyFrame2 frame)
- R10_2 と同じ
- public void changeMove()
- 動作
- 電車の横の移動方向を逆にする
- 中心 \(x\) 座標の変化量 vx を -vx に変更する
- 電車の横の移動方向を逆にする
- 動作
R10_4
準備
- R10_3 で作成した以下をコピーする
- Car.java
- Train.java
- Vehicle.java
- DisplayCarTrain.java
課題
- 好きな乗り物をデザインして,R10_3 の Car クラス および Train クラスを参考にして,その乗り物を描画する MyVehicle クラスを追加せよ
- ただし,MyVehicle クラスは,R10_2 で作成した Vehicle クラスを継承すること
- また,changeMove メソッドで Car クラスや Train クラスとは異なる移動の変化を定義すること
- R10_3 で作成した DisplayCarTrain.java を修正し,時刻 i が 7 で割り切れる時に,以下の乗り物を 1 → 2 → 3 → 1 … の順番で生成するように変更せよ
- 1. 自動車(Car クラスのオブジェクト)
- 2. 電車(Train クラスのオブジェクト)
- 3. 好きな乗り物(MyVehicle クラスのオブジェクト)
- 他の条件は,R10_3 のもの と同じとする
提出物
- 使用した Car.java
- 使用した Train.java
- 使用した Vehicle.java
- 作成した MyVehicle.java
- 作成した DisplayCarTrain.java
R10_5 (オプション)
準備
課題
- R8_5 で作成した Triangle クラスと R8_6 で作成した Star.java の共通部分をとりだした親クラス(MyPolygon クラス)を作成せよ
- 作成した MyPolygon クラスを継承するように,Triangle クラスと Star クラスを修正せよ
- DisplayPolygonOject.java で,多角形(三角形 or 星を時間とともに生成し,図 6 のように流星群(?)のようなアニメーションを実行するように修正せよ
- 条件は,R8_5 で作成するプログラムの条件 で「三角形」を「多角形」に読み替えたものとする
- ※ 図 6 では時刻 t を描画しているが,提出するプログラムでは描画しなくてもよい
- また,軌跡は描画してもしなくてもよい
実行例
図6: R10_5 で作成するプログラムで表示されるアニメーション(ループ再生)の例 (学籍番号を 5 で割った余り n = 4 の場合)
提出物
- 作成した MyPolygon.java
- 修正した Triangle.java
- 修正した Star.java
- 作成した DisplayPolygonObject.java