paizajackで使えそうなユーティリティ作ってみた(C#)

# きっかけ
[一攫千金プログラミングpaizajackを遊んでみた \- Qiita](https://qiita.com/kithz39/items/5550246c40ac5cab170c) を見て。

あとは組み合わせてどう勝率をあげるかみたいな。

## 手役計算クラス Cards
カード情報はスペース区切りの数値がなのでこれを上手いことバラして手役を計算する。
BJ判定とかバースト判定とかする。

![スクリーンショット (79).png](https://qiita-image-store.s3.amazonaws.com/0/199750/225bc63c-189f-9849-3362-e8688d607363.png)


```C#:Cards.class
    class Cards {
        private List<int> data;
        public Cards(string input) {
            this.data = new List<int>();
            foreach (var s in input.Split(' ')) {
                this.data.Add(int.Parse(s));
            }
        }
        public int value {
            get {
                if (!this.isValid) return 0;
                int sum = 0;
                foreach (var i in clone) {
                    if (i == 1) {
                        sum += 10;
                    }
                    sum += i;
                }
                //バーストしてて1が手役にあったらバーストしない最大数まで減算
                if (sum>21 && clone.Any(i => i == 1)) {
                    double cc = Math.Min(Math.Ceiling((sum - 21) / 10f), (double)clone.Count(i => i == 1));
                    sum -= (int)cc * 10;
                }
                return sum;
            }
        }
        public bool isValid { get { return data.FirstOrDefault() > 0; } }
        public bool isBlackjack { get { return this.value == 21; } }
        public bool isBurst { get { return this.value > 21; } }
        public int mergin { get { return 21 - this.value; } }
        public IEnumerable<int> List {
            get {
                foreach (var i in this.data) yield return i;
            }
        }
    }
```

### プロパティ

- value : 現在の数字
- isValid : 正しいカード情報か。(1回目判定用)
- isBlackjack : BJ判定
- isBurst : バスト判定
- mergin : 次回BJになるために必要な数
- List : カード参照用

### 使い方
```C#:Cards_Usage
var cards = new Cards(Console.ReadLine());
if (!cards.isValid) { //初回
    Console.WriteLine("100"); // 賭けチップ数
} else {
    if (cards.value>16) Console.WriteLine("STAND") ;
    else Console.WriteLine("HIT") ;
}
```

## 残り札管理 Field
ステージ4の六村リオからディーラーの手札が見えるので、これを利用して残山を管理したり期待値出したりする。

```C#:Field
class Field {
    private List<int> stock = new List<int>();
    public Field() {
        //4 x 13種類で初期化
        for (int i = 0; i < 9; i++) {
            stock.Add(4);
        }
        // 10 J Q K は10扱い
        stock.Add(4 * 4);
    }
    //手持ちのカード分 山から減算
    public Field sub(Cards cards) {
        foreach (var i in cards.List) {
            stock[i - 1]--;
        }
        return this;
    }
    // num 以下のカードを引くパーセンテージ
    public double nextPercentage(int num) {
        if (num > 10) num = 10;

        int sumSafety = stock.Take(num).Sum();
        int sumCards = stock.Sum();
        return 100f * (double)sumSafety / (double)sumCards;
    }
}
```
### メソッド
- sub : 残山から手札分を減算
- nextPercentage(int num) : 次にnum以下のカードを引く確率を計算

### 使い方
```C#:Field_usage
    var cards = new Cards(Console.ReadLine());
    Console.ReadLine(); //読み飛ばし 現在何戦目かを示す数字
    Console.ReadLine(); //読み飛ばし 現在何連勝かを示す数字
    Console.ReadLine(); //読み飛ばし 最大BETチップ数
    var dealer_cards = new Cards(Console.ReadLine()); //ディーラーのカード

    var field = new Field().sub(cards).sub(dealer_cards);
    // ディーラーのバースト率が80%超えたら高みの見物
    if (field.nextPercentage(dealer_cards.margin) < 20 ){
        Console.WriteLine("STAND") ;
    }else{
```