裏返しアニメーションを付けてついに完成!前回はひとまずカスタムViewを使ってボードを描いて、画面をタッチした時に石を配置する所まで出来た。今回はゲームのロジックを実装して実際に遊べる所まで一通り作ってみた。必要な処理は次の4つになる。画面タッチ時に、押された場所が石を配置しても良い場所かどうか判断する。挟んだ相手の石を自分の石で置き換える。配置可能な場所が無い場合はスキップする。両者とも配置可能な場所が無い場合はゲーム終了とする。これに加えて、「次に配置可能な場所」を示してくれるヒント機能も付けて見た。小さな丸で表示されているのが「次に配置可能な場所」。濃い色にすると見辛くなるのでかなり薄くしてある。ゲーム終了時の結果表示。Toastでさらっと。メニューは「設定」、「カウント」、「最初から始める」、「閉じる」の4つ。設定でヒント表示のON/OFFを変更出来る。画面を縦表示に固定マーケットで配布されているオセロゲームをいくつか試した限りでは、全て縦表示で固定されていたので、同じように縦表示で固定する事にした。これはマニフェストファイルでの設定だけなので簡単だ。Activityタグの属性として、android:screenOrientation="portrait"を入れておけばOK。何もしないと、一旦他の画面に切り替わった後で再表示される場合に画面が初期状態に戻ってしまう。盤面の状態を保存しないと行けない。いうメソッドを作った。ここから各セルのステータスを1文字で表したものを連結した64文字からなる文字列を返す様にする。現在どちらの番なのかを表す文字を先頭に付加するので、実際には1+64=65文字になる。本当の所は、セルの状態は「黒/白/空白」の3つしか無いので情報としては2ビットあれば足りる。17という事で、17バイトのバイト配列に格納する事も出来る。ビット演算などが面倒なので今はこのまま65文字の文字列に格納する事にする。ViewのonSaveInstanceStateで状態を保存して、onRestoreInstanceStateで復元していた。これだとひとつ問題がある。端末の「戻る」ボタンで画面を閉じた時にはどちらのメソッドも呼ばれず、状態が失われてしまうのだ。これらのメソッドを使わずに代わりにActivityのonPauseとonResumeを使う様に変更した。この場合はデータの保存先はプログラムで適当な所を選ぶ必要がある。今回は保存したいデータが65文字の文字列なので、SharedPreferenceを使う事にした。これで「戻る」ボタンが押されてもちゃんと状態が保存される様になった。BoardクラスのchangeCellメソッドを呼んでいる。このメソッドはこの配置によって変更された全てのセルをArrayListに入れて返してくれる。View側ではこれを受け取って、順に変更されたセルの領域を指定しながらViewのinvalidateメソッドを呼んでいる。invalidateを引数なしで呼んだ場合はView全体が再描画されるが、引数rectに領域を指定して呼び出すと、その領域だけが再描画される。出来るだけ再描画する量を減らした方が処理が速くなる。drawRoundRectメソッドで四角の枠を表示した。それから、黒と白それぞれの現在の数をdrawTextメソッドで表示する様にした。これらの座標やフォントサイズの指定方法に少し悩んだ。Android側がDIPというデバイス非依存な単位として扱ってくれるらしい。画面の物理的な大きさや解像度が変わってもプログラム側は何もしなくてもいいはずだ。このページを読むと、なにやらXperiaでちょっとした問題があるとの事。格納した画像が使われるという問題があります。いう事なので、yanzmさんの真似をしてXMLファイルに座標関係の値を全て書き出す事にした。XMLファイルの書き方とプログラムでの使い方の説明はこちら。単位いちいちXMLを編集するのは最初はちょっと面倒だけれども、慣れてしまえば逆に微妙な調整などはこの方がやり易いかも知れない。デバイス間の解像度の違いについては、実機(800x480)とエミュレータ(480x320)で試して見たところ上手く表示されているので、多分大丈夫。ゲームロジックの実装Cellクラスで表されている各セルは「今このセルに石が配置されたらどのセルとどのセルが裏返されるか」という「裏返し対象セル」のリスト(mReversibleCells)を持っている。手番が変わるごとに毎回全てのセルについてこれを計算し直している。このリストのサイズが1以上ある場合は、そのセルは次に石を配置可能な場所であるという事になる。サイズが0なら、タッチされても何も起こらない。リストのサイズが1以上ある(配置可能な)セルがタッチされた場合は、この前もって計算された「裏返し対象リスト」に格納されているセルのステータスを順に現在の手番を表すステータス(黒または白)に置き換えて行く。配置可能なセルが一つも存在しない状態になった場合は、その手番はスキップ(パス)される。今回はここまでさて、これで一応ゲーム開始から終了まで動作する状態になった。ここまで来ると、もう少し完成度を上げて見たくなる。石はきれいな画像で表示したいし、裏返す時のアニメーション効果とコンピュータとの対戦機能ぐらいは欲しい。どこかにそこそこ強いオセロの思考ルーチンのコードが公開されていないものだろうか。(笑)ここまでのプロジェクト全体のダウンロードはこちらから。さんのコメント...Mikeさん。現在、Android作成について勉強中のタロイと申します。ゲームアプリを作成してみようと思い、こちらの処理を参考に現在作成しています。そこで、一つ問題がありこちらに書き込みをいたしました。問題というのは、ゲームを初めて黒と白の石を交互にひっくり返す処理で時折、石をひっくり返すと同時に画面かわ石が突如消えてしまう現象が起きることがあります。原因が判らず現在悩んでいます。処理はこちらで載せてあった処理で作成しています。言った現象等は起きたりしましたでしょうか?抽象的な質問ですみません。さんのコメント...タロイさん、はじめまして。きれいなソースコードではありませんが、参考にして頂いて嬉しいです。画面から石が突然消えるという現象が出た事があるかとの事ですが、私の方ではそういう現象はありませんでした。お役に立つかどうか分かりませんが、デバッグの方針としては、まず「時折」起きると書かれていますが、何か決まった条件(手順)があるのではないでしょうか。現象が発生する条件が分かれば、そこから原因を突き止める事が出来るのではないかと思います。さんのコメント...Mikeさん。