はじめてのC++【25日目】

#はじめに
ブラックジャックのエラー治すのがしんどかった。
何回も見直してもエラー出るのでなにかと思ったら、 関数の処理で`std::cout << std::cout << std::end; << std::endl`というような二重に`std::cout`を出力していた。
関数を作りすぎるとこういう失敗もあるんだと思った。

##BlackJack【3日目】
**<修正前>**

```BlackJack.cpp
#include <iostream>
#include <array>
#include <vector>
#include <numeric>
#include <random>
int Random_Number(int s,int f){
  std::uniform_int_distribution<int> dist(s,f);//s~fのランダム生成
  std::mt19937 mt{ std::random_device{}() };//ランダム作るときに必要
  return dist(mt);
}
void Draw_a_Card(std::vector<int> Hand){

  Hand.emplace_back(Random_Number(1, 10));//カードを一枚引く
}

void Choice_a_Mark(){
  constexpr const char* heart = "♥";
  constexpr const char* spade = "♠";
  constexpr const char* clover = "♣";
  constexpr const char* dia = "◆";
  switch (Random_Number(1, 4)) {
    case 1:
            std::cout << heart;
            break;
    case 2:
            std::cout << spade;
            break;
    case 3:
            std::cout << clover;
            break;
    case 4:
            std::cout << dia;
            break;
  }
}

void Show_a_Card(std::vector<int> Hand){

  std::cout << "カードは";
  Choice_a_Mark();
  std::cout << ":" << Hand.at(Hand.size()-1) << "です" << std::endl;
}

void Show_a_Sum(std::vector<int> Hand){
  std::cout << "合計値は" << std::accumulate(Hand.begin(), Hand.end(), 0) << "です" << std::endl;
}

bool Judge(std::vector<int> Hand){
  char choose = 'd';//dで初期化
  if(std::accumulate(Hand.begin(), Hand.end(), 0)> 21){//合計値が21より大きくなると負け
    std::cout << "21より大きくなりました。あなたの負けです。" << std::endl;
    //break;
    return true;
  }
  else if(std::accumulate(Hand.begin(), Hand.end(), 0)== 21){
    //break;//合計値が21丁度になると強制的に終了
    return true;
  }
  else{
    std::cout << "引き続きカードを引きますか？(y/n)" << std::endl;//カードを引くかどうかの意思決定
    std::cin >> choose;//y/nをchoooseに代入させる
    if(choose == 'n') return true;//もしnならカードを引くことを終了
    return false;
  }
}

int main(){
  std::vector<int> myself = {0};//自分の持ち札を入れる
  std::cout << "BrackJackを始めます" << std::endl;
  while (1) {
    Draw_a_Card(myself);
    Show_a_Card(myself);
    Show_a_Sum(myself);
    if(Judge(myself))break;
  }
}
```
<img width="473" alt="スクリーンショット 2019-03-23 23.18.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/298612/179639c7-0fe9-b685-ebe4-88591ba75018.png">

Judge関数を最初void型にしていて、関数の中でどのようにしてwhile文を抜け出すか考えていた。関数の中で`break`を定義しても、コンパイルエラーになった。そして、bool型にすることで、while文でif文が作ることができることを思いついた。
しかし、カードを引いたときに値が増えていない。あと、引いたカードが0を表示される。
もしかして、関数の引数に動的配列はできない？

いろいろ調べてみたら
（https://qiita.com/shun-shun123/items/69af670f0332fa424f6e）
こんな記事が出てきた。

引数に動的配列をするには&をつけたらもとのvectorにも反映されるみたい。
参照渡しっていいましたね。前にもやったけど、思いつかなかった。(要復習！)

**<修正後>**

```blackjack.cpp
#include <iostream>
#include <array>
#include <vector>
#include <numeric>
#include <random>

int Random_Number(int s,int f){
  std::uniform_int_distribution<int> dist(s,f);//s~fのランダム生成
  std::mt19937 mt{ std::random_device{}() };//ランダム作るときに必要
  return dist(mt);
}
void Draw_a_Card(std::vector<int> &Hand){

  Hand.emplace_back(Random_Number(1, 10));//カードを一枚引く
}

void Choice_a_Mark(){
  constexpr const char* heart = "♥";
  constexpr const char* spade = "♠";
  constexpr const char* clover = "♣";
  constexpr const char* dia = "◆";
  switch (Random_Number(1, 4)) {
    case 1:
            std::cout << heart;
            break;
    case 2:
            std::cout << spade;
            break;
    case 3:
            std::cout << clover;
            break;
    case 4:
            std::cout << dia;
            break;
  }
}

void Show_a_Card(std::vector<int> &Hand){

  std::cout << "カードは";
  Choice_a_Mark();
  std::cout << ":" << Hand.at(Hand.size()-1) << "です" << std::endl;
}

void Show_a_Sum(std::vector<int> &Hand){
  std::cout << "合計値は" << std::accumulate(Hand.begin(), Hand.end(), 0) << "です" << std::endl;
}

bool Judge(std::vector<int> &Hand){
  char choose = 'd';//dで初期化
  if(std::accumulate(Hand.begin(), Hand.end(), 0)> 21){//合計値が21より大きくなると負け
    std::cout << "21より大きくなりました。あなたの負けです。" << std::endl;
    //break;
    return true;
  }
  else if(std::accumulate(Hand.begin(), Hand.end(), 0)== 21){
    //break;//合計値が21丁度になると強制的に終了
    return true;
  }
  else{
    std::cout << "引き続きカードを引きますか？(y/n)" << std::endl;//カードを引くかどうかの意思決定
    std::cin >> choose;//y/nをchoooseに代入させる
    if(choose == 'n') return true;//もしnならカードを引くことを終了
    return false;
  }
}

int main(){
  std::vector<int> myself = {0};//自分の持ち札を入れる
  std::cout << "BrackJackを始めます" << std::endl;
  while (1) {
    Draw_a_Card(myself);
    Show_a_Card(myself);
    Show_a_Sum(myself);
    if(Judge(myself))break;
  }
}
```
<img width="483" alt="スクリーンショット 2019-03-23 23.21.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/298612/f5e7ab7d-05c1-498f-df08-3ee5ae605672.png">
無事実行できました。
関数化に成功しました。
今日クラスを作ろうと思ったが、エラー地獄から抜けられなくて時間足りなくなった。明日は、ディーラーの関数作ってクラス作ってみようと思う。

##ロベールのC++
###07-10　スコープ解決演算子
`クラス名::メンバ名`で好きなメンバを呼ぶことができる。
たとえ、オーバーライドしても、スコープ解決演算子を使えばオーバーライド前の関数をよぶことができる。

`std::cout`とかも同じ。

#終わりに
明日はクラスの動的確保。
本では`new`や`delete`を使っているが、前に教えていただいたスマートポインタを使って実装しようと思う。
おやすみなさい。