2011年8月16日

Androidでオセロゲームを作ってみる (4) 文字列をぐるぐる回す方法

Androidでオセロゲームを作ってみる (1)
Androidでオセロゲームを作ってみる (2) ゲームロジックの実装
Androidでオセロゲームを作ってみる (3) 思考ルーチンの実装
Androidでオセロゲームを作ってみる (4) 文字列をぐるぐる回す方法
Androidでオセロゲームを作ってみる (5) 裏返しアニメーションを付けてついに完成!


前回までで思考ルーチンがそこそこ動く様になってゲームとしては結構遊べる状態になったので、今回からは少しずつグラフィックを改善して行きたい。

ひとまずこんな感じで、ゲーム終了時の結果表示の文字列をぐるぐる回してみた。
http://www.youtube.com/watch?v=AYld0bnjxeI

FrameLayoutを使ってオーバーレイ表示


前回まではカスタムのReversiViewの中でdrawTextを使って勝ち負けを表示していた。今回はその代わりにAndroid標準のアニメーション機能を使いたいので、ReversiViewの中心に重なる様にTextViewを配置して、そこに文字列を表示した。

複数のViewを重なる様に配置するには、FrameLayoutを使うと良いらしい。

TextViewには標準でドロップシャドウの機能が付いているのでこれも利用した。


文字列を画面の中心に配置するのは、

 android:layout_gravity="center"

とするだけで出来た。素晴らしい。^^

ちなみにTextViewの上のViewは、ゲーム終了時に画面の背景を暗くするアニメーションを入れる為に使っている。




AnimationをXMLファイルで定義


AnimationをXMLファイルで定義するには、res/の下にanimフォルダを作ってそこに適当な名前でXMLファイルを作成する。

色々試行錯誤して見た結果、こんな形になった。
回転しながらズームイン&フェードインして、一瞬止まった後でスーっと上に動く感じ、が作りたかったので。

また文字列を回すのと同時に、背景を少しずつ暗くするのもalphaアニメーションを使って行なっている。

あと、ちょっとハマったのは、setタグの属性として「xmlns:android=...」を付けないと set全体にfillEnabledとfillAfterの属性を付けられなかった点だった。




AnimationをTextViewに適用


ActivityのonCreateでAnimationUtils.loadAnimation()を呼んで上で定義したアニメーションを準備しておく。

実際にアニメーションを開始するには、TextViewのstartAnimation()を呼ぶだけだ。





ソースコードと次回の予定


現時点のプロジェクト全体のソースコードはこちら。
mikehibm/MiReversi at ver4 - GitHub

次回はいよいよコマをひっくり返す時のアニメーションを作りたい。それが出来たら一応完成かな?


Androidでオセロゲームを作ってみる (1)
Androidでオセロゲームを作ってみる (2) ゲームロジックの実装
Androidでオセロゲームを作ってみる (3) 思考ルーチンの実装
Androidでオセロゲームを作ってみる (4) 文字列をぐるぐる回す方法
Androidでオセロゲームを作ってみる (5) 裏返しアニメーションを付けてついに完成!








 .

2011年8月3日

Androidでオセロゲームを作ってみる (3) 思考ルーチンの実装

Androidでオセロゲームを作ってみる (1)
Androidでオセロゲームを作ってみる (2) ゲームロジックの実装
Androidでオセロゲームを作ってみる (3) 思考ルーチンの実装
Androidでオセロゲームを作ってみる (4) 文字列をぐるぐる回す方法
Androidでオセロゲームを作ってみる (5) 裏返しアニメーションを付けてついに完成!


前回の記事からあっと言う間に半月以上も経ってしまった。

その間、会社のXenServerがトラブったり、オフィスの引越し準備と大きなプロジェクトのカットオーバーが重なったりで、7月はなかなか大変な月だった。

そんな中で実はオセロの思考ルーチンを少しずつ実装したりもしていた。結局、仕事と子育てで一杯一杯なのはいつもの事なので、早朝5時起きしてでもなんとか自分の時間を作ってやって行くしかないかなあと思う。



思考ルーチンの実装


オセロの思考ルーチンを作り込む事は、このアプリを作り始めた時の「Androidでの2Dグラフィックス処理の習得」という目標からは完全に脱線している。でもどうしても誘惑に負けて、作り込まずにはいられなかった。(笑) 面白いのだから仕方がない。

下の2つのリンク先にはとてもとてもお世話になった。
-鶯教-コンピュータ・リバーシ講座

リバーシ(オセロ)プログラム (2018年現在リンク切れ)

今のところ、作成した思考ルーチン(?)は下の4種類。それぞれが ComputerPlayer クラスのサブクラスになっている。

