﻿○システム名
  ブラックジャック

○システム説明
  通常のブラックジャックです。

○納品物
  作成したプログラム

1段階目（Cardクラスの作成）
以下のクラスを作成する。
実行できないのでコンパイルエラーがなくなれば1段階目は完成とする。
・クラス名：Card
・フィールドはそれぞれint型のsuitとrankを定義。
　　suit：マークのこと。0:スペード、1:ハート、2:ダイヤ、3:クラブとする。
　　rank：数字のこと。1:A、11:J、12:Q、13:Kとする。
・Cardクラスはカプセル化し、フィールドはprivateとし、セッターメソッドを作成せず、
　publicなゲッターメソッドのみ作成する。
・セッターメソッドを作成しない代わりにsuitとrankを引数に持つコンストラクタを作成し、
　コンストラクタの中でフィールドにセットする。

2段階目（カード内容の表示）
Cardクラスに以下のpublicメソッドを追加実装する。
・メソッド名：toString
・引数　　　：なし
・戻り値　　：カードのマークと数字を以下の形式の文字列でリターンする
　　　　　　　　ハート　3
　　　　　　　　ダイヤ　A
　　　　　　　　クラブ　10
　　　　　　　　スペード　Q
Test1クラスを作成し、mainメソッドの中で以下を実行する。
・Cardクラスのインスタンスを以下のように4個作成し、c1～c4に格納する。
　　　　　　　　c1:ハート　3
　　　　　　　　c2:ダイヤ　A
　　　　　　　　c3:クラブ　10
　　　　　　　　c4:スペード　Q
・System.out.println()メソッドの引数にc1～c4を指定し、以下のように表示する。
＜実行例＞
ハート　3
ダイヤ　A
クラブ　10
スペード　Q

3段階目（Deckクラスの作成）
以下のクラスを作成する。
実行できないのでコンパイルエラーがなくなれば3段階目は完成とする。
・クラス名：Deck　　←ひと組のカード、という意味
・フィールドはArrayList<Card>型のcardListを定義。
・引数なしのコンストラクタを作成し、以下の処理を行う。
　〇cardListにArrayList<Card>のインスタンスを作成する
　〇二重のfor文を使用して52枚のCardクラスのインスタンスをcardListに追加する
・Deckクラスのフィールドはprivateとするが、ゲッター・セッターメソッドは作成しないこととする。

4段階目（shuffleメソッド、drawCardメソッドの実装）
Deckクラスに以下のpublicメソッドを追加実装する。
実行できないのでコンパイルエラーがなくなれば3段階目は完成とする。
・shuffleメソッド
　〇引数　：なし
　〇戻り値：なし
　〇機能　：cardListの中の52枚のカードをランダムに並び替える
・drawCardメソッド
　〇引数　：なし
　〇戻り値：cardListにカードが残っていれば先頭のカード（cardList[0]）をリターン
　　　　　　cardListにカードが残っていなければnullをリターン
　〇機能　：リターンした先頭のカードはcardListから削除し、2枚目以降を前につめる(ArrayListの機能を利用すること)

5段階目（シャッフルしたカードを表示）
Test2クラスを作成し、mainメソッドの中で以下の処理を行う。
・Deckクラスのインスタンスを作成する
・作成したDeckインスタンスをシャッフルする
・シャッフルしたDeckインスタンスをカードがなくなるまで以下を繰り返す
　〇先頭のカードを引く
　〇引いたカードを画面に表示する
＜実行例＞
ハート　3
ダイヤ　A
　　：
クラブ　10
スペード　Q　　←全部で52行表示される

6段階目（Handクラスの作成）
以下のクラスを作成する。
実行できないのでコンパイルエラーがなくなれば6段階目は完成とする。
・クラス名：Hand　　←トランプの参加者、という意味
・以下のフィールドを定義する
　〇hands  ：ArrayList<Card>型、protected　←このhandsは手札の意味
　〇name   ：String型、protected
・以下の内容のpublicなコンストラクタを定義する。
　〇引数　：名前
　〇機能　：handsにArrayList<Card>のインスタンスを作成し、nameに引数の名前をセットする
・以下の内容のpublicなdrawCardメソッドを定義する。
　〇引数　：Deckクラスのインスタンス
　〇戻り値：なし
　〇機能　：Deckインスタンスから1枚カードを引き、handsに追加する
・以下の内容のpublicなshowHandメソッドを定義する。
　〇引数　：なし
　〇戻り値：なし
　〇機能　：handsの中の全てのカードを以下の形式で画面に表示する
<nameの値>の手札
　⇒　ハート　3
　⇒　ダイヤ　A
・handsはゲッター、セッターは不要、nameはゲッターメソッドのみ作成する

