消えてしまった時間が消えてしまわないように足跡を残す

正月を潰して仕事、そのあた気疲れ(?)とインフルエンザの打撃…ってな感じで1月があっという間に過ぎてしまったわけですが。「あっという間」かどうかは、過去を振り替えてみるとわかるかも、ということで、しばらくは、日記風に blog を書き綴るということで、調子を戻しましょう > 自分、うんうん。

最初はチープな画面を作ってロジックを確認を | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/3982

の続きです。

  1. データクラスを作成する
  2. チープな画面を作成する

ってことで、Model と View が揃ったので、ゲームロジックを作っていきます。データ形式の持ち方はこれでいいのか?ってのを確かめるためでもあるし、ざっとゲームロジックを作ることで、それが「遊べるものかどうか?」ってのが確認できます。ええ、「遊べなそう」ってのが分かったら清く捨ててしまえばいいのです。そのために、この手のデータクラスとか、チープな画面をさっくりと作るのは大切かと。
この方法は、業務アプリでもよくやる方法で、「捨て去ってもいい時間」を使ってプロトタイプ的なものを作ります。世の中のプロトタイプだとお客に見せるために、結構手を込んだものを作る場合がありますが(プレゼンテーション的な意味があるので、それはそれで重要なのです)、自分で確認するプロトタイプ≒これが本当に動くのかどうかのプロトタイプの場合は、「捨てても惜しくない時間を割り当てます」。2,3時間というところでしょうか。長くて1日ですね。ただ、最近気づいたのは、1日でさっくりできるようになるための「実力」を付けるのは結構鍛錬がいるのではないかな、ということ。20年前のパソコン通信の頃の「この人の開発スピードってすごいな!」って程度には、やっとこさ、達することができたような気が…するんだけど、どうでしょう?いやいや、本当のところが、がっと集中して作れる程度が2,3時間ってところなんですけどね。ってことかも。

■データを作成する

さて、通常はそれらしいサンプルを作成するとこから(データクラスの操作性の確認も兼ねて)始めるわけですが、花札の場合は枚数が限られているので、データも作ってしまいます。
Card クラスに持たせてしまうのは異論がある!(私もある!)のですが、ざっと作ったということで。ゲームとしては「こいこい」を作る予定なので、点数自体には意味がないのですが、カス札とか短冊とかを区別するために必要ってことです。このあたりはユーティリティクラスを作っても同じですね。データ量が多い場合は、検索時の効率を考えて、ってのもあるのですが、このぐらいならば全件検索しても特に問題ないし。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/// <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 は無関係になっていません。まあ、これはこれでよいかと。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/// <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 フォームが簡単にできるようになったので、これはこれでよいかと。

■お次は

  1. データクラスを作成する
  2. チープな画面を作成する
  3. ゲームロジックを作成する

ってところまでできたので、この度は View の部分を少しリッチにしてみます。
リッチにするところは、

  1. 花札の画像を使って表示する。
  2. 花札ゲームのアクションを作る。

ってところです。花札の画像自体は、Windows ストア アプリのゲーム画像を流用するとして、アクションの部分は、MVVM とユーザーコントロールとの兼ね合いもあるので、ちょっと試行中。

カテゴリー: 雑談 パーマリンク

消えてしまった時間が消えてしまわないように足跡を残す への2件のフィードバック

  1. konica のコメント:

    お疲れ様でした。
    インフルエンザでしたか。
    ついつい、日々何やっているか忘れがちですものね。

    • masuda のコメント:

      実は人生初のインフルエンザでしたyo。
      いろいろ、途中と気分が飛んでしまったので、ブログはしばらくだらだらペースで書く予定ですね。

コメントは停止中です。