(クラス名クリックでソースコードを表示します)
ComputerPlayer0 何も考えずに打てる場所の中からランダムに選んで打つ。
ComputerPlayer1 次に打つ場所の候補のリストを、事前に定義された評価テーブルにしたがってソートした上で、評価の最も高い場所に打つ。打った結果についての先読みはしない。
ComputerPlayer2 1手先までの局面の評価値を計算し、最も評価の高い手を選ぶ。
ComputerPlayer3 「ネガマックス法」にしたがって最大4手先までの局面の評価値を計算し、最も評価の高い手を選ぶ。


クラスの継承関係はこんな感じになっている。
  Player (人間とコンピュータの両方に共通のコードを記述)
     HumanPlayer   
     ComputerPlayer (スレッドの起動・停止など全ての思考ルーチンに共通する処理を記述)
       ComputerPlayer0 (各思考ルーチンの実装はこのレベルのクラスに記述)
       ComputerPlayer1
       ComputerPlayer2
       ComputerPlayer3

ゲーム実行時の基本的な流れとしては、HumanPlayerの番になるとボード上の有効な場所がタッチされるまで待ち、ComputerPlayerの番になると別スレッドを起動して思考ルーチンを走らせる様になっている。

思考ルーチンは戻り値としてPointを返すので、あとは人間がその座標をタッチした場合と同様の処理を行えばよい。

ただ、思考ルーチンが走っている間に電話がかかって来たり別のアプリが前面に呼び出されたりするとActivityが終了してしまう可能性がある。その場合は思考ルーチンのスレッドもきちんと終了させる必要があるので、その辺りにはちょっと気を使わないと行けない。



気になる強さは?


ComputerPlayer1と2はそれなりに遊べるとは思うけど、かなり弱い。

ComputerPlayer3は、個人的にはそこそこ強いのではないかと思う。ただめちゃくちゃ強いというほどでもない。自分で対戦して見た限りだと、5回やると4回は自分が負ける。1回ぐらいはぎりぎり勝てるという感じだ。

不思議な事に、こいつに自分が負けるとなぜか嬉しい。早起きして眠い目をこすりながらデバッグした甲斐があったというものだ。(笑)



ソースコードと次回の予定


現時点のプロジェクト全体のソースコードはこちら。
mikehibm/MiReversi at ver3 - GitHub

次回はいよいよ石を裏返す時のアニメーションとか、ゲーム終了時の結果表示画面などをグラフィック機能を駆使して作り込んでみたい。早寝早起きして頑張ろう。^^


Androidでオセロゲームを作ってみる (1)
Androidでオセロゲームを作ってみる (2) ゲームロジックの実装
Androidでオセロゲームを作ってみる (3) 思考ルーチンの実装
Androidでオセロゲームを作ってみる (4) 文字列をぐるぐる回す方法
Androidでオセロゲームを作ってみる (5) 裏返しアニメーションを付けてついに完成!





2012/1/12 追記:
ここにある思考ルーチンは最強かも!
Booby Reversi Download Page

強いオセロプログラムについて







2011年7月16日

XenServerのiSCSI共有ストレージが壊れた時の復旧方法メモ

トラブルの概要


先日、社内で使っているXenServerの共有ストレージにアクセス出来なくなると言うトラブルが起こった。

使っていた共有ストレージは、Buffalo TeraStation ProのiSCSIモデル。セットアップしてから約1年半、全く何のトラブルも無く動いていた機器だったので、油断していた。

ビルディングのメンテナンスで長時間の停電があって、その停電からの復帰後に起動したら「iSCSIの論理ボリュームを作成出来ない」という旨のエラーがストレージ側のログに出て、XenServerからの接続が一切出来なくなってしまった。

TeraStationの管理画面を開いて色々やって見たけれどもどうもらちが開かないので、TeraStationからHDDを取り出してPC(サーバー)に直接接続してみた。Raid1で4本のHDDを2本ずつ別々にミラーリングしているだけだったので、1本だけ取り出してもそのまま読めるだろうと思ったのだ。

まずはPC上でDVDからUbuntuを起動する。でもそのままではHDDはマウント出来なかった。かなり焦りながら調べた所、どうやら mdadm コマンドでSoftware Raidとして認識させる必要があるらしいという事が分かった。
ソフトウェアRAIDのデグレード(縮退)モードからの復旧 - RX-7乗りの適当な日々

mdadmを使ったRAIDの再構成 - 日々雑文



mdadmでミラーリングを認識


まずは、
sudo apt-get install mdadm
でmdadmをインストール。
mdadm --examine --scan
cat /proc/mdstat
これでRaidの認識は出来た。次に、
mdadm --run /dev/md0
mdadm --run /dev/md1
mdadm --run /dev/md2
とやると、ミラーリングされたデバイスに片肺状態でアクセス可能になる。
cat /proc/mdstat
でACTIVEと表示されるのが確認出来る。



lvm2で論理ボリュームを認識