7段階目（Playerクラスの作成）
以下のクラスを作成する。
実行できないのでコンパイルエラーがなくなれば7段階目は完成とする。
・クラス名：Player　　←Handクラスを継承する
・以下の内容のpublicなコンストラクタを定義する。
　〇引数　：名前
　〇機能　：引数の名前を使って親クラスのコンストラクタを呼び出す
・以下の内容のpublicなselectメソッドを定義する。　　←HitかStandかの選択をする意味
　〇引数　：Deckクラスのインスタンス
　〇戻り値：boolean型。Hitを選択した場合false、Standを選択した場合true。
　〇機能　：「どうしますか？」「1:Hit - もう一枚カードを引く」「2:Stand - この手札で勝負」の3行を表示する。
　　　　　　キーボードから入力させ、1か2以外であれば「ちゃんとやって」を表示し、再入力する。
　　　　　　1を入力した場合はデッキから1枚カードを引き、手札に追加する。

8段階目（Standするまで繰り返し）
BlackJackクラスを作成し、mainメソッドで以下の処理を行う。
・Playerインスタンスを名前を「あなた」で作成する
・Deckクラスのインスタンスを作成する
・作成したDeckインスタンスをシャッフルする
・Playerが2枚カードを引く
・以下の処理をbreakが実行されるまで繰り返す。
　〇Playerの手札を表示する
　〇区切りの「**********」を表示する
　〇Playerインスタンスのselectメソッドを呼び出し、Standを選択したらループを抜ける
・Standが選択されたら区切りの「@@@@」を表示する
＜実行例＞
あなたの手札
　⇒　ハート　A
　⇒　スペード　5
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
3　　　　　　　　　　　　←正しくない入力の場合
ちゃんとやって
1　　　　　　　　　　　　←Hitを入力の場合
あなたの手札
　⇒　ハート　A
　⇒　スペード　5
　⇒　スペード　J
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
2　　　　　　　　　　　　←Standを入力の場合
@@@@

9段階目（合計値表示）
Handクラスにprotectedのフィールドtotalを追加する。
totalはセッターは作成せず、ゲッターメソッドのみ作成する。
Handクラスに以下のメソッドを追加する。
・calculateTotalメソッド　private。
　〇引数　：なし
　〇戻り値：なし
　〇機能　：handsの中のカードのrankをすべて足し合わせる。
　　　　　　ただし、Aは11、J～Kは10と計算する。
　　　　　　合計が21を超えた場合、最大でhandsの中のAの数だけ10を減算する。
・isNaturalBlackJackメソッド　public。
　〇引数　：なし
　〇戻り値：ナチュラルブラックジャックならtrue、違う場合はfalse
　〇機能　：totalが21で手札の枚数が2のときナチュラルブラックジャックと判定する。
HandクラスのdrawCardメソッドの最後でcalculateTotalメソッドを呼び出す処理を追加する。
BlackJackクラスのmainメソッドで、Playerの手札を表示した後、以下の処理を追加する。
・PlayerインスタンスのgetTotalメソッドを使って合計値を表示する
「**********」を表示した後、以下の処理を追加する。
・ナチュラルブラックジャックか判定し、trueなら「ナチュラルブラックジャック！」を表示し、ループを抜ける
・合計値が21を超えていたら「Busted！」を表示し、ループを抜ける
＜実行例＞
あなたの手札
　⇒　ハート　3
　⇒　ダイヤ　7
合計値：10
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
1
あなたの手札
　⇒　ハート　3
　⇒　ダイヤ　7
　⇒　ハート　9
合計値：19
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
1
あなたの手札
　⇒　ハート　3
　⇒　ダイヤ　7
　⇒　ハート　9
　⇒　スペード　3
合計値：22
**********
Busted！
@@@@

