はじめに
C++によるゲーム開発をいくつか行ってきました.次に開発を行いたいと考えたのがブラックジャックです.トランプカードゲームの代表例であるゲームですが,シンプルなルールなので作りやすかったです.ぜひプレイしてみてください.
ブラックジャックとは
ブラックジャックのルールは以下のようになっているそうです.
(参考:https://casinocafe.jp/casinovenus/game/blackjack/)
- カジノディーラーがカードを2枚ずつ配ります.
- カジノディーラーは順番に各プレイヤーに対してカードの追加を行うか(アクション)を聞いていきます.
- カードを追加(ヒット)する場合は、テーブルを軽く叩いてください.カードは何枚でもヒットできますが、21点を越えてしまうとその時点で失格(バスト)となります.
- 手持ちの点数が十分だと思ったら,手を横に振り,カードをいらないことを示し(スタンド),その点数のままでディーラーと勝負することになります.
- プレイヤー全員が選択を終えた後,最後にディーラーがカードをめくり,17点以上になるまでカードを引き続け,勝負となります.
- ディーラーよりも21点に近いプレイヤーは勝ち,逆にディーラーよりも21点に遠いプレイヤーは負けとなります.なお、同点の場合はプッシュといい、引き分けとなります.
追記:賭け金の制度を導入しました(2024/07/31)
実装してみた
header.h
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <thread>
#include <chrono>
using namespace std;
extern int deck[13]; //山札記録用変数
int initialization(void);
int betting(int);
int sum_card(vector<int> a);
int draw();
void show_card(vector<int>);
functions.cpp
#include"header.h"
int initialization(void) {
ios::sync_with_stdio(false);
cin.tie(nullptr);
srand((unsigned int)time(NULL));
for (int i = 0;i < 13;i++)
deck[i] = 4; //山札生成
cout << "コインを何枚購入しますか?";
int coin;
cin >> coin;
return coin;
}
int betting(int coin) {
int bet;
while (true) {
cout << "コインを何枚賭けますか?(所持:" << coin << "枚)";
cin >> bet;
if (bet > coin) {
cout << "所持枚数より少ない数を入力してください.\n";
continue;
}
return bet;
}
}
int sum_card(vector<int> a) { //手札の合計を計算する.
int sum = 0;
for (int i = 0;i < a.size();i++) {
if (a[i] > 10) sum += 10; //11~13も10として数えられる
else sum += a[i];
}
if (find(a.begin(), a.end(), 1) != a.end() && sum <= 11)
sum += 10; //1は1または11の都合の良い方で数えられる
return sum;
}
int draw() { //カードを引く関数
int r;
while (true) {
r = rand() % 13 + 1; //乱数生成
if (deck[r - 1] > 0) { //山札に含まれるカードのみ処理
deck[r - 1]--;
break;
}
}
return r;
}
void show_card(vector<int> a) {
cout << "のカードは"; //カード出力
for (int i : a)
cout << i << " ";
cout << "です.\n";
}
main.cpp
#include"header.h"
int deck[13];
int main(void) {
int coin = initialization();
int flag = 0;
int count = 0;
int sum_player = 0;
while (coin > 0) {
vector<vector<int>> card(2); //手札記録用変数
count++;
cout << "\n"<< count << "回目の勝負を開始します.\n";
int bet;
bet = betting(coin);
for (int i = 0;i < 2;i++) {
for (int j = 0;j < 2;j++)
card[i].push_back(draw()); //初めにプレイヤー,ディーラーの両方に二枚配る
}
cout << "\nプレイヤー"; //プレイヤーのカード出力
show_card(card[0]);
sum_player = sum_card(card[0]);
while (true) {
cout << "もう一枚引きますか?(y or n)"; //引く場合はy,引かない場合はnを入力
char s;
cin >> s;
if (s == 'n')
break;
card[0].push_back(draw());
cout << "\nプレイヤー"; //プレイヤーのカード出力
show_card(card[0]);
sum_player = sum_card(card[0]);
if (sum_player > 21) { //21を超えたらバストしてプレイヤーの負け
cout << "バストしました.\n";
coin -= bet;
flag = 1;
break;
}
}
if (flag == 1)
continue;;
cout << "あなたのスコアは" << sum_player << "です.\n\n";
cout << "ディーラー"; //ディーラーのカード出力
show_card(card[1]);
while (true) {
int sum_dealer = sum_card(card[1]);
if (sum_dealer <= 16) { //ディーラーはスコアが16以下のときはさらに引く
card[1].push_back(draw());
sum_dealer = sum_card(card[1]);
}
cout << "ディーラー"; //ディーラーのカード出力
show_card(card[1]);
if (sum_dealer > 21) { //21を超えたらバストしてディーラーの負け
cout << "ディーラーのスコアは" << sum_dealer << "です." << "\n";
cout << "ディーラーがバスト\nプレイヤーの勝利";
coin += bet;
break;
}
else if (sum_dealer >= 17) { //17を超えたら引くのをやめて勝敗判定
cout << "ディーラーのスコアは" << sum_dealer << "です." << "\n";
if (sum_dealer == sum_player)
cout << "ドロー\n";
else if (sum_dealer > sum_player) {
cout << "ディーラーの勝利\n";
coin -= bet;
}
else {
cout << "プレイヤーの勝利\n";
coin += bet;
}
break;
}
}
}
cout << "所持金がなくなりました\n";
return 0;
}