ここまで来たら、lvm2で論理ボリュームを確認する所までは一気に行ける。
sudo apt-get install lvm2
pvscan
vgscan
lvscan

これで論理ボリュームの情報が表示されればOK。保存されていた仮想マシンのディスクイメージの分だけ論理ボリュームが存在している。

この論理ボリュームを何とかUbuntuでマウント出来れば、データが取り出せるはずだ。よし、復旧までもう少し。。。

と思ったが、ここからがまた結構長かった。データがそこにあるのが分かっているのに取り出せない、という辛い状態で数時間を費やす事になってしまった。

しょんぼり技術メモ

LVMの論理ボリュームをddでコピー - litediary




ddで吸いだす


とりあえずlvmの論理ボリュームのままでは扱いにくいので、 dd コマンドでボリュームを丸ごと別のディスクにファイルとしてコピーしておく。実はddコマンドなんて普段使う事がほとんど無いので、勉強になった。(笑)
dd if=/dev/VS_XenStorage..(論理ボリュームの名前) of=/media/EXTERNAL/data.vhd bs=4M
これで論理ボリュームからdata.vhdというファイルにコピー出来た。

さて、XenServerの仮想マシンのイメージはVHD形式で保存されているらしいという事は分かったのだが、それがどうやってもマウント出来ない。

最初は losetup と kpartx と言うコマンドでループバックデバイスを構成してから mountコマンドでマウントという方法を試した。下の例の様に、その方法で解決出来たという情報がいくつか見つかったからだ。
Citrix Forums : Unable to mount a VHD in Dom0 ...

CTX117791 - How To Mount a Linux LVM Partition in a XenServer Host - Citrix Knowledge Center

CTX116183 - How To Mount a XenVM Filesystem on XenServer Host - Citrix Knowledge Center

Xenのイメージファイルをマウントする « そこはかと

lvmのディスクイメージをmount - 間違いだらけの備忘録

LVMで使っていたドライブからデータを救出する - kinneko@転職先募集中の日記

上の方法ではどうしても上手く行かなかったので、さらに検索。。。

次に、vdfuse というコマンドでVHDがマウント出来るらしいという事でやって見たが、これもなぜか上手く行かなかった。
Mounting a VHD in Linux




VirtualBoxでVHDをアタッチ


一晩空けて、ふと思い付いた。VirtualBoxの仮想マシンにVHDファイルをアタッチして見たらどうだろうか。。。結果、これが見事に成功だった。VirtualBox上のUbuntu仮想マシンで、アタッチされたディスクをマウントして無事データを復旧する事が出来た。

ただこの方法では、VirtualBoxでアタッチする時にエラーになって出来なかったケースもあった。確か「Parent file with UUID XXXX-XXX-XXXX-....XXX cannot be found...」みたいなエラーメーッセージだった。

これは、どうもXenServerでスナップショット機能を使っていた場合に起こる様だ。スナップショットによって複数の論理ボリュームにディスクイメージのデータが分散してしまっている場合は、VirtualBoxでは上手くアタッチ出来ないのかも知れない。

あと、qemu-img のコンバート機能を使ってもVHDからRAWフォーマットに変換出来るそうだ。RAWフォーマットに変換出来れば、あとは上記のlosetup と kpartxを使う方法でマウント可能になる。
qemu-img convert -f vpc -O raw data.vhd data.raw



XenConvertで仮想マシンを復旧


データをVHDのイメージから取り出す事は上の方法で出来たが、仮想マシン自体をもう一度XenServerで起動するにはどうしたら良いだろうか。データだけ取り出すよりも、元の仮想マシンがそのまま動かせればそれに越した事はない。

まず考えたのは、上でコピーしたdata.vhdファイルの中味を、ddコマンドでXenServerのローカルストレージに作った領域に書き戻してやるという方法だった。理論的にはこれでバッチリ復旧だと思った。でも実際にローカルストレージに元のイメージと同じサイズの仮想ディスクを作成して、そこに dd コマンドで仮想マシンのイメージをそのまま書きこんで起動しようとしても、エラーになって出来なかった。

そこで最後の手段として、VHDのイメージをXenConverterで読み込んで、変換先に「XenServer」を指定して変換して見た。これはなんとか上手く行った。XenConverterでの処理は1台の仮想マシンにつき2時間~5時間ぐらいかかるので大変だったけれども、最終的にはほとんどの仮想マシンをこの方法で元通り稼働させる事が出来た。

復旧後のXenServerのホストはもちろん「TeraStation無し」で動いている。今はローカルストレージをメインで使って、プラス別のLinuxサーバーのNFSシェアを共有ストレージとして使っている。

「NFSは遅いだろう」という先入観があったけれども、TeraStationのiSCSIの時と比べると変わらない。というよりもむしろパフォーマンスは良くなっているかも知れない。