10段階目（Dealerクラスの作成）
以下のクラスを作成する。
実行できないのでコンパイルエラーがなくなれば10段階目は完成とする。
・クラス名：Dealer　　←Handクラスを継承する
・以下の内容のpublicなコンストラクタを定義する。
　〇引数　：なし
　〇機能　：名前を「ディーラー」として親クラスのコンストラクタを呼び出す

11段階目（ディーラーの手札表示）
Cardクラスにboolean型のflgUpフィールドを追加し、初期値はtrueとする。
追加したflgUpはprivateとし、publicなゲッター、セッターメソッドを作成する。
CardクラスのtoStringメソッドで、カードが裏になっている場合は「？？？？？？？」を
リターンするように修正する。
Handクラスに以下のメソッドを追加する。
　〇メソッド名：getCard　public
　〇引数　　　：index(先頭0)
　〇戻り値　　：手札のindex枚目のカード

　〇メソッド名：showHand　public
　〇引数　　　：boolean型の公開フラグとlong型のミリ秒
　〇戻り値　　：なし
　〇機能　　　：handsの中の全てのカードを以下の形式で画面に表示するが、
　　　　　　　　1行表示するたびに引数のミリ秒だけsleepする。
　　　　　　　　また、1行の表示内容は公開フラグがtrueの場合は以下のようにする。
<nameの値>の手札を公開します。
HandクラスのもともとあったHandクラスの引数なしのshowHandメソッドは上記で追加したメソッドを
falseと0Lの引数で呼び出すのみとする。
BlackJackクラスのmainメソッドで、以下のよう変更する。
・Prayerクラスのインスタンス作成をやめ、、Hand型の長さ2の配列hands(参加者の意味)を作成し、
　[0]にDealerクラスの、[1]にPlayerクラスのインスタンスを作成するように変更する。
・参加者全員にdrawCardメソッドを使って2枚ずつカードを配る。
・ディーラーの手札の2枚目は裏にするため、CardクラスのsetFlgUpメソッドを使い、false(裏)にする。
・ディーラーの手札をshowHandメソッドで表示し、区切りの「**********」を表示する。
・ディーラーの手札の表示が終わったら2枚目を表に戻しておく。
・プレイヤーがStandかBustしたあと、
　公開フラグをtrue、ミリ秒を1000にしてディーラーの手札を表示する。
＜実行例＞
ディーラーの手札
　⇒　ダイヤ　A
　⇒　？？？？？？？
**********
あなたの手札
　⇒　ハート　K
　⇒　スペード　2
合計値：12
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
1
あなたの手札
　⇒　ハート　K
　⇒　スペード　2
　⇒　ハート　3
合計値：15
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
2
@@@@
ディーラーの手札を公開します。
　⇒　ダイヤ　A
　⇒　クラブ　3

12段階目（ディーラーの合計表示）
Dealerクラスに以下のpublicなメソッドを追加する。
　〇メソッド名：drawAdditionalCard
　〇引数　　　：Deckインスタンス
　〇戻り値　　：なし
　〇機能　　　：totalが17未満である間、カードを1枚引く
BlackJackクラスのmainメソッドで以下を修正する。
・プレイヤーがカードを引き終えた後、
　プレイヤーがBustしていなければDealerクラスのdrawAdditionalCardを呼び出す。
・ディーラーの手札を表示後、ディーラーの合計値を表示する。
＜実行例＞
ディーラーの手札
　⇒　ダイヤ　A
　⇒　？？？？？？？
**********
あなたの手札
　⇒　ハート　K
　⇒　スペード　2
合計値：12
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
1
あなたの手札
　⇒　ハート　K
　⇒　スペード　2
　⇒　ハート　3
合計値：15
**********
どうしますか？
1:Hit - もう一枚カードを引く
2:Stand - この手札で勝負
2
@@@@
ディーラーの手札を公開します。
　⇒　ダイヤ　A
　⇒　クラブ　3
　⇒　ハート　2
　⇒　ダイヤ　3
合計：19

