研修でブラックジャックを作ったまとめ

# 目次
[1.はじめに](#1-はじめに)
[2.使用言語 使用ツール](#2-使用言語-使用ツール)
[3.設計](#3-設計)
[4.実装](#4-実装)
[5.テスト](#5-テスト)
[6.おわりに](#6-おわりに)

# 1. はじめに

24年4月から新社会人となり、この１ヶ月研修を受けさせていただきました。
研修ではUdemyでJavaやUMLについて学んだ後に開発研修としてJavaでブラックジャックを制作しました。
今回は開発研修の総括としてQiitaで記事を書いていきます。

今回制作することとなったブラックジャックは[こちらのサイト](https://bright777.com/rules_blackjack)のルールを参考にさせていただきました。

# 2. 使用言語 使用ツール

| 言語/ツール | 用途 |
|:-----------|:-----|
| Java | 開発言語 |
| plantUML | 基本設計での作図 |
| git | プロジェクトのバージョン管理 |
| Exel | テストシート作成 |
| Backlog | 課題の管理 |
| VSCode | コードエディタ |

# 3. 設計
4/15~4/16

今回要件定義の内容はゲームのルールであり、サイトを参考にしているためサイトからのリストアップのみを行った。
基本設計として、使用言語、基本ルール、最低要件、ゲームフローを決定した。また、それをもとにアクティブ図と入出力設計を作成した。
### 基本ルール

- ディーラー（DL）とプレイヤー（PL）の対戦型
- カードの合計が21点に近ければ勝利
  - 配当は1倍
- カードの合計が21点を超えると負け
  - 賭け金を失う
- **2~9**は**そのまま**、**10, J, Q, K**
- **A** は「**1点or11点**」
- **最初に配られた**２枚のカードが **”Aと10点札”** で**21点**が完成していた場合「ブラックジャック」
    - その時点で勝ち
    - 配当は 1.5倍
    - 引き分けあり
- 所持金は300$
- 最低25$から賭けられる
- 掛け金がなくなった場合ゲームオーバー
- 配当は賭け金を含めない

### ゲームフロー

1. 賭け金を決める
2. PLにカードを表２枚で配る
3. DLにカードを表１裏１枚で配る
4. DLがPLにカードの補充を行うか聞く
    1. 21点を超えなければ何回でも行える
    2. 21点を超えると失格(バースト)
    3. 十分と判断すれば勝負へ
5. DLはカードを表にし、17点以上になるまでカードを引き続け勝負へ
6. ディーラーより21点に近ければ勝利
    1. 勝：掛け金と同額の配当がもらえる
    2. 負：掛け金が没収
    3. 引き分け
7. もう一度遊ぶ/終了する

### アクティビティ図
```plantuml
@startuml
start
'賭け金を決めます
:BET;
'カードを配ります
:DEAL;

'PLがブラックジャックかどうか
if (PL:BlackJack?) then (Yes)
    'ブラックジャックだった場合自動で勝負へ
else (No)
    'ヒットするか
    while(HIT?)is(Hit)
        'カードを一枚引く
        :PL:AddCard;
        'バストしたかどうか
        if(BUST?) then (Yes)
            end
        endif
    'スタンドを選択
    endwhile(stand)
        'DLのホールドカードをアップカードに
        :UpCard;
        'DLがブラックジャックか
        if(DL:BlackJack?)then(Yes)

        else(No)
            '17以上になるまでカードを引く
            while (Bigger than 16?) is (No) 
                :DL:AddCard;
                if(BUST?) then (Yes)
                    end
                endif
            endWhile(Yes)
        endif
endif

'DLとPLのハンドを比較し勝ち、負け、プッシュを判断します
:Judge;

'勝敗から賭け金に応じた報酬を支払います
:reward;

end
@enduml
```

### 詳細設計
クラス図を作成した。
今回の詳細設計ではアクセス修飾子やメソッド扱いなどの細かい部分には触れなかったので、今後は詳細設計の段階より詳しく定義を行っていきたい。
```plantuml
@startuml

class BlackJack {
~ boolean isWin
~ void clearHand()
+ {static} void main(String[])
~ void bet(int)
~ void playerHit()
~ void dealerHit()
~ int calPoint()
~ int judge(int,int)
~ void calReward(int,int)
~ boolean canContinue()
~ void gameOver()
}

package デッキ{

    class Deck {
    + Card drawCard
    - int deckIndex
    - List<Card> deck
    + Card draw()
    ~ void reset()
    }
    note left of Deck : Cardを52通り生成しListに格納する


    class Card {
    - Pattern pattern
    - Number number
    + Number getNumber()
    + Pattern getPattern()
    }
    note left of Card : 数字と柄の組み合わせが52通りある


    enum Pattern {
    +  HEART
    +  CLOVER
    +  DIAMOND
    +  SPADE
    - String cardPattern
    }
    note top of Pattern : カードの絵柄の情報を管理

    enum Number {
    +  one
    +  two
    +  three
    +  four
    +  five
    +  six
    +  seven
    +  eight
    +  nine
    +  ten
    +  eleven
    +  twelve
    +  thirteen
    - int cardPoint
    - String cardNum
    }
    note top of Number : カードの数字の情報を管理
}

package キャラクタ{
    class Player {
    - int money
    + int bet()
    + void hit()
    + Card getPlayerHand()
    }
    note bottom of Player : プレイヤーの情報を管理する

    class Dealer {
    + void hit()
    + Card getDealerHand()
    }
    note bottom of Dealer : ディーラーの情報を管理する

    abstract class Human {
    ~ boolean bust
    ~ boolean bj
    ~ List<Card> hand
    ~ {abstract}void hit()
    ~ void cardOpen()
    ~ Boolean isBust()
    ~ Boolean isBJ()
    }
}

package お金 {
    class Money {
    - int playerMoney
    - int betMoney
    + int getBetMoney()
    + int getPlayerMoney()
    + void setPlayerMoney(int)
    }
    note bottom of Money : お金を管理する，Playerのコンストラクタで生成
}

class Output {
- String state
- int plPoint
- int dlPoint
- List<Card> plHands
- List<Card> dlHands
- String choices
- int betMoney
- int money

~ void gameLog(String,int,int,List<Card>,List<Card>,String,int,int)
~ void ruleLog()
}

Deck "1"-up-"1..52" Card
Card -up- Number
Card -up- Pattern

BlackJack -- Output

BlackJack -left- Deck

BlackJack -right- Dealer
BlackJack -right- Player

Player *-right- Money

Human <|-- Player
Human <|-- Dealer
@enduml
```

# 4. 実装
4/17~4/23
基本設計、詳細設計を基に実装を行った。

### ポイント
- クラス毎に明確な役割を決定する
    - 今回は実際のゲームの役割に例えた
- オブジェクト指向
    - 継承
    - カプセル化
    - Static
- モジュール結合度は弱く
    - コードレビューで指摘を頂いて修正した
- 行数削減

ディレクトリ構成は以下の通り。

```
root/
  ┗ Java/
     ┣ Character/
     ┃   ┣ Human.java
     ┃   ┣ Dealer.java
     ┃   ┣ Player.java
     ┃   ┗ Money.java
     ┣ Deck/
     ┃   ┣ Deck.java
     ┃   ┗ Card.java
     ┣ BlackJack.java
     ┗ Output.java
```
### BlackJack.java
 メインメソッドを持っているクラスであり、クラス間の値の受渡しや値の入力、スコアの計算などを行っている。

### Character/
 Human.javaはPlayr.javaとDealer.javaの親クラスである。フィールドとして手札のリストや手札のポイントが定義され管理されている。
 また、Money.javaにはプレイヤーのお金や賭け金を管理するためのメンバーが用意されており、Player.javaとはコンポジションの関係にある。
  Player.javaはHuman.Javaのサブクラスでありお金の管理が追加されている。

### Deck/
列挙型のクラス2つからCard.javaでカードの実体を生成する。
カードをインスタンス化したらDeck.javaのリストに入れることでデッキを作ることができる。
カードを配る際はdrawメソッドを呼び出すことでindex変数を参照してその場所のカードを渡すことができる。

### Output.java
BlackJack.javaから渡された情報を標準出力へ表示する。
 
## 5. テスト
4/24~4/25
基本設計をもとにエクセルでテストケースを作成しテストを行った。
大項目、小項目、確認内容、結果の項目に沿ってそれぞれテストケースを制作し、テストの可否を判断した。

### ポイント
- 境界値
    - 25未満の場合に正しい結果が出るか確かめたい
    - テストの確認内容を「24を入力」とする
- 初見の人が見てもわかるように記述する
    - 手順と結果に具体的な数値を示す


# 6. おわりに
今回の研修課題でブラックジャックを制作することで、オブジェクト指向について理解することが出来た。また設計段階から開発を行うことで、実際の業務ではどのようにしてクライアントの要件に正確に沿ったものを納品するのかを体験することが出来た。また、ブラックジャックを通してオブジェクト指向の考え方をより理解できた。今後新たな言語を学ぶ際の基準点ともしていきたい。