正月を潰して仕事、そのあた気疲れ(?)とインフルエンザの打撃…ってな感じで1月があっという間に過ぎてしまったわけですが。「あっという間」かどうかは、過去を振り替えてみるとわかるかも、ということで、しばらくは、日記風に blog を書き綴るということで、調子を戻しましょう > 自分、うんうん。
最初はチープな画面を作ってロジックを確認を | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3982
の続きです。
- データクラスを作成する
- チープな画面を作成する
ってことで、Model と View が揃ったので、ゲームロジックを作っていきます。データ形式の持ち方はこれでいいのか?ってのを確かめるためでもあるし、ざっとゲームロジックを作ることで、それが「遊べるものかどうか?」ってのが確認できます。ええ、「遊べなそう」ってのが分かったら清く捨ててしまえばいいのです。そのために、この手のデータクラスとか、チープな画面をさっくりと作るのは大切かと。
この方法は、業務アプリでもよくやる方法で、「捨て去ってもいい時間」を使ってプロトタイプ的なものを作ります。世の中のプロトタイプだとお客に見せるために、結構手を込んだものを作る場合がありますが(プレゼンテーション的な意味があるので、それはそれで重要なのです)、自分で確認するプロトタイプ≒これが本当に動くのかどうかのプロトタイプの場合は、「捨てても惜しくない時間を割り当てます」。2,3時間というところでしょうか。長くて1日ですね。ただ、最近気づいたのは、1日でさっくりできるようになるための「実力」を付けるのは結構鍛錬がいるのではないかな、ということ。20年前のパソコン通信の頃の「この人の開発スピードってすごいな!」って程度には、やっとこさ、達することができたような気が…するんだけど、どうでしょう?いやいや、本当のところが、がっと集中して作れる程度が2,3時間ってところなんですけどね。ってことかも。
■データを作成する
さて、通常はそれらしいサンプルを作成するとこから(データクラスの操作性の確認も兼ねて)始めるわけですが、花札の場合は枚数が限られているので、データも作ってしまいます。
Card クラスに持たせてしまうのは異論がある!(私もある!)のですが、ざっと作ったということで。ゲームとしては「こいこい」を作る予定なので、点数自体には意味がないのですが、カス札とか短冊とかを区別するために必要ってことです。このあたりはユーティリティクラスを作っても同じですね。データ量が多い場合は、検索時の効率を考えて、ってのもあるのですが、このぐらいならば全件検索しても特に問題ないし。
/// <summary> /// カード /// </summary> public class Card { string _id; ... static protected Dictionary<string,int> _tens; /// <summary> /// 点数を取得 /// </summary> public int Ten { get { if (Card._tens == null) { Card._tens = new Dictionary<string, int>(); Card._tens["A1"] = 20; // 松に鶴 Card._tens["A2"] = 5; Card._tens["A3"] = 1; Card._tens["A4"] = 1; Card._tens["B1"] = 10; // 梅に鶯 Card._tens["B2"] = 5; Card._tens["B3"] = 1; Card._tens["B4"] = 1; Card._tens["C1"] = 20; // 桜に幕 Card._tens["C2"] = 5; Card._tens["C3"] = 1; Card._tens["C4"] = 1; Card._tens["D1"] = 10; // 藤にホトトギス Card._tens["D2"] = 5; Card._tens["D3"] = 1; Card._tens["D4"] = 1; Card._tens["E1"] = 10; // 菖蒲に八つ橋 Card._tens["E2"] = 5; Card._tens["E3"] = 1; Card._tens["E4"] = 1; Card._tens["F1"] = 10; // 牡丹に蝶 Card._tens["F2"] = 5; Card._tens["F3"] = 1; Card._tens["F4"] = 1; Card._tens["G1"] = 10; // 萩に猪 Card._tens["G2"] = 5; Card._tens["G3"] = 1; Card._tens["G4"] = 1; Card._tens["H1"] = 20; // ススキに月 Card._tens["H2"] = 10; Card._tens["H3"] = 1; Card._tens["H4"] = 1; Card._tens["I1"] = 10; // 菊に盃 Card._tens["I2"] = 5; Card._tens["I3"] = 1; Card._tens["I4"] = 1; Card._tens["J1"] = 10; // 銀杏に鹿 Card._tens["J2"] = 5; Card._tens["J3"] = 1; Card._tens["J4"] = 1; Card._tens["K1"] = 20; // 小野道風に蛙 Card._tens["K2"] = 10; Card._tens["K3"] = 5; Card._tens["K4"] = 1; Card._tens["L1"] = 50; // 桐に鳳凰 Card._tens["L2"] = 1; Card._tens["L3"] = 1; Card._tens["L4"] = 1; } return Card._tens[_id]; } } public override string ToString() { return _id; } }
■役を作る
ざっくりとデータができたら、役を作ります。いわゆるカードゲームの場合は、同じパターンで作るのではないかな、と。最初は「役を計算する」部分と「点数を計算する」部分とを独立させて作っていたのですが、結局のところ「役」を使って「点数」を計算することになるので、CalcYaku と CalcTen は無関係になっていません。まあ、これはこれでよいかと。
/// <summary> /// 役クラス /// </summary> public class Yaku { public List<Card> GoKou; public List<Card> ShiKou; public List<Card> AmeShiKou; public List<Card> SanKou; public List<Card> InoShika; public List<Card> AkaTan; public List<Card> AoTan; public List<Card> Hanami; public List<Card> Tukimi; public List<Card> Tane; public List<Card> Tan; public List<Card> Kasu; } /// <summary> /// ゲームルールライブラリ /// </summary> public class Game { ... /// <summary> /// 役を計算する /// </summary> /// <param name="cards"></param> /// <returns></returns> public Yaku CalcYaku(List<Card> cards) { Yaku yaku = new Yaku(); // 菊に盃の有無をチェック bool I1 = cards.Find(n => n.ID == "I1") != null; // 20点札をチェック var cs = cards.FindAll(n => n.Ten == 20); if (cs.Count == 5) yaku.GoKou = new List<Card>( cs ); else if ( cs.Count == 4 ) if (cs.Find(n => n.ID == "K1") != null ) yaku.AmeShiKou = new List<Card>( cs ); else yaku.ShiKou = new List<Card>( cs ); else if ( cs.Count == 3 ) yaku.SanKou = new List<Card>( cs ); // 花見、月見 cs = cards.FindAll(n => n.ID == "I1" || n.ID == "C1"); if ( cs.Count == 2 ) yaku.Hanami = new List<Card>(cs); cs = cards.FindAll(n => n.ID == "I1" || n.ID == "H1"); if (cs.Count == 2) yaku.Hanami = new List<Card>(cs); // 猪鹿蝶 cs = cards.FindAll(n => n.ID == "G1" || n.ID == "J1" || n.ID == "F1"); if (cs.Count == 3) { yaku.InoShika = new List<Card>(cs); // タネに追加 yaku.Tane = cards.FindAll(n => n.Ten == 10); } // 赤短 cs = cards.FindAll(n => n.ID == "A2" || n.ID == "B2" || n.ID == "C2"); if ( cs.Count == 3 ) yaku.AkaTan = new List<Card>(cs); // 青短 cs = cards.FindAll(n => n.ID == "I2" || n.ID == "J2" || n.ID == "F2"); if ( cs.Count == 3 ) yaku.AoTan = new List<Card>(cs); if (yaku.AkaTan != null || yaku.AoTan != null) { // タンに追加 yaku.Tan = cards.FindAll(n => n.Ten == 5); } // タネ if ( yaku.Tane == null ) { cs = cards.FindAll(n => n.Ten == 10); if ( cs.Count >= 5 ) yaku.Tane = new List<Card>(cs); } // タン if ( yaku.Tan == null ) { cs = cards.FindAll(n => n.Ten == 5); if ( cs.Count >= 5 ) yaku.Tane = new List<Card>(cs); } // カス cs = cards.FindAll(n => n.Ten == 1); if ( I1 == true && yaku.Tane.Find(n=>n.ID== "I1") == null ) cs.Add( cards.Find( n=>n.ID == "I1" )); if ( cs.Count >= 10 ) yaku.Kasu = new List<Card>(cs); return yaku; } /// <summary> /// 点数を計算する /// </summary> /// <param name="yaku"></param> /// <returns></returns> public int CalcTen( Yaku yaku ) { int ten = 0; // 20点札をチェック if (yaku.GoKou != null) ten += 10; // 五光 if (yaku.SanKou != null) ten += 8; // 四光 if (yaku.AmeShiKou != null) ten += 7; // 雨四光 if (yaku.SanKou != null) ten += 5; // 三光 if (yaku.Hanami != null) ten += 5; // 花見 if (yaku.Tukimi != null) ten += 5; // 月見 if (yaku.InoShika != null) // 猪鹿蝶 { ten += 5; // タネ分を加算 if (yaku.Tane != null) ten += yaku.Tane.Count - 3; } if (yaku.AkaTan != null) ten += 5; // 赤短 if (yaku.AoTan != null) ten += 5; // 青短 if (yaku.AoTan != null || yaku.AkaTan != null) { // タン分を加算 if (yaku.Tan != null) ten += yaku.Tan.Count - yaku.AkaTan.Count - yaku.AoTan.Count; } // タネ if (yaku.Tane != null && yaku.InoShika == null) ten += yaku.Tane.Count - 4; // タン if (yaku.Tan != null && yaku.AkaTan == null && yaku.AoTan == null) ten += yaku.Tan.Count - 4; // カス if (yaku.Kasu != null) ten += yaku.Kasu.Count - 9; return ten; } }
で、これを組み込んで、チープな画面を使ってテストをすると、そこそこ「遊べる」ことがわかります。昔ならばコマンドラインでぽちぽちとキーボードでテストをしていたのですが、Windows フォームが簡単にできるようになったので、これはこれでよいかと。
■お次は
- データクラスを作成する
- チープな画面を作成する
- ゲームロジックを作成する
ってところまでできたので、この度は View の部分を少しリッチにしてみます。
リッチにするところは、
- 花札の画像を使って表示する。
- 花札ゲームのアクションを作る。
ってところです。花札の画像自体は、Windows ストア アプリのゲーム画像を流用するとして、アクションの部分は、MVVM とユーザーコントロールとの兼ね合いもあるので、ちょっと試行中。
お疲れ様でした。
インフルエンザでしたか。
ついつい、日々何やっているか忘れがちですものね。
実は人生初のインフルエンザでしたyo。
いろいろ、途中と気分が飛んでしまったので、ブログはしばらくだらだらペースで書く予定ですね。