Javaプログラミング基礎 演習問題

解答は

に提出しなさい。クラスファイル (〜.class) は提出しなくてよい。 提出には gFTP 等の ftp ソフトを用いること。

問題1 (Basic)

夏休みの課題でボールのアニメーションを行うプログラムを作成した。 今回はボールをクラスとして設計しなさい。

枠内を跳ね返りながら移動するボールのアニメーションの原理は次のようであった。

int x, y;          // ボールの位置 (x座標, y座標)
int vx, vy;        // ボールのx軸方向, y軸方向の速度
int width, height; // ボールの動く枠の幅と高さ

while(true) {

    // 移動を行った結果ボールが枠外に出そうなら進む方向を逆転
    if (x + vx > width || x + vx < 0)
        vx = -vx;

    // ボールの位置 (x座標) の計算
    x = x + vx;

    // 移動を行った結果ボールが枠外に出そうなら進む方向を逆転
    if (y + vy > height || y + vy < 0)
        vy = -vy;

    // ボールの位置 (y座標) の計算
    y = y + vy;


    // アニメーションの1コマの表示

    // 時間稼ぎ
}

このプログラムでボールをクラスにすることを考えると、 ボールの属性には、「ボールの位置情報」や、「ボールの速度情報」、 「ボールの動く枠の範囲」があることが考えられる。 また、「ボールを移動する」、「現在のボールの位置情報を取り出す」 というメソッドがあることが考えられる。

次のような枠組みのプログラムを作成し、 ボール (Ball) クラスを用いた、ボールの移動を行うプログラムを作成しなさい。 ファイル名は BallSimulation.java とする。

class BallSimulation {
    public static void main(String[] args) {
        Ball ball = new Ball();

        ballの位置情報を設定 (x座標, y座標を0, 0に設定) ;
        ballの速度情報を設定 (x方向, y方向を1, 1に設定) ;
        ballの動く枠の幅と高さを設定 (幅, 高さを46, 20に設定) ;

        // アニメーションの開始
        while (true) {
            ballの位置を1コマぶん進める;

            ballの位置情報を取りだし、表示;
        }
    }
}

class Ball {

    属性
        ボールの位置情報
        ボールの速度情報
        ボールの動く枠の幅と高さ

    メソッド
        ボールの位置情報を設定する ( ..... )  {
        }

        ボールの速度情報を設定する ( ..... )  {
        }

        ボールの動く枠の幅と高さを設定する ( ..... )  {
        }

        ボールの位置を1コマぶん進める ( ..... ) {
        }

        ボールの現在のx座標を取り出す ( ..... ) {
        }

        ボールの現在のy座標を取り出す ( ..... ) {
        }
}

なお、このプログラムでは、 1コマごとのボールの位置 (x座標とy座標) が表示されれば良い。 画面の書き換えを伴うアニメーション表示までは必要ない。

このプログラムは無限に繰り返しを行う。終了させるには Ctrl-C を押すこと。

問題2 (Basic)

「人間」をあらわすクラスを考える。 人間といっても様々な人がいる、ということで次のような人間を考えてみよう。

年齢を問いかけたときの答えとして

という、さばを読んだ年齢を答える人をクラスとして作成することを考える。

このような人間をクラス CheatingPerson として定義し、 自己紹介をさせるようなプログラムを作成しなさい。 このプログラムの実行結果は、 例えば実年齢 35 歳の Maurice White という人物について

Hello, my name is Maurice White. I am 33 years old.

のように、さばを読んだ年齢を含んだ自己紹介を行うようにする。

さばを読む人のクラス CheatingPerson の定義は次のようになる。

class CheatingPerson {
    属性
        名前
        実年齢

    メソッド
        名前と実年齢を受け取り初期化するメソッド ( .... ) {
            ....
        }

        自分の名前を返すメソッド ( .... ) {
            ....
        }

        さばを読んだ年齢を返すメソッド ( .... ) {
            ....
        }
}

また、このクラス CheatingPerson を用いて 自己紹介をさせるメソッド main は次のようになる。

class IntroduceCheatingPerson {
    public static void main(String[] args) {
        CheatingPerson maurice = new CheatingPerson();

        maurice に対して名前と実年齢を登録 ;

        // maurice の自己紹介を行う
        System.out.println("Hello, my name is " + ............... );
    }
}

このプログラムを完成させなさい。 メソッド main のあるクラスは IntroduceCheatingPerson とする。 (ファイル名は IntroduceCheatingPerson.java)

問題3 (Standard)

簡単な自動販売機の動きを真似るプログラムを作成する。

問題3-1

「自動販売機」のクラスを設計する。

ここでは単純に、 お金を入れ「購入ボタン」を押すと物が出てくるような機能簡略版を想定する。 通常のジュースや切符の自動販売機に近い動きをするが、 ジュースの種類の選択や在庫の管理の機能は無いものとする。

まず、自動販売機の利用者が、 どうやって自動販売機を利用するかという「シナリオ」から、 自動販売機にどのようなメソッドがあり、 どのような属性 (変数) があるかを考える必要がある。 では、次のシナリオから、自動販売機のクラスを設計することを考えてみよう。

「利用者は 120 円のジュースを売っている自動販売機に100円を入れた。
購入ボタンを押すと、 20 円不足であると表示された。
次に 50 円を入れた。購入ボタンを押すと、 ジュースとおつり 30 円が出た。」

このシナリオから導き出される自動販売機の仕様は次のようになる。

「自動販売機は利用者からお金を複数回に分けて受け取ることができる。
購入ボタンを押すと、入れたお金が120円以上の場合はジュースとおつりが出る。
入れたお金が120円未満の場合は不足金額が表示される。」

ファイル VendingMachine.txt に自動販売機クラスの設計内容を書きなさい。 ここでは、実際のプログラムを書く必要はなく、 それぞれの属性、メソッドの役割や動作が言葉で説明できていれば良い。

設計内容は次のような形式とする。 それぞれの属性、メソッドごとに1,2行の説明を書くこと。

問題3-2

前の問題の設計に基づき、自動販売機クラスを作成しなさい。 自動販売機クラスを利用して、ジュース買う動作を行うプログラムも作成し、 自動販売機が動いている様子を表示するようにしなさい。

このプログラムの実行の様子は、各自の分析結果によって異なるが、 例えば次のような結果が考えられる。 メソッドmainのあるクラス名は VendingMachineUser とし、 自動販売機のクラス名は VendingMachine とする。 (ファイル名: VendingMachineUser.java)

$ java VendingMachineUser
100 円を入れます。
-----> 投入合計金額は 100 円です。

購入ボタンを押します。
-----> 20 円不足しています。

50 円を入れます。
-----> 投入合計金額は 150 円です。

購入ボタンを押します。
-----> ジュースを出します。
-----> 30 円のおつりを出します。

なお、ジュースやおつりが出てくる場合、 プログラムから本物を出すことはできないので、 「◯◯を出します。」とメッセージを出せば良いものとする。

問題4 (Standard)

電源を入れてキー入力ができるパソコン (のようなもの) をプログラムの中で表してみよう。 パソコンを表すクラス PC を定義しなさい。 このパソコンには電源スイッチとキーボードがあり、 押したキーに従ってその文字が画面に出力されるものとする。

問題 4-1

メソッド type(入力文字) により、引数で指定した文字が画面に表示されるようにしなさい。 また、メソッド enter() により改行されるようにしなさい。

以下のようにメソッド main のあるクラス名は PCUser1 とし、 ファイル名は PCUser1.java とする。

class PCUser1 {
    public static void main(String[] args) {
	PC myPC = new PC();
	myPC.type('t');    // キー「t」を押す
	myPC.type('d');    // キー「d」を押す
	myPC.type('u');    // キー「u」を押す
	myPC.enter();      // キー「Enter」を押す
    }
}

class PC {
    .....
}

上記のプログラムを実行すると、画面にtduという文字が表示され、改行されて終了する。

$ java PCUser1
tdu
$

問題 4-2

上のクラス PC を機能拡張し、 電源をon/offするメソッド power を作成し、 電源が入っていないときにはキーを押しても反応しないようにしなさい。

以下のようにメソッド main のあるクラス名は PCUser2 とし、 ファイル名は PCUser2.java とする。

class PCUser2 {
    public static void main(String[] args) {
	PC myPC = new PC();
	myPC.power();      // 電源スイッチを押す(電源が入る)
	myPC.type('t');    // キー「t」を押す
	myPC.type('d');    // キー「d」を押す
	myPC.type('u');    // キー「u」を押す
	myPC.enter();      // キー「Enter」を押す
	myPC.power();      // 電源スイッチを押す(電源が切れる)

	myPC.type('t');    // 電源が入っていない状態でキーを押すとエラーが表示される
	myPC.enter();      // 同様
    }
}

class PC {
    .....
}

ヒント: クラス PC に、電源がonかoffかの状態を保持する属性を用意する必要がある。

問題5 (Advanced)

前回のペットボトルの問題では、 ジュースを飲むとペットボトルの残量が変化する様子を プログラムとして表わした。 このように、 現実世界の現象をプログラムとして再現しコンピュータの中で真似をすることを シミュレーション (simulation) と呼ぶ。 各自で時間とともに変化する現象を一つ選び、 簡単なシミュレーションを行うプログラムを作りなさい。 メソッド main のあるクラス名は MySimulation とし、 ファイル名は MySimulation.java とする。 シミュレーションの対象となるものをクラスとして定義すること。

ソースファイルの先頭に、 そのシミュレーションのタイトルと、 どのような内容かを説明する文章をコメントの形式で書いておくこと。

例えば、次のようなシミュレーションが考えられる。

問題6 (Advanced)

以前の演習問題 で可変個数の配列(のようなもの)を扱うプログラムを作成した。 このプログラムの解答例を以下に示す。

