最終バージョン一歩手前とインターフェース
インターフェース
ユーザインターフェース
⇒ コンピュータと人間の間を取り持つ機構
例)入力インターフェース:ボタン、マウス操作、アイコン
CUI: Character-based (Command) User Interface ⇒ キャラクタ(文字)でコンピュータに命令を送り操作するインターフェース (CLI)
GUI: Graphical User Interface ⇒ 画像を使ってコンピュータに命令を送り操作するインターフェース
最終バージョン一歩手前
#include <iostream>
#include <string>
#include <iomanip>
using std::cout;
using std::endl;
using std::cin;
using std::string;
//トランプ trump
//4つのマークsuit ->
//1~13の数字
//1->A 11->J 12->Q 13->K 表示されている数
//
//トランプのカード1枚当たりのデータ
struct aCard
{
//スペード:0 ハート:1 ダイヤ:2 クラブ:3 ジョーカー:4
int s_num;
//カードの数字 1~13 + ジョーカー:0?
int c_value;
};
const int num_of_cards = 52; //13 * 4
struct aCard cards[num_of_cards];//13 * 4 各スートのカード + ババ 1枚
const string suit[5] = { "S", "H", "D", "C", "B" }; //空白はジョーカー用
//2~9,A,J,Q,Kの表示用文字 + ジョーカー B
const string c_dsp_val[14] = { "B","A","2","3","4","5","6","7","8","9","10","J","Q","K" };
//カード1デッキにマークと数字をセットする関数
//第1引数 struct aCard* _c : カードを表す配列のポインタ(アドレス)
//第2引数 int num : カードの枚数(多分53)
void initCards(struct aCard* _c, int num)
{
for (int j = 0; j < 4; j++) {
for (int i = 1; i <= 13; i++)
{
_c[j * 13 + i - 1].s_num = j;
_c[j * 13 + i - 1].c_value = i;
}
}
//_c [num_of_cards - 1].s_num = 4;
//_c [num_of_cards-1].c_value = 0;
}
//
void printaCard(struct aCard* _c)
{
//cout << (*_c).suit[(*_c).s_num] << (*_c).c_dsp_val[(*_c).c_value];
cout << suit[_c->s_num] << c_dsp_val[_c->c_value];
}
//トランプのカードを並び順に一覧表示
void printAllCards(struct aCard* _c, int num)
{
for (int i = 0; i < num_of_cards; i++)
{
printaCard(_c + i);
cout << " ";
}
cout << endl;
}
//シャッフル=カードをばらばらにする。
//struct aCard cards[num_of_cards];
//cards[0]~cards[52]の53枚のカードがあるとき
//これをシャッフルする方法を考えてください
void shuffleCards(struct aCard* _c, int num)
{
//randを使ってどうにかしてカードをシャッフルする
for (auto i = 0; i < 100; i++)
{
int s1 = rand() % num_of_cards;
int s2 = rand() % num_of_cards;
std::swap(_c[s1], _c[s2]);
}
}
struct aCard
popCard(struct aCard* _c, int num, int* cp)
{
if (*cp < num)
{
struct aCard tmp = _c[*cp];
(*cp)++;
return tmp;
}
}
// 関数名 calcCardPoint
// 戻り値 intでカードの得点を計算して返す
// ただし、BJの時は 0 を返す
// 引数 カードの配列 struct aCard *_cards
// カードの数 int num
int calcCardPoint(struct aCard* _cards, int num)
{
int point = 0;//カードの合計値
//カードが2枚の時はブラックジャックの判定が必要
//ブラックジャックの時は0を返す
//ブラックジャックじゃないときは、合計値を返す
if (num == 2)//_cards[0], _cards[1]しかないよ
{
if ((_cards[0].c_value == 1 && _cards[1].c_value >= 10)
|| (cards[0].c_value >= 10 && cards[1].c_value == 1))
{
return 0;//ブラックジャックの時
}
else
{
//Aは11点。絵札は全部10点
int tmp0 = 0, tmp1 = 0;
if (_cards[0].c_value >= 11)
tmp0 = 10;
else if (_cards[0].c_value == 1)
tmp0 = 11;
else
tmp0 = _cards[0].c_value;
if (_cards[1].c_value >= 11)
tmp1 = 10;
else if (_cards[1].c_value == 1)
tmp1 = 11;
else
tmp1 = _cards[1].c_value;
point = tmp0 + tmp1;
if (point >= 22)
{
for (int i = 0; i < num; i++)
{
if (_cards[i].c_value == 1) {
point = point - 10;
}
}
//もしカードの合計が22以上の時は、Aを1と数える
//アルゴリズム
//カードを全部、走査してAがあったら
//11→1点で数えなおす 得点合計からAを見つけるたびに10点引けばいい
}
return point;
}
}
//カードが3枚以上の時は、カードの合計値を返す
else
{
//Aは11点。絵札は全部10点
//※21を超えたら、Aがないか確認して、あったら1点で数える
int tmp = 0;
for (int i = 0; i < num; i++) {
if (_cards[i].c_value >= 11)
tmp = 10;
else if (_cards[i].c_value == 1)
tmp = 11;
else
tmp = _cards[i].c_value;
point = point + tmp;
}
if (point >= 22)
{
for (int i = 0; i < num; i++)
{
if (_cards[i].c_value == 1) {
point = point - 10;
}
}
//もしカードの合計が22以上の時は、Aを1と数える
//アルゴリズム
//カードを全部、走査してAがあったら
//11→1点で数えなおす 得点合計からAを見つけるたびに10点引けばいい
}
return point;
}
}
// 関数名 printOnesCards
// 戻り値 なし
// 引数 カードの配列 struct aCard *_cards
// カードの数 int num
void printOnesCards(struct aCard* _cards, int num)
{
for (int i = 0; i < num; i++) {
printaCard(_cards + i);
cout << " ";
}
cout << endl;
}
int main()
{
int sp = 0;//デッキから配られたカード数
int p_card_n = 0;//プレイヤーの手持ちカード数
struct aCard p[12];//12枚分確保
int d_card_n = 0;//ディーラーの手持ちカード数
struct aCard d[12];//12枚分確保
srand((unsigned int)time(nullptr));//乱数の初期化
initCards(cards, num_of_cards); //カードを初期化
shuffleCards(cards, num_of_cards);//カードをシャッフル
d[0] = popCard(cards, num_of_cards, &sp);
d_card_n++;
d[1] = popCard(cards, num_of_cards, &sp);
d_card_n++;
p[0] = popCard(cards, num_of_cards, &sp);
p_card_n++;
p[1] = popCard(cards, num_of_cards, &sp);
p_card_n++;
printOnesCards(p, p_card_n);
int player_Point = 0;
int dealer_Point = 0;
player_Point = calcCardPoint(p, p_card_n);
if (player_Point != 0)
{
int command;
cout << "プレイヤーのカードの合計ポイントは" << player_Point << "です。" << endl;
while (true) {
cout << "どうしますか?" << endl;
cout << "1:もう一枚(Hit)" << endl;
cout << "2:これで勝負(Stand)" << endl;
cin >> command;
if (command == 1)
{
cout << "カードをひくよ" << endl;
p[p_card_n] = popCard(cards, num_of_cards, &sp);//カード引く処理
p_card_n++;//プレイヤーの持ちカード数更新
printOnesCards(p, p_card_n);
player_Point = calcCardPoint(p, p_card_n);//得点計算
cout << "プレイヤーのカードの合計ポイントは" << player_Point << "です。" << endl;
//バースト(22を超える)するとその時点で負けなので、ループを抜ける
if (player_Point > 21) {
break;
}
//バーストの時はループ抜けるか
}
else if (command == 2)
{
cout << "これで勝負だ!" << endl;
break;
}
else
{
cout << "エラー!1 or 2 を入力してください。" << endl;
}
}
}
//cout << "ここで結果表示します" << endl;
cout << "相手の手札:" << endl;
printOnesCards(d, d_card_n);
dealer_Point = calcCardPoint(d, d_card_n);
cout << "相手の点数: " << dealer_Point << endl;
//もう一枚(Hit)
//これで勝負(Stand)
//player_Point ← 自分の得点 0はBJ
//dealer_Point ← 相手の得点 0はBJ
if (player_Point == 0) {//自分がBJの時に
if (dealer_Point == 0) {//相手もBJ
cout << "この勝負 引き分け!" << endl;
}
else
{
cout << "Black Jack!" << endl;
cout << "Player Win!" << endl;
}
}
else
{//自分がBJではないとき
if (dealer_Point == 0) {//相手だけBJ
//ディーラーだけブラックジャック
cout << "Dealer Win!" << endl;
}
else
{//相手もBJではない
//両方バーストの時
//片方バースト1:プレイヤーのみバーストの時
//片方バースト2:ディーラーのみバーストの時
//両方バーストじゃないとき
if (player_Point > 21 && dealer_Point > 21) {
cout << "両者バースト:引き分け" << endl;
}
else if (player_Point > 21 && dealer_Point <= 21) {
cout << "バースト:Dealer Win!" << endl;
}
else if (player_Point <= 21 && dealer_Point > 21)
{
cout << "ディーラーバースト:Player Win !" << endl;
}
else if (player_Point > dealer_Point) {
cout << "Player Win!" << endl;
}
else if (player_Point < dealer_Point)
{
cout << "Dealer Win!" << endl;
}
else//同点の時
{
cout << "この勝負 引き分け!" << endl;
}
}
}
}
力試し
- 結果表示の処理を関数化してみよう。
- ディーラーもカードを引くようにしてみよう
- ちょっとしたAI気分で書いてみよう。
- 簡単なのは、16以下の時は引く、それ以外は引かない、というアルゴリズム
- カードが上限こえることに対して、現在はエラー処理をしていない。危ないのでエラー処理をきちんとやる