prg-lang-2 / final / BlackJack / player.h
player.h
Raw
#ifndef PLAYER_H
#define PLAYER_H

#include "card.h"

#define MAX_NAME_LEN 11
#define MAX_DRAW_CARD 11
#define MAX_CHIPS 999999999

/**
 * @brief ゲーム結果の状態
 *
 * 1回のゲームで起こりうる結果を表す列挙型。
 */
typedef enum
{
    GameWin = 1,       /**< プレイヤーの勝ち */
    GameDraw = 2,      /**< ディーラーとの引き分け */
    GameLose = 3,      /**< プレイヤーの負け */
    GameBlackJack = 4, /**< ブラックジャックでの勝ち */
    GameSurrender = 5, /**< サレンダー(降り)*/
    GameNone = 0       /**< ゲーム未終了 */
} GameStatus;

/**
 * @brief プレイヤー構造体
 *
 * プレイヤーの手札、賭け金、ゲームの状態など全ての情報を保持する。
 * 通常の手札とスプリット(分割)手札の両方に対応。
 */
typedef struct
{
    char name[MAX_NAME_LEN]; /**< プレイヤーの表示名 */
    long chips;              /**< 現在のチップ数 */
    int isBot;               /**< コンピュータプレイヤーかどうか */
    int surrendered;         /**< サレンダーしたかどうか */

    Card hand[MAX_DRAW_CARD]; /**< メインの手札 */
    int handSize;             /**< メイン手札のカード枚数 */
    int handValue;            /**< メイン手札の合計値 */
    long bet;                 /**< メイン手札への賭け金 */
    GameStatus lastGame;      /**< メイン手札の結果 */

    Card splitHand[MAX_DRAW_CARD]; /**< スプリット手札 */
    int splitHandSize;             /**< スプリット手札のカード枚数 */
    int splitHandValue;            /**< スプリット手札の合計値 */
    long splitBet;                 /**< スプリット手札への賭け金 */
    GameStatus splitLastGame;      /**< スプリット手札の結果 */
    int hasSplit;                  /**< スプリットしたかどうか */
} Player;

/**
 * @brief ボット用のランダムな名前を選択
 *
 * @return const char* 定義済みリストからランダムに選んだ名前
 */
const char *chooseRandomName();

/**
 * @brief ディーラーの初期化
 *
 * ディーラーの初期状態を設定し、名前を"Dealer"に設定する。
 *
 * @param player ディーラーとして初期化するプレイヤー構造体
 */
void initDealer(Player *player);

/**
 * @brief ボットプレイヤーの初期化
 *
 * コンピュータ制御のプレイヤーをランダムな名前と初期チップで設定する。
 *
 * @param player 初期化するプレイヤー構造体
 * @param initChips 初期チップ数
 */
void initBot(Player *player, const int initChips);

/**
 * @brief 人間プレイヤーの初期化
 *
 * 人間プレイヤーを指定された名前と初期チップで設定する。
 *
 * @param player 初期化するプレイヤー構造体
 * @param initChips 初期チップ数
 * @param name プレイヤーの表示名
 */
void initPlayer(Player *player, const int initChips, const char *name);

/**
 * @brief ダブルダウン可能か確認
 *
 * プレイヤーが十分なチップを持っており、手札が適切な状態か確認する。
 *
 * @param player 確認するプレイヤー
 * @param split スプリット手札を確認するかどうか
 * @return int 可能なら1、不可能なら0
 */
int canDoubleDown(const Player *player, const int split);

/**
 * @brief サレンダー可能か確認
 *
 * プレイヤーが最初のターンで2枚の手札を持っているか確認する。
 *
 * @param player 確認するプレイヤー
 * @return int 可能なら1、不可能なら0
 */
int canSurrender(const Player *player);

/**
 * @brief サレンダーの処理
 *
 * 賭け金の半額を返却し、プレイヤーをサレンダー状態にする。
 *
 * @param player サレンダーするプレイヤー
 */
void processSurrender(Player *player);

/**
 * @brief 賭け金の設定
 *
 * プレイヤーからチップを差し引き、賭け金として設定する。
 *
 * @param player 賭けを行うプレイヤー
 * @param amount 賭け金額
 * @param split スプリット手札への賭けかどうか
 * @return int 成功なら1、チップ不足なら0
 */
int placeBet(Player *player, const long amount, const int split);

/**
 * @brief メイン手札にカードを追加
 *
 * カードを追加し、手札の合計値を更新する。
 *
 * @param player カードを受け取るプレイヤー
 * @param card 追加するカード
 */
void addCardToHand(Player *player, const Card card);

/**
 * @brief スプリット手札にカードを追加
 *
 * カードを追加し、スプリット手札の合計値を更新する。
 *
 * @param player カードを受け取るプレイヤー
 * @param card 追加するカード
 */
void addCardToSplitHand(Player *player, const Card card);

/**
 * @brief スプリット可能か確認
 *
 * プレイヤーが十分なチップを持っており、同じランクの2枚のカードを
 * 持っているか確認する。
 *
 * @param player 確認するプレイヤー
 * @return int 可能なら1、不可能なら0
 */
int canSplit(const Player *player);

/**
 * @brief スプリットの処理
 *
 * 手札を2つに分け、それぞれに同額の賭け金を設定する。
 *
 * @param player スプリットを行うプレイヤー
 */
void processSplit(Player *player);

/**
 * @brief 手札の価値を計算
 *
 * ブラックジャックのルールに従って手札の合計値を計算する。
 * エースを1または11として適切に扱う。
 *
 * @param hand カードの配列
 * @param handSize カードの枚数
 * @return int 手札の合計値
 */
int calculateHandValue(const Card hand[MAX_DRAW_CARD], const int handSize);

/**
 * @brief ゲーム結果の表示
 *
 * 勝敗結果を適切な形式で表示する。
 *
 * @param player 結果を表示するプレイヤー
 * @param split スプリット手札の結果を表示するかどうか
 */
void printLastGame(const Player *player, const int split);

#endif