はじめに
ブラックジャックのエラー治すのがしんどかった。
何回も見直してもエラー出るのでなにかと思ったら、 関数の処理でstd::cout << std::cout << std::end; << std::endl
というような二重にstd::cout
を出力していた。
関数を作りすぎるとこういう失敗もあるんだと思った。
BlackJack【3日目】
<修正前>
#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;
}
}
Judge関数を最初void型にしていて、関数の中でどのようにしてwhile文を抜け出すか考えていた。関数の中でbreak
を定義しても、コンパイルエラーになった。そして、bool型にすることで、while文でif文が作ることができることを思いついた。
しかし、カードを引いたときに値が増えていない。あと、引いたカードが0を表示される。
もしかして、関数の引数に動的配列はできない?
いろいろ調べてみたら
(https://qiita.com/shun-shun123/items/69af670f0332fa424f6e)
こんな記事が出てきた。
引数に動的配列をするには&をつけたらもとのvectorにも反映されるみたい。
参照渡しっていいましたね。前にもやったけど、思いつかなかった。(要復習!)
<修正後>
#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;
}
}
無事実行できました。
関数化に成功しました。
今日クラスを作ろうと思ったが、エラー地獄から抜けられなくて時間足りなくなった。明日は、ディーラーの関数作ってクラス作ってみようと思う。
ロベールのC++
07-10 スコープ解決演算子
クラス名::メンバ名
で好きなメンバを呼ぶことができる。
たとえ、オーバーライドしても、スコープ解決演算子を使えばオーバーライド前の関数をよぶことができる。
std::cout
とかも同じ。
終わりに
明日はクラスの動的確保。
本ではnew
やdelete
を使っているが、前に教えていただいたスマートポインタを使って実装しようと思う。
おやすみなさい。