Javaプログラミング基礎

演習問題 (中級〜上級)

解答は

に提出しなさい。ソースファイル (〜.java) のみを提出。 提出は gFTP 等の ftp ソフトを用いて行う。

問題1

月曜日に示した例題のメソッド repeatCharacters を用い、 次のような三角形を書くプログラムを作成しなさい。 プログラム名は FlippedTriangle2 とする。

....*
...**
..***
.****
*****

問題2

次のような円を表示するプログラムを作成しなさい。 プログラム名は PaintedCircle とする。

          *
      *********
    *************
   ***************
  *****************
  *****************
 *******************
 *******************
 *******************
 *******************
*********************
 *******************
 *******************
 *******************
 *******************
  *****************
  *****************
   ***************
    *************
      *********
          *

このプログラムは次の方針で作成すること。

メソッド main で、 y 座標の値を -10 から 10 まで変化させる繰り返しを行う。 そしてこの繰り返しの内側で、x座標の値を -10 から 10 まで変化させる繰り返しを行う。

メソッド printAsteriskInCircle を定義する。 このメソッドは、 x 座標と y 座標の 2 つの int 型の値を受け取り、 その座標が円の内側か外側かを判定し、 内側であれば「*」を表示し、外側であれば空白を表示するように作る。

メソッド main では、 二重の繰り返しの内側で x 座標と y 座標を引数に与え、 メソッド printAsteriskInCircle を実行すれば、 円を表示することができる。

以下に、メソッド printAsteriskInCircle において、 その座標が円内にあるか外にあるか判定する方法を示す。

点 (x, y) が、原点中心で半径 r の円に含まれているかどうかは、 原点からの距離を比較すればよい。 原点からの距離が r 以下であれば、点は円内にある。

両辺を2乗しても成り立つので

点(x,y)が上記の条件を満たすか調べ、 満たしていれば '*' を表示し、満たしていなければ空白を表示すればよい。

問題3

いつもの塗り潰された三角形を、漸化式の考え方で描くことを考えてみよう。 底辺の長さ n の三角形は、底辺の長さ n-1 の三角形に、長さ n の線を足すことにより得られる。

(底辺の長さ n の三角形) = (底辺の長さ n-1 の三角形) + (長さ n の線)

*
**
***
****   <- ここまでが底辺の長さ 4 の三角形
*****  <- 長さ 5 の線(底辺)

いま、底辺の長さ n の三角形を描くメソッド printTriangle を考える。 上記の漸化式を素直にプログラムにしてみよう。

なお、底辺の長さ 1 の三角形は "*" になるので、 この場合には漸化式を使わずに "*" を表示するだけでよい。

プログラム名を RecursiveTriangle1 とすると、その大枠は以下のようになる。

class RecursiveTriangle1 {
    public static void main(String[] args) {
        // 引数で底辺の長さを与える
        printTriangle(Integer.parseInt(args[0]));
    }
    /** 底辺の長さ n 、高さ n の二等辺三角形を表示する */
    static void printTriangle(int n) {
        if(n == 1) {
            // 底辺 1 の三角形として "*" を表示
        }
        else {
            // 底辺 n - 1 の三角形を表示
            //
            // 長さ n の線(底辺)を表示
        }
    }
    static void repeatCharacters(int num, String character) {
        for(int i = 0; i < num; i++)
            System.out.print(character);
    }
}

なお、繰り返しを行う文 (for, while 等) を使う必要はないので、使わないこと。

問題4

メソッドに関する理解を深めるために、再度、 メソッドの中身からメソッド自分自身を実行するようなプログラムを考えてみよう。

次のプログラムは、5 から順に 0 までカウントダウンを行うプログラムである。

class CountDown {
    public static void main(String[] args) {
	countDown(5);
    }

    static void countDown(int number) {
	System.out.println(number);
	if (number > 0)
	    countDown(number - 1);
    }
}

このプログラムの注目すべき点は、 メソッド countDown のなかで、 さらに自分自身を呼び出していることである。 プログラムの実行時には次のようなメソッドの実行が行われる。

countDown(5) の実行: 「5」を表示し CountDown(5-1) を実行
  countDown(4) の実行: 「4」を表示し CountDown(4-1) を実行
    countDown(3) の実行: 「3」を表示し CountDown(3-1) を実行
      countDown(2) の実行: 「2」を表示し CountDown(2-1) を実行
        countDown(1) の実行: 「1」を表示し CountDown(1-1) を実行
          countDown(0) の実行: 「0」を表示する
          coundDown(0) の実行は終了
        coundDown(1) の実行は終了
      coundDown(2) の実行は終了
    coundDown(3) の実行は終了
  coundDown(4) の実行は終了
coundDown(5) の実行は終了
「5 4 3 2 1 0」が表示できた めでたし

このようなプログラムは一見奇妙だと思うかも知れないが、 メソッドの「再帰呼び出し (recursive call) 」と呼ばれる一般的なプログラミング手法である。

再帰呼び出しの考え方を用いて、 次のような図形を表示するプログラムを作成しなさい。 プログラム名は RecursiveTriangle2 とする。

*
**
***
****
*****
******
*******
********
*********
**********
*********
********
*******
******
*****
****
***
**
*

この問題では、繰り返しを行う文 (for, while 等) は使わないこと。

例題で示したメソッド repeatCharacters を用いると良い。

問題5

上級者向け。

配列を用い、可変個数の集合を扱えるような機能を実現しなさい。 具体的には、配列に対して値の追加、削除、検索、要素の表示など さまざまな操作を行うメソッド群を作成しなさい。 具体的には次のとおり。

さらに、メソッド main に、 これらのメソッドを使い集合にいろいろな操作を行うプログラムを書きなさい。

例えば、新たな集合を作り、1, 9, 6 を追加すると、 集合の内容は次のようになる。

1 9 6

次に 10 を追加すると、集合の内容は次のようになる。

1 9 6 10

また、6 を検索すると 2 番目 (配列は 0 から始まるので) であることがわかるようにする。

そして、集合から 6 を削除すると次のようになる。

1 9 10

このプログラムでは、可変個のデータを扱うことから、 配列の何番目まで意味のあるデータが入っているかを管理する必要がある。 それを行う一つの方法は、 最初に配列全体を「空」を表わす特別な値 (たとえば -1) を決めて初期化し、 先頭から順番に値を入れていくことが考えられる。値を順に取り出すときには -1 が見つかったら、 取り出しを終了すれば良い。

次に、値が削除されたとき、削除済のデータを配列内で管理する必要がある。 一つの方法として次のような処理が考えられる。 削除済みを示す特別な値 (たとえば -2) を決めて、 値が削除されたときに配列要素にその値を書き込むようにする。 データを取り出すときは -2 があったらその要素を読み飛ばすようにする。

プログラム名は CollectionByArray とする。