神経衰弱アプリを作ってみる
6.実はこれがカードをランダムに並べるメソッドだったのだ
さて前項に続いて、カードをランダムに並べる処理の内容を確認してみよう。
前項は、「setCards」というメソッドで「Card」クラスのオブジェクトを生成しているってところで話が終わったね。
では早速、その「setCards」というメソッドの中身を見てみよう。
定義は以下のとおりなので、まずはご覧あれ。
/**
* カードの配列にランダムに画像をセット
*/
private void setCards() {
//カードの表の画像(配列)・・・(A)
TypedArray images = getResources().obtainTypedArray(R.array.card_images);
//imageArrayを使って、すべての画像番号をシャッフルする・・・(B)
ArrayList<Integer> imageArray = new ArrayList<Integer>();
for ( int i = 0; i < images.length(); i++ ) {
imageArray.add(i);
}
Collections.shuffle(imageArray);
//cardArrayを使って、カードの数分の画像番号をペアで取り出しシャッフルする・・・(C)
ArrayList<Integer> cardArray = new ArrayList<Integer>();
for ( int i = 0; i < ROW*COL/2; i++ ) {
cardArray.add(imageArray.get(i));
cardArray.add(imageArray.get(i));
}
Collections.shuffle(cardArray);
//カードの配列に、シャッフルした画像番号と画像をセットする・・・(D)
for (int i=0; i < ROW*COL; i++) {
card[i] = new Card(
cardArray.get(i),
images.getDrawable(cardArray.get(i))
);
}
}
この中で「Card」クラスのオブジェクトを生成してるんだけれども、実のところこれはカードをランダムに並べる処理を担当しているメソッドなんだね。
つまり以下の4つの処理をそのままコーディングしたのが、まさにコレなわけ。
(1) 52枚のカードをシャッフルする。
(2) シャッフルしたカードの上から12枚を取り出し、それぞれ複製して24枚にする。
(3) さらに、24枚のカードをシャッフルする。
(4) シャッフルした24枚のカードを順に並べてセットする。
では、順を追って内容を見てみよう。
まず最初に(A)のところで、カード画像を配列のオブジェクトとして生成している。
TypedArray images = getResources().obtainTypedArray(R.array.card_images);
前項で「arrays.xml」というファイルを新規で作ったけれども、それがココに生きているわけだね。
つまりそのおかげで、「obtainTypedArray(R.array.card_images)」というメソッドを使って「images」という配列にイッキに画像データを取込むことができたってこと。
画像ファイルの実体の管理は「arrays.xml」のほうで分離してできるし、プログラムのほうは簡潔になるし、言うこと無しだ。
数十行に渡ってファイル名を記述してXMLファイルを作った苦労が報われたよ!やったよ、頑張ったよ!自分に乾杯。
というわけで画像ファイルをimages[0]~images[51]の配列で利用できるようにしたら、次の(B)の処理。
ここでは「カード番号」をシャッフルしている、「カード画像」じゃなくて「カード番号」と言ってるところに注意。
つまり「カード画像」の実体のimages[0]~images[51]を使わずに、その代理として配列の添字の0~51を「カード番号」としてシャッフルの対象に使うってこと。
そのためにまずは、次のように「imageArray」という名前の「ArrayListクラス」のオブジェクトを生成する。
ArrayList<Integer> imageArray = new ArrayList<Integer>();
ここで「ArrayListクラス」というのは、簡単に言えばサイズ(要素数)が可変の配列のようなものだ。
可変サイズなので、要素数を指定しなくてもオブジェクトの生成が可能なんだね。
次に「forループ」を使って、0~51の番号を「imageArray」にセットする。
「ArrayListクラス」に要素を追加するには、「add」というメソッドを使うだけ。
そしてこれをシャッフルしたいんだけれども、果たしてどうやるか?ここで「Collections.shuffle()」という便利なメソッドを見つけたんだよね。
Collections.shuffle(imageArray);
これは「Collections」クラスのメソッドで、引数で渡された「ArrayList」の順序を無作為に入れ替えるという働きをする便利なヤツ。
さて、ここまでの(A)(B)の部分で目的の
(1) 52枚のカードをシャッフルする。
という処理が実行されるわけだけれども、大体ご理解いただけたかな。
では続いて、(C)の処理。
ここでは「imageArray」のときと同様にして、「cardArray」という名前の「ArrayListクラス」のオブジェクトを生成する。
そしてこれに「imageArray」から、必要なカードの枚数分(=ROW*COL=24枚)の画像番号をペアで追加する。
「ペアで」っていうのを実現するために同じカード番号を2回追加しているところ、そしてforループを必要なカードの枚数の半分だけ回している点がここのポイントだ。
「ArrayListクラス」から要素を取り出すには、前述の「add」と同様に「get」というメソッドを使う。
「get(i)」っていうのは、「i」番目の要素を取り出してるんだね。
つまりここでは「imageArray」から「1~12番目」の要素を取り出(get)して、それを「cardArray」に「2回」追加(add)してるってことになる。
「imageArray」はシャッフルされてるから、もちろん「1~12番目」の要素はランダムになっているはずだ。
ここまでの処理で、
(2)シャッフルしたカードの上から12枚を取り出し、それぞれ複製して24枚にする。
という処理が実行されるわけだね。
引き続き、その下の
Collections.shuffle(cardArray);
によって、
(3)さらに、24枚のカードをシャッフルする。
という処理が実行されるというのは、もう言わずもがなだ。
さぁいよいよ手順の最後、クライマックスだよ。
(D)の部分だけれども、ここでついに待ちに待った「Cardクラス」の登場だ。
というところで、今回はここで終了。
クライマックスになったところで次回に引っ張るドラマみたいな流れも、焦らされる感じがたまらないでしょ。
次はようやく、「Cardクラス」のオブジェクトの生成についてだ。
Mな気分で、待たれよ次項!