LoginSignup
1
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-03-23

はじめに

ブラックジャックのエラー治すのがしんどかった。
何回も見直してもエラー出るのでなにかと思ったら、 関数の処理で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を使っているが、前に教えていただいたスマートポインタを使って実装しようと思う。
おやすみなさい。

1
0
11

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0