class CollectionByArray {
    public static void main(String[] args) {
	int[] content = new int[100];

	// 配列要素全体を -1 (未使用) で初期化
	init(content, -1);

	// 1,9,6 の追加
	add(content, 1);
	add(content, 9);
	add(content, 6);
	print(content);

	// 10 の追加
	add(content, 10);
	print(content);

	printIndexOf(content, 6);
	
	// 6 の削除
	remove(content, 6);
	print(content);

    }

    static void init(int[] content, int a) {
	for(int i = 0; i < content.length; i++)
	    content[i] = a;
    }

    static void add(int[] content, int a) {
	// 配列の要素中から -1 (未使用) を探し、最初に -1 が現れた場所、
        // すなわち意味のある値のある要素の末尾に値を追加
	for(int i = 0; i < content.length; i++) {
	    if(content[i] == -1) {
		content[i] = a;
		return;
	    }
	}

	// 配列要素の最後まで -1 (未使用) が見つからない場合はエラー
	System.out.println("配列に空きがありません。");
    }

    static void remove(int[] content, int a) {
	// 配列の要素中から削除したい値を探し -2 (削除済み) にマーク
	for(int i = 0; i < content.length; i++) {
	    if (content[i] == a) {
		content[i] = -2;
		return;
	    }
	}

	// 配列要素の最後まで削除したい値が見つからない場合はエラー
	System.out.println("削除したい値が見つかりません。");
    }

    static void printIndexOf(int[] content, int a) {
	// 配列の要素中から値を探して表示
	for(int i = 0; i < content.length; i++) {
	    if (content[i] == a) {
		System.out.println(a + " は " + i + " 番目に見つかりました");
		return;
	    }
	}

	// 配列要素の最後まで値が見つからない場合はエラー
	System.out.println("値が見つかりません。");
    }

    static void print(int[] content) {
	// 配列要素を最初から最後まで繰り返す
	for(int i = 0; i < content.length; i++) {
	    // 繰り返しの途中で -1 (未使用) があったら繰り返しを終了
	    if (content[i] == -1)
		break;

	    // -2 (削除済み) 以外の値を表示
	    if (content[i] != -2) 
		System.out.print(content[i] + " ");
	}
	System.out.println();
    }
}

問題6-1

このような可変個数のデータの並びのことを「リスト」(list)という。 このプログラムを改造し、 「リスト」を実現する機能をクラスとして書きなさい。 クラス名は PrimitiveArrayList とする。 このクラスの内容は以下のようになる。

この設計にもとづき、クラス PrimitiveArrayList を作成しなさい。 なお、(※1)の配列の宣言の部分は次のように変数の宣言のみを行う。

int[] content;

そして、(※2)のメソッド initialize の部分で、 new 演算子を用い実際に配列の中身を生成した後、 中身の値を初期化するようにする。

void initilize() {
    content = new int[100];
    for(int i = 0; i < content.length; i++)
        content[i] = -1;
}

クラス PrimitiveArrayListUser に、メソッド main を作成し、 リストに対して値の出し入れや検索を行いなさい。 プログラム全体のファイル名は PrimitiveArrayListUser.java とする。

プログラム全体の枠組みは次のとおり。

class PrimitiveArrayListUser {
    public static void main(String[] args) {
	PrimitiveArrayList list = new PrimitiveArrayList();
	list.initialize();


        list に対して様々な操作を行う。


    }
}

class PrimitiveArrayList {

    // リストの各要素を格納する属性 content の宣言


    メソッド initilize の宣言 () {
        content の配列を生成し、中身を -1 で初期化する。
    }

    メソッド add の宣言 ( .... ) {
        content に引数で指定された値を追加する。
    }

    メソッド remove の宣言 ( .... ) {
        content から引数で指定された値を削除する。
    }

    メソッド printIndexOf の宣言 ( .... ) {
        content 内から引数で指定された要素を探し、何番目に見つかったか表示する。
    }

    メソッド print の宣言 () {
        リスト全体の内容を表示する。
    }
}

問題6-2

クラス PrimitiveArrayList の機能を拡張し、 リストの内容を小さい順に並び替える機能を追加しよう。 クラス PrimitiveArrayList に、 小さい順に並び替えた結果を表示するメソッド printAscendingOrder を追加しなさい。 クラス PrimitiveArrayList をベースに機能拡張したクラスの名前は、 新たに SortablePrimitiveArrayList とする。 小さい順の並び替えの考え方は 以前の演習問題 と同様である。

また、クラス SortableArrayListUser に、メソッド main を作成し、 リストに対して値の出し入れや並び替えを行いなさい。 プログラム全体のファイル名は SortableArrayListUser.java とする。

問題6-3

クラス PrimitiveArrayList に独自の機能を追加しよう。 クラス PrimitiveArrayList をベースに機能拡張したクラスの名前は、 新たに PrimitiveArrayListPlus とする。

独自の機能とは、例えば次のようなものである。

クラス PrimitiveArrayListPlusUser に、メソッド main を作成し、 追加機能の動作を示すようにメソッドを実行しなさい。 プログラム全体のファイル名は PrimitiveArrayListPlusUser.java とする。