#include #include #include "game.h" #include "player.h" #include "util.h" void initPlayers(Game *game, const int initChips, const int playerCount, const int botCount) { // プレイヤー数の設定(人間プレイヤー + ボット) game->playerCount = playerCount + botCount; initDealer(&game->dealer); game->players = (Player *)malloc(game->playerCount * sizeof(Player)); int *indices = (int *)malloc(game->playerCount * sizeof(int)); for (int i = 0; i < game->playerCount; i++) { indices[i] = i; } // プレイヤーの順番をランダムにシャッフル for (int i = game->playerCount - 1; i > 0; i--) { int j = rand() % (i + 1); int temp = indices[i]; indices[i] = indices[j]; indices[j] = temp; } for (int i = 0; i < game->playerCount; i++) { if (indices[i] < playerCount) { char defaultName[MAX_NAME_LEN]; snprintf(defaultName, MAX_NAME_LEN, "User%.2d", (indices[i] + 1) % 100); initPlayer(&game->players[i], initChips, defaultName); } else { initBot(&game->players[i], initChips); } } free(indices); } void initGame(Game *game) { initDeck(game->deck); shuffleDeck(game->deck); game->deckIndex = 0; initDealer(&game->dealer); for (int i = 0; i < game->playerCount; i++) { game->players[i].surrendered = 0; game->players[i].bet = 0; game->players[i].handSize = 0; game->players[i].handValue = 0; game->players[i].splitBet = 0; game->players[i].splitHandSize = 0; game->players[i].splitHandValue = 0; game->players[i].hasSplit = 0; } } Card drawCard(Game *game) { return game->deck[game->deckIndex++]; } void displayTitle() { int startX = (getTerminalWidth() - 52) / 2; if (startX < 1) startX = 1; printf("\033[2J\033[H"); printf("\033[1m\033[47m"); printf("\033[2;%dH", startX); printf("\033[31m ____ _ _ "); printf("\033[30m _ _ "); printf("\033[3;%dH", startX); printf("\033[31m | _ \\| | | | "); printf("\033[30m | | | | "); printf("\033[4;%dH", startX); printf("\033[31m | |_) | | __ _ ___| | __ "); printf("\033[30m | | __ _ ___| | __ "); printf("\033[5;%dH", startX); printf("\033[31m | _ <| |/ _` |/ __| |/ / "); printf("\033[30m _ | |/ _` |/ __| |/ / "); printf("\033[6;%dH", startX); printf("\033[31m | |_) | | (_| | (__| < "); printf("\033[30m| |__| | (_| | (__| < "); printf("\033[7;%dH", startX); printf("\033[31m |____/|_|\\__,_|\\___|_|\\_\\ "); printf("\033[30m \\____/ \\__,_|\\___|_|\\_\\ "); printf("\033[8;%dH", startX); printf("\033[31m "); printf("\033[30m "); printf("\033[39m\033[49m\033[0m"); printf("\033[10;1H"); fflush(stdout); } void _displayBoard(const Game *game, const int init, const int status, const int playerIndex, const char playerAction, const int splitAction) { // プレイヤー人数に応じて表示幅を計算 int contentWidth = 20 * game->playerCount; // ディーラーの手札表示(初期状態では2枚目以降は裏向き) int startX = (getTerminalWidth() - contentWidth) / 2; if (startX < 1) startX = 1; printf("\033[2J\033[H"); printf("\033[1;%dH", startX + (contentWidth - 20) / 2); printf("%s", game->dealer.name); printf("\033[2;%dH", startX + (contentWidth - 20) / 2); for (int i = 0; i < game->dealer.handSize; i++) { if (init == 1 && i != 0) { printCardBack(); } else { printCard(game->dealer.hand[i]); } printf(" "); } // プレイヤーの表示 for (int i = 0; i < game->playerCount; i++) { int x = 4; int y = startX + (i * 20); printf("\033[%d;%dH", x, y); if (game->players[i].bet > 0) { printf("[%ld]", game->players[i].bet); } else { printf("[]"); } if (game->players[i].hasSplit) { printf("\033[%d;%dH", x, y + 9); if (game->players[i].splitBet > 0) { printf("[%ld]", game->players[i].splitBet); } else { printf("[]"); } } for (int j = 0; j < game->players[i].handSize; j++) { if (game->players[i].hasSplit && j % 2 == 0) { printf("\033[%d;%dH", x + 1 + (j / 2), y); } else if (!game->players[i].hasSplit && j % 4 == 0) { printf("\033[%d;%dH", x + 1 + (j / 4), y); } else { printf(" "); } printCard(game->players[i].hand[j]); } if (game->players[i].hasSplit) { for (int j = 0; j < game->players[i].splitHandSize; j++) { if (j % 2 == 0) { printf("\033[%d;%dH", x + 1 + (j / 2), y + 9); } else { printf(" "); } printCard(game->players[i].splitHand[j]); } } printf("\033[%d;%dH", x + 3, y); if (game->players[i].isBot) { printf("%s (%ld)", game->players[i].name, game->players[i].chips); } else { printf("\033[4m%s\033[0m (%ld)", game->players[i].name, game->players[i].chips); } if (status) { for (int t = 0; t <= game->players[i].hasSplit; t++) { printf("\033[%d;%dH", x + 4, y + 9 * t); printLastGame(&game->players[i], t); } } else { if (playerIndex == i) { printf("\033[%d;%dH", x + 4, y + splitAction * 9); if (playerAction == 'H' || playerAction == 'h') { printf("Hit"); } else if (playerAction == 'D' || playerAction == 'd') { printf("Double"); } else if (playerAction == 'R' || playerAction == 'r') { printf("Surr"); } else { printf("Stand"); } } } } printf("\033[10;1H"); fflush(stdout); } void displayBoard(const Game *game, const int init) { _displayBoard(game, init, 0, -1, 'n', 0); } void displayStatus(const Game *game) { _displayBoard(game, 0, 1, -1, 'n', 0); } void displayAction(const Game *game, const int playerIndex, char action, int split) { _displayBoard(game, 1, 0, playerIndex, action, split); } void _processBet(Game *game, Player *player, GameStatus *lastGame, long *bet, const int handValue, const int handSize, const double bjRate) { // サレンダーの場合の処理 if (player->surrendered) { *lastGame = GameSurrender; } // ディーラーがバーストした場合の処理 else if (game->dealer.handValue > 21) { if (handValue <= 21) { // ブラックジャック(21で2枚)の場合は高配当 if (handValue == 21 && handSize == 2) { *lastGame = GameBlackJack; player->chips += (long)(*bet * (bjRate + 1.0)); printf("SYSTEM> %s won. %ld chips back.\n", player->name, (long)(*bet * 2.5)); } else { *lastGame = GameWin; player->chips += *bet * 2; printf("SYSTEM> %s won. %ld chips back.\n", player->name, *bet * 2); } } else { *lastGame = GameLose; printf("SYSTEM> %s lose.\n", player->name); } } // ディーラーがバーストしなかった場合の処理 else { if ( handValue > 21 || game->dealer.handValue > handValue) { *lastGame = GameLose; printf("SYSTEM> %s lose.\n", player->name); } else if (game->dealer.handValue < handValue) { if (handValue == 21 && handSize == 2) { *lastGame = GameBlackJack; player->chips += (long)(*bet * 2.5); printf("SYSTEM> %s won. %ld chips back.\n", player->name, (long)(*bet * 2.5)); } else { *lastGame = GameWin; player->chips += *bet * 2; printf("SYSTEM> %s won. %ld chips back.\n", player->name, *bet * 2); } } else { *lastGame = GameDraw; player->chips += *bet; printf("SYSTEM> %s is draw. %ld chips back.\n", player->name, *bet); } } *bet = 0; } void processBet(Game *game, Player *player, const double bjRate) { _processBet(game, player, &player->lastGame, &player->bet, player->handValue, player->handSize, bjRate); } void processSplitBet(Game *game, Player *player, const double bjRate) { _processBet(game, player, &player->splitLastGame, &player->splitBet, player->splitHandValue, player->splitHandSize, bjRate); } int processAction(Game *game, const int playerIndex, const int split, const char action) { Player *player = &game->players[playerIndex]; // Hit if (action == 'H' || action == 'h') { addCardToHand(player, drawCard(game)); displayAction(game, playerIndex, action, split); if (player->handValue > 21) { printf("SYSTEM> %s busted!\n", player->name); return 1; } } // Split else if ((action == 'P' || action == 'p') && canSplit(player)) { processSplit(player); displayAction(game, playerIndex, action, 0); csleep(0.5); addCardToHand(player, drawCard(game)); displayAction(game, playerIndex, action, 0); csleep(0.5); addCardToSplitHand(player, drawCard(game)); displayAction(game, playerIndex, action, 0); } // Double Down else if ((action == 'D' || action == 'd') && canDoubleDown(player, split)) { if (split) { placeBet(player, player->splitBet, split); addCardToSplitHand(player, drawCard(game)); } else { placeBet(player, player->bet, split); addCardToHand(player, drawCard(game)); } displayAction(game, playerIndex, action, split); if (player->handValue > 21) { printf("SYSTEM> %s busted!\n", player->name); } return 1; } // Surrender else if ((action == 'R' || action == 'r') && canSurrender(player)) { processSurrender(player); displayAction(game, playerIndex, action, split); printf("SYSTEM> %s surrendered.\n", player->name); csleep(1); return 1; } // Stand else if (action == 'S' || action == 's') { displayAction(game, playerIndex, action, split); csleep(1); return 1; } else { printf("SYSTEM> Invalid call\n"); return 0; } return 0; }