moveRing() --その2--さて、お膳立ても整ったところでメソッドmoveRing()を作りましょう。
メソッドmoveRing()では
場合は前項で作成したIllegalMovementExceptionを投げ、それ以外の場合はリングを移動します。
まず宣言部分ですが
public void moveRing(int from, int to) throws IllegalMovementException
と例外IllegalMovementExceptionを投げるメソッドであることを示すために、throws IllegalMovementExceptionを書きます。
メソッド本体を見ていくと、まず
if (from == to)
で「同じ塔にリングを移そうとした」かどうか調べ、そうだった場合は
throw new IllegalMovementException("Move ring to another tower!", "違う塔にリングを移しましょうよ。");
と「違う塔にリングを移しましょうよ。」というlocalized detail messageを持つIllegalMovementExceptionのインスタンスを投げます。
次に
if ((!tower[to].empty() &&
(((Integer)tower[from].peek()).intValue() > ((Integer)tower[to].peek()).intValue())))
で「小さいリングの上に大きいリングを移そうとした」かどうか調べ、そうだった場合は
throw new IllegalMovementException("Can't move bigger ring upto smaller ring!", "小さなりリングの上に大きなリングを動かすことはできません。");
と「小さなりリングの上に大きなリングを動かすことはできません。」というlocalized detail messageを持つIllegalMovementExceptionのインスタンスを投げます。
(Integer)tower[from].peek()).intValue()
では何をしているかというと、まずtower[from].peek()でスタックの一番上のオブジェクトを調べます。tower[from].peek()の返り値はObject型なので、これを(Integer)でInteger型にキャストします。最後にInteger型で使えるメソッドintValue()で値をint型に変換し、大小を比較できるようにしています。
!tower[to].empty()
を調べているのはtower[to]にリングがなければ無条件で移して良いからです。この条件を調べる順番も大切で、逆だと&&以下にあるtower[to].peek()で例外EmptyStackExceptionが生じてしまいます。この順番ならば!tower[to].empty()が真のときは&&以下を実行しません。
上記二つのチェックをくぐり抜けたら
tower[to].push(tower[from].pop());
でリングを移動します。この文は
Object ring = tower[from].pop(); tower[to].push(ring);
を一文にまとめたものです。
「リングがつまれていない塔からリングを取りだそうとした」場合を調べていませんが大丈夫です。この場合は上述のtower[from].pop()からEmptyStackExceptionが発生するので、これを処理する部分で面倒みます。
try {
...
tower[to].push(tower[from].pop());
...
} catch (java.util.EmptyStackException e) {
throw new IllegalMovementException("There is no ring in tower " + from + " !", "その塔にリングはありません。");
}
として、例外EmptyStackExceptionが発生した場合は「その塔にリングはありません。」というlocalized detail messageを持つIllegalMovementExceptionのインスタンスを投げます。