13段階目（勝敗表示）
Dealerクラスに以下のpublicなメソッドを追加する。
　〇メソッド名：compareTo
　〇引数　　　：Playerインスタンス
　〇戻り値　　：ディーラーが勝ちなら0より大きい整数、
　　　　　　　　プレイヤーが勝ちなら0より小さい整数、
　　　　　　　　引き分けなら0
　〇機能　　　：プレイヤーがBustなら無条件にディーラーの勝ち
　　　　　　　　プレイヤーがBustでなく、ディーラーがBustならプレイヤーの勝ち
　　　　　　　　どちらか一方がナチュラルブラックジャックならその人が勝ち
　　　　　　　　上記以外は合計値が高い方が勝ち
BlackJackクラスのmainメソッドで、ディーラーの合計値を表示後、以下の処理を追加する。
・compareToメソッドの戻り値に応じ、以下のいずれかを表示する。
<プレイヤーの名前>は勝ちです。
<プレイヤーの名前>は負けです。
<プレイヤーの名前>は引き分けです。

14段階目（掛け金計算）
Handクラスに以下のpublicなメソッドを追加する。
　〇メソッド名：clearHands()
　〇引数　　　：なし
　〇戻り値　　：なし
　〇機能　　　：手札を全部削除する
Playerクラスにint型のmoneyフィールドとbetMoneyフィールドを追加する。
どちらもprivateとし、セッターは作らず、ゲッターメソッドのみpublicのみで作成する。
Playerクラスのコンストラクタの引数にmoneyを追加し、引数のmoneyをそのままフィールドにセットする
Playerクラスに以下のpublicなメソッドを追加する。
　〇メソッド名：addMoney
　〇引数　　　：加算金額
　〇戻り値　　：なし
　〇機能　　　：moneyフィールドに引数の加算金額を加える。

　〇メソッド名：bet
　〇引数　　　：なし
　〇戻り値　　：なし
　〇機能　　　：キーボードから掛け金を入力させ、以下のエラーの場合は対応するエラーメッセージを
　　　　　　　　表示して再入力させる。エラー出なければbetMoneyに設定する。
　　　　　　　　　●int型に変換できない
　　　　　　　　　　　→数値を入力してください
　　　　　　　　　●0円以下
　　　　　　　　　　　→1以上にしてね！
　　　　　　　　　●持ち金(money)を超えている
　　　　　　　　　　　→そんなにお金持ってないでしょ！
BlackJackクラスのmainメソッドに以下の処理を追加する。
・最初に以下を表示する
　　全5回ゲームを行います。
　　※ただし持ち金が無くなった時点でゲーム終了です。
・Playerのインスタンス作成時、初期の持ち金10000円とする。
・以下の処理を5回繰り返す。
　〇ゲームの最初に以下を表示する
　　(一行空行をあける)
　　<回数>回目のゲームを開始します。
　　BET金額を入力してください。（持ち金：<プレイヤーの持ち金>円）
　〇Playerクラスのbetメソッドで掛け金を入力する。
　〇区切り線「==========================================================」を表示する
　〇12段階目の処理を行う。ただし、各参加者にカードを2枚ずつ配る前に全員の手札を削除する。
　〇勝敗表示は以下とする。
<プレイヤーの名前>は勝ちです。配当金をお渡しします。
<プレイヤーの名前>は負けです。掛け金は没収します。
<プレイヤーの名前>は引き分けです。掛け金を払い戻します。
　〇負けの場合は持ち金から掛け金を減算、引き分けの場合は±0、
　　勝ちの場合は持ち金に掛け金を加算する。
　　ただし、プレイヤーがナチュラルブラックジャックで勝った場合は掛け金を1.5倍して加算。
　〇清算した結果、持ち金が0になったら以下を表示してプログラムを終了する。
お金がありません。。。もう終わりです。
　〇5回ゲームしたら最後に以下の表示をしてプログラムを終了する。
あなたのスコアは<持ち金>円でした

＜以下、時間が余った人向け＞
15段階目（例外判定）
例外処理を入れないといけないところを考えて適切に処理する
例）デッキからカードを引こうとしたらもうデッキにカードがない場合　etc

16段階目（複数のプレイヤー）
実際のカジノでは1人のディーラーが複数のプレイヤーと同時にゲームするのが普通。
プレイヤーが複数でもゲームできるようにする。

17段階目（特別ルール）
スプリットやインシュランスなどの特別ルールを実装する。
ルールはネット等で調べること。どのルールを実装するかは開発者に任せる。
