ASP.NET Core版 対人対戦できるぷよぷよをつくる(7)の続きです。前回はユーザー登録してプレイした人の記録を残す機能を実装しました。今回は開始から勝敗が決するまでの過程(将棋や囲碁でいうところの棋譜)を残すことができるように改良します。

棋譜のフォーマット

まず棋譜のフォーマットを決めます。ここから参照できます。

最初の1行は2人の対戦者の名前と勝者(0か1か)がタブ区切りになっています。空白行が2行あって次にあるのが対戦開始からの経過秒です。

そのあと1行の空白行があってカンマ区切りされた “-1_0,-1_0,-1_0,3_0,0_0,0_0″のような行が13列あります。整数値がアンダーバー(”_”)でつながっていますが、これはぷよの種類と連鎖発生時に表示される数字です。連鎖が発生していないときは右側の数字はすべて0になります。

これが2セットあり、そのあと空白行1行のあと”4_2_4_4,4_2_4_4″のようなカンマとアンダーバーで区切られた数字がありますが、これがネクストぷよです。カンマで両プレイヤーのネクストぷよが区切られていて、それぞれがアンダーバーで区切られていて、それぞれが2個で1セットの次回と次々回のぷよになっています。

さらにカンマで区切られた数字があります。これは両者のスコアです。その下にさらにカンマで区切られた数字があります。これが予告ぷよの数です。

さらにそのあとに空白行が2行ありますが、ここから次のサイクルになります。

ではこれらの文字列を生成するためのメソッドを示します。PuyoMatchGameクラスに処理を追加します。

フィールド上に存在するぷよを文字列に変換

以下はフィールド上に存在するぷよを文字列に変換するためのメソッドです。対象はすでに固定されているぷよだけではなく、落下中の組ぷよ、落下中のおじゃまぷよも含みます。

棋譜として保存する文字列を生成する

以下は上記も含めて棋譜として保存する文字列をすべて取得するメソッドです。

棋譜にはゲーム開始時からの経過時間も保存したいので、ゲーム開始時に現在時刻をフィールド変数に格納する処理を追加します。

2戦目以降がはじまるときも開始時刻を初期化します。

StringBuilderクラスを利用して棋譜として文字列を保存する

以下のような状態の変化が起きた場合は、これを保存します。

ぷよが着地したとき
連鎖が発生したとき
おじゃまぷよの落下が完了したとき
勝敗が決したとき

上記のときでGetStringForSaveメソッドが実行された結果、前回取得された文字列と違いがある場合、メモリー上に保存します。

SaveStringToMemoryメソッドを実行するのは、ぷよが着地したとき、連鎖が発生したとき、おじゃまぷよの落下が完了したとき、勝敗が決したときです。そこでこれらが起きたとき呼び出されるイベントハンドラ内でSaveStringToMemoryメソッドを呼び出します。

着地したときは連鎖がまったく発生しないときでもBeginRensaとFinishRensaイベントは発生します。そこでここでSaveStringToMemoryメソッドを呼び出します。

連鎖が進行しているときもSaveStringToMemoryメソッドを呼び出します。

おじゃまぷよの落下が完了したときもSaveStringToMemoryメソッドを呼び出します。コンストラクタ内でOjamaFalledのイベントハンドラを追加しておきます。

棋譜をファイルとして保存する

決着がついたらこれをテキストファイルとして保存します。

テキストファイルを保存する場所はアプリケーションをアップロードするフォルダの外側にしています。これはメンテナンスのときに間違ってローカル上のファイルで上書きしてしまわないようにするためで、とくに意味はありません。

ファイル名で保存された時刻がわかるようにしています。また他の対戦が同時に終わったとき例外が発生することがあるので例外処理をしています。

このメソッドを実行するのはGameOveredイベントハンドラです。

たまに同時に窒息してしまうことがあります。そこで両方が勝者になってしまわないように IsPlaying が false のときはなにもしません。これで同時に窒息した場合も片方が勝者、他方が敗者になることを保証しています。