fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <stdbool.h>
  5. #include <string.h>
  6.  
  7. #define MAX_PLAYERS 6
  8. #define MAX_CARDS_IN_HAND 60
  9. #define DECK_SIZE 53 // 52 + Joker(1)
  10.  
  11. typedef struct {
  12. int rank; // 1-13, Joker = 0
  13. int suit; // 0-3, Joker = -1
  14. } Card;
  15.  
  16. typedef struct {
  17. Card hand[MAX_CARDS_IN_HAND];
  18. int count;
  19. bool finished; // 上がったか
  20. bool joker_dice_used; // 特殊ルールを使ったか
  21. } Player;
  22.  
  23. /* ====== 表示補助 ====== */
  24. static const char* rank_str(int r) {
  25. switch (r) {
  26. case 1: return "A";
  27. case 11: return "J";
  28. case 12: return "Q";
  29. case 13: return "K";
  30. case 0: return "JOKER";
  31. default: return "N";
  32. }
  33. }
  34. static void print_card(Card c) {
  35. if (c.rank == 0) {
  36. printf("JOKER");
  37. } else {
  38. if (c.rank >= 2 && c.rank <= 10) printf("%d", c.rank);
  39. else printf("%s", rank_str(c.rank));
  40. }
  41. }
  42.  
  43. /* ====== 山札 ====== */
  44. static void init_deck(Card deck[DECK_SIZE]) {
  45. int idx = 0;
  46. for (int s = 0; s < 4; s++) {
  47. for (int r = 1; r <= 13; r++) {
  48. deck[idx++] = (Card){ .rank = r, .suit = s };
  49. }
  50. }
  51. deck[idx++] = (Card){ .rank = 0, .suit = -1 }; // Joker
  52. }
  53. static void shuffle_deck(Card deck[DECK_SIZE]) {
  54. for (int i = 0; i < DECK_SIZE; i++) {
  55. int j = rand() % DECK_SIZE;
  56. Card tmp = deck[i];
  57. deck[i] = deck[j];
  58. deck[j] = tmp;
  59. }
  60. }
  61.  
  62. /* ====== 手札操作 ====== */
  63. static void add_card(Player *p, Card c) {
  64. p->hand[p->count++] = c;
  65. }
  66. static Card remove_card_at(Player *p, int idx) {
  67. Card c = p->hand[idx];
  68. for (int i = idx; i < p->count - 1; i++) p->hand[i] = p->hand[i + 1];
  69. p->count--;
  70. return c;
  71. }
  72.  
  73. /* 同じrankのペアを捨てる(Jokerはペアにならない) */
  74. static int discard_pairs(Player *p) {
  75. int freq[14] = {0}; // 0..13
  76. for (int i = 0; i < p->count; i++) {
  77. int r = p->hand[i].rank;
  78. if (r != 0) freq[r]++;
  79. }
  80.  
  81. int to_discard_rank[14] = {0};
  82. for (int r = 1; r <= 13; r++) {
  83. to_discard_rank[r] = (freq[r] / 2) * 2;
  84. }
  85.  
  86. int discarded = 0;
  87. for (int r = 1; r <= 13; r++) {
  88. while (to_discard_rank[r] > 0) {
  89. for (int k = 0; k < 2; k++) {
  90. for (int i = 0; i < p->count; i++) {
  91. if (p->hand[i].rank == r) {
  92. remove_card_at(p, i);
  93. discarded++;
  94. to_discard_rank[r]--;
  95. break;
  96. }
  97. }
  98. }
  99. }
  100. }
  101. return discarded;
  102. }
  103.  
  104. static bool has_joker(const Player *p) {
  105. for (int i = 0; i < p->count; i++) {
  106. if (p->hand[i].rank == 0) return true;
  107. }
  108. return false;
  109. }
  110.  
  111. /* ====== 生存者(上がってない)関連 ====== */
  112. static int count_alive(Player players[], int n, int *last_alive) {
  113. int alive = 0;
  114. *last_alive = -1;
  115. for (int i = 0; i < n; i++) {
  116. if (!players[i].finished) {
  117. alive++;
  118. *last_alive = i;
  119. }
  120. }
  121. return alive;
  122. }
  123. static int next_alive(int cur, Player players[], int n) {
  124. for (int step = 1; step <= n; step++) {
  125. int j = (cur + step) % n;
  126. if (!players[j].finished) return j;
  127. }
  128. return -1;
  129. }
  130.  
  131. /* ====== 全員同時の手札交換(右/左) ====== */
  132. static void rotate_hands(Player players[], int n, int dir) {
  133. // dir: +1 = 右隣と交換(結果として「手札が右へ1つ移動」)
  134. // dir: -1 = 左隣と交換(結果として「手札が左へ1つ移動」)
  135. Card backup[MAX_PLAYERS][MAX_CARDS_IN_HAND];
  136. int bcount[MAX_PLAYERS];
  137.  
  138. // バックアップ
  139. for (int i = 0; i < n; i++) {
  140. bcount[i] = players[i].count;
  141. memcpy(backup[i], players[i].hand, sizeof(Card) * players[i].count);
  142. }
  143.  
  144. // 入れ替え(同時)
  145. for (int i = 0; i < n; i++) {
  146. int src = (i - dir + n) % n; // i が受け取る相手
  147. players[i].count = bcount[src];
  148. memcpy(players[i].hand, backup[src], sizeof(Card) * bcount[src]);
  149. }
  150.  
  151. // 入れ替え後にペア捨て&上がり判定
  152. for (int i = 0; i < n; i++) {
  153. if (players[i].finished) continue; // 上がってる人はそのまま(本来0枚のはず)
  154. discard_pairs(&players[i]);
  155. if (players[i].count == 0) players[i].finished = true;
  156. }
  157. }
  158.  
  159. /* ====== 特殊ルール ======
  160.   Jokerを持ってるとき、その人は1回だけサイコロを振れる
  161.   1,2: 変化なし
  162.   3,4: 全員が右隣と手札交換(同時)
  163.   5,6: 全員が左隣と手札交換(同時)
  164. */
  165. static void apply_joker_dice_rule(Player players[], int n, int player_id) {
  166. Player *p = &players[player_id];
  167. if (p->joker_dice_used) return;
  168. if (p->finished) return;
  169. if (!has_joker(p)) return;
  170.  
  171. int dice = (rand() % 6) + 1;
  172. printf("\n[P%d] Joker special: rolled %d\n", player_id, dice);
  173.  
  174. if (dice == 1 || dice == 2) {
  175. printf(" -> No change.\n");
  176. } else if (dice == 3 || dice == 4) {
  177. printf(" -> Everyone swaps hands with RIGHT neighbor (simultaneous).\n");
  178. rotate_hands(players, n, +1);
  179. } else { // 5,6
  180. printf(" -> Everyone swaps hands with LEFT neighbor (simultaneous).\n");
  181. rotate_hands(players, n, -1);
  182. }
  183.  
  184. p->joker_dice_used = true;
  185. }
  186.  
  187. /* ====== メイン ====== */
  188. int main(void) {
  189. srand((unsigned)time(NULL));
  190.  
  191. int n;
  192. printf("Number of players (2-%d): ", MAX_PLAYERS);
  193. if (scanf("%d", &n) != 1 || n < 2 || n > MAX_PLAYERS) {
  194. printf("Invalid.\n");
  195. return 0;
  196. }
  197.  
  198. Player players[MAX_PLAYERS] = {0};
  199. for (int i = 0; i < n; i++) {
  200. players[i].count = 0;
  201. players[i].finished = false;
  202. players[i].joker_dice_used = false;
  203. }
  204.  
  205. Card deck[DECK_SIZE];
  206. init_deck(deck);
  207. shuffle_deck(deck);
  208.  
  209. // 配る(順番に1枚ずつ)
  210. for (int i = 0; i < DECK_SIZE; i++) {
  211. add_card(&players[i % n], deck[i]);
  212. }
  213.  
  214. // 初期ペア捨て&上がり判定
  215. for (int i = 0; i < n; i++) {
  216. discard_pairs(&players[i]);
  217. if (players[i].count == 0) players[i].finished = true;
  218. }
  219.  
  220. // 開始プレイヤーを生存者に合わせる
  221. int cur = 0;
  222. while (players[cur].finished) cur = (cur + 1) % n;
  223.  
  224. while (1) {
  225. int last_alive;
  226. int alive = count_alive(players, n, &last_alive);
  227. if (alive == 1) {
  228. printf("\n=== GAME OVER ===\n");
  229. printf("Loser (Old Maid) is P%d\n", last_alive);
  230. break;
  231. }
  232.  
  233. // 特殊ルール(ジョーカー所持で1回だけ)
  234. apply_joker_dice_rule(players, n, cur);
  235.  
  236. // 特殊ルールで自分が上がった可能性もあるので再チェック
  237. if (players[cur].finished) {
  238. cur = next_alive(cur, players, n);
  239. continue;
  240. }
  241.  
  242. // 次の生存者から1枚引く
  243. int target = next_alive(cur, players, n);
  244. Player *p = &players[cur];
  245. Player *t = &players[target];
  246.  
  247. int idx = rand() % t->count;
  248. Card drawn = remove_card_at(t, idx);
  249. add_card(p, drawn);
  250.  
  251. printf("\n[P%d] drew a card from [P%d]: ", cur, target);
  252. print_card(drawn);
  253. printf("\n");
  254.  
  255. // ペア捨て
  256. int discarded = discard_pairs(p);
  257. if (discarded > 0) {
  258. printf("[P%d] discarded %d cards (pairs)\n", cur, discarded);
  259. }
  260.  
  261. // 上がり判定
  262. if (p->count == 0) {
  263. p->finished = true;
  264. printf("[P%d] finished (no cards)!\n", cur);
  265. }
  266. if (t->count == 0) {
  267. t->finished = true;
  268. printf("[P%d] finished (no cards)!\n", target);
  269. }
  270.  
  271. cur = next_alive(cur, players, n);
  272. }
  273.  
  274. return 0;
  275. }
  276.  
Success #stdin #stdout 0.01s 5284KB
stdin
Standard input is empty
stdout
Number of players (2-6): Invalid.