Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

ブラックジャックのエラー治すのがしんどかった。
何回も見直してもエラー出るのでなにかと思ったら、 関数の処理で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;
  }
}

スクリーンショット 2019-03-23 23.18.55.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;
  }
}

スクリーンショット 2019-03-23 23.21.28.png
無事実行できました。
関数化に成功しました。
今日クラスを作ろうと思ったが、エラー地獄から抜けられなくて時間足りなくなった。明日は、ディーラーの関数作ってクラス作ってみようと思う。

ロベールのC++

07-10 スコープ解決演算子

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

std::coutとかも同じ。

終わりに

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

suponji
GoでAPIサーバの開発してます。 プログラム書くのも好きだけど、設計とかセキュリティについて調べて考えるのも好き。
https://www.suptree.info
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした