こんにちは
私は現在カードゲームを作成しています。
作成したいゲームの基本的な処理は作成できたのですが一か所どうすれば実現できるのかわからない処理があり困っています。
【ルール】
・場に出ているカードの絵柄か数字が手札のカードと同じだった場合、
一致したカードを捨てることができる。
・手札が0枚になったら勝ちとなる。
・手札枚数が51枚になり、カードを引こうとした場合プレイヤーの負けとする。
・山札が0枚になったときカードを引こうとした場合、最後に場に出したカードと手札以外のカードをシャッフルし再度山札を作る。
この最後のルールの処理を実現したいのですが特定の配列の値(手札と最後に場に出したカード値)を固定し、
その他の配列をシャッフルすれば可能なのではないかと思いました。
main関数のコメントアウトした箇所で再シャッフル用の関数(リバースデッキ関数)を呼び出してシャッフルしようとしたのですが、私の考え方が違うのかうまくいきませんでした。
どうすれば最後のルールの再シャッフル処理をできるのか知恵をお借りしたいです。
C
1#define _CRT_SECURE_NO_WARNINGS//scanf警告解除用 2#include <stdio.h> 3#include <stdlib.h> 4#include <time.h> 5 6#define CARD_MAX (52)//カード枚数 7#define SAME_CARD (13)//同じ種類のカード枚数 8#define INIT_HAND (5)//初手 9#define TRUE (1)//正 10#define FALSE (0)//負 11#define YES (1)//イエス 12#define NO (2)//ノー 13#define SPADE (0)//スペード 14#define CLUB (1)//クラブ 15#define DIA (2)//ダイヤ 16#define HEART (3)//ハート 17 18/*構造体定義*/ 19typedef struct { 20 21 unsigned int hand_cnt;//手札カウンタ 22 unsigned char card_num[CARD_MAX];//カードの種類 23 24}PLAYER_DATA; 25 26/*変数宣言*/ 27unsigned char card_deck[CARD_MAX];//カードデッキ 28unsigned int rest_cnt;//デッキ残数カウンタ 29unsigned int turn_cnt;//ターンカウンタ 30 31char number[CARD_MAX];//カード値格納用 32 33/*関数プロトタイプ宣言*/ 34void init_card(void); 35void draw_card(PLAYER_DATA *myhand); 36void output_hand(PLAYER_DATA *myhand); 37void cemetery_card(PLAYER_DATA* field, PLAYER_DATA* myhand, int *input_data); 38void delete_hand(PLAYER_DATA *myhand, int *input_data); 39int search_card(PLAYER_DATA *field, PLAYER_DATA *myhandint, int *input_data); 40void rebirth_deck(PLAYER_DATA *field, PLAYER_DATA *myhand); 41/********************************/ 42/* メイン関数 */ 43/********************************/ 44int main(int argc, char*argv[]) 45{ 46 static PLAYER_DATA myhand;//プレイヤーの手札構造体 47 PLAYER_DATA field_card;//場のカード構造体 48 49 int draw_cnt;//ドローカウンタ 50 int input;//プレイヤー入力 51 int return_num;//戻り値 52 int yes_no;//Yes or No 53 54 init_card();//デッキ初期化 55 myhand.hand_cnt = 0;//手札枚数初期化 56 field_card.hand_cnt = 0;//場のカード枚数初期化 57 turn_cnt = 1;//ターンカウンタ初期化(開始時を1ターン目とする) 58 59 /*カードを5枚ドロー*/ 60 for (draw_cnt = 0; draw_cnt < INIT_HAND; draw_cnt++) { 61 draw_card(&myhand); 62 } 63 /*場に出すカードをドロー*/ 64 draw_card(&field_card); 65 66 /*画面にカードを出力*/ 67 printf("******************************************************\n"); 68 printf("現在のターン:%dターン目\n", turn_cnt); 69 printf("******************************************************\n"); 70 printf("場のカード:\n"); 71 output_hand(&field_card); 72 printf("\nあなたの手札:\n"); 73 output_hand(&myhand); 74 75 while (1) { 76 /*************/ 77 /* 1ターン目 */ 78 /*************/ 79 printf("\n山札(残数) %d 枚\n", CARD_MAX - rest_cnt); 80 printf("\n【ルール】\n"); 81 printf("場のカードと同じ数字か同じスートの\n"); 82 printf("カードを捨てることができます。\n"); 83 printf("\n"); 84 printf("カードを捨てますか?\n"); 85 printf("(1)Yes (2)No\n"); 86 scanf("%d", &yes_no); 87 printf("\n"); 88 if (yes_no == YES) {//捨てる場合捨てるカードを選択 89 printf("捨てるカード番号を入力してください:"); 90 scanf("%d", &input); 91 return_num = search_card(&field_card, &myhand, &input); 92 if (return_num == TRUE) {//フィールドのカード値または絵柄が一致した場合 93 cemetery_card(&field_card, &myhand, &input);//card_dataの配列は[0~4]出力のため関数内で-1する 94 delete_hand(&myhand, &input); 95 } 96 else if (return_num == FALSE) { 97 printf("\n選んだ番号のカードは捨てられません。\n"); 98 printf("デッキからカードを一枚引きます。\n"); 99 100 //if (rest_cnt == CARD_MAX) { 101 //rebirth_deck(&field_card, &myhand); 102 //} 103 104 draw_card(&myhand); 105 106 } 107 } 108 else if (yes_no == NO) {//捨てない場合デッキからカードを引く 109 draw_card(&myhand); 110 if (myhand.hand_cnt == CARD_MAX) {//手札に52枚目を加えようとしたらバースト 111 printf("\nカードがなくなりました。\n"); 112 printf("あなたの負けです。\n"); 113 printf("ゲームを終了します。\n"); 114 break; 115 } 116 } 117 turn_cnt++;//カードを捨てたら1ターン目終了 118 /****************/ 119 /*以下nターン目 */ 120 /****************/ 121 printf("******************************************************\n"); 122 printf("現在のターン:%dターン目\n", turn_cnt); 123 printf("******************************************************\n"); 124 printf("場のカード:\n"); 125 output_hand(&field_card); 126 printf("\nあなたの手札:\n"); 127 output_hand(&myhand); 128 if (myhand.hand_cnt == 0) {//手札が0になったら 129 printf("\nゲームクリアおめでとうございます。\n"); 130 printf("クリアするのに%dターンかかりました。\n", turn_cnt); 131 printf("このまま終了します。\n"); 132 break; 133 } 134 } 135 136 /*デバッグ用*/ 137#if 1 138 int debag; 139 scanf("%d", &debag); 140#endif 141 return 0; 142} 143/********************************/ 144/* デッキシャッフル(初期化)関数 */ 145/********************************/ 146void init_card(void) { 147 148 int rnd;//ランダム値格納用変数 149 int tmp; 150 int arr_cnt;//配列カウンタ 151 srand((unsigned)time(NULL)); 152 153 for (arr_cnt = 0; arr_cnt < CARD_MAX; arr_cnt++) {//カード値配列初期化 154 number[arr_cnt] = arr_cnt; 155 156 } 157 158 for (rest_cnt = 0; rest_cnt< CARD_MAX; rest_cnt++) {//デッキ初期化 159 160 card_deck[rest_cnt] = rest_cnt; 161 162 } 163 164 rest_cnt = 0;//初期残数0 165 166 for (rest_cnt = 0; rest_cnt < CARD_MAX; rest_cnt++) {//デッキシャッフル 167 168 rnd = rand() % (CARD_MAX); 169 tmp = card_deck[rest_cnt]; 170 card_deck[rest_cnt] = card_deck[rnd]; 171 card_deck[rnd] = tmp; 172 173 } 174 175 rest_cnt = 0; 176} 177 178/********************************/ 179/* ドローカード関数 */ 180/********************************/ 181void draw_card(PLAYER_DATA *myhand) { 182 183 myhand->card_num[myhand->hand_cnt] = card_deck[rest_cnt]; 184 185 myhand->hand_cnt++;//手札に一枚加える 186 rest_cnt++;//デッキから1枚カードを抜く 187 188} 189 190/********************************/ 191/* 手札表示関数 */ 192/********************************/ 193void output_hand(PLAYER_DATA *myhand) 194{ 195 unsigned int myhnd_cnt; 196 int select; 197 int card; 198 int suit; 199 select = 0; 200 201 //ドローしたカード枚数分画面に表示 202 for (myhnd_cnt = 0; myhnd_cnt < myhand->hand_cnt; myhnd_cnt++) { 203 select++; 204 card = (int)(number[myhand->card_num[myhnd_cnt]]) % SAME_CARD + 1; 205 suit = (int)(number[myhand->card_num[myhnd_cnt]])/ SAME_CARD; 206 207 printf("(%d)%d", select, card); 208 switch (suit) { 209 210 case SPADE: 211 printf("S"); 212 break; 213 214 case CLUB: 215 printf("C"); 216 break; 217 218 case DIA: 219 printf("D"); 220 break; 221 222 case HEART: 223 printf("H"); 224 break; 225 226 } 227 228 } 229 230 printf("\n"); 231} 232 233/********************************/ 234/* セメタリーカード関数 */ 235/********************************/ 236void cemetery_card(PLAYER_DATA *field, PLAYER_DATA *myhand, int *input_data) 237{ 238 //セメタリーのカードを選択された手札で更新 239 field->card_num[field->hand_cnt] = myhand->card_num[*input_data - 1]; 240 field->hand_cnt++;//フィールドのカード列をずらす 241 242} 243 244/********************************/ 245/* 手札削除関数 */ 246/********************************/ 247void delete_hand(PLAYER_DATA *myhand, int *input_data) 248{ 249 unsigned int input_cnt; 250 251 //入力された選択肢のカードを起点に手札を一枚ずつずらす 252 for (input_cnt = *input_data - 1; input_cnt < myhand->hand_cnt - 1; input_cnt++) { 253 myhand->card_num[input_cnt] = myhand->card_num[input_cnt + 1]; 254 } 255 myhand->hand_cnt--;//手札を一枚減らす 256} 257 258/********************************/ 259/* 手札検索関数 */ 260/********************************/ 261int search_card(PLAYER_DATA *field, PLAYER_DATA *myhand,int *input_data) 262{ 263 unsigned int search_cnt; 264 int answer; 265 int hand_card; 266 int hand_suit; 267 int field_card; 268 int field_suit; 269 hand_card = (int)(number[myhand->card_num[*input_data - 1]]) % SAME_CARD + 1; 270 hand_suit = (int)(number[myhand->card_num[*input_data - 1]]) / SAME_CARD; 271 field_card = (int)(number[field->card_num[field->hand_cnt-1]]) % SAME_CARD + 1; 272 field_suit = (int)(number[field->card_num[field->hand_cnt-1]]) / SAME_CARD; 273 274 answer = FALSE; 275 if((hand_card == field_card) 276 ||(hand_suit == field_suit)) 277 { 278 answer = TRUE; 279 } 280 281 return answer; 282} 283 284#if 0 285/********************************/ 286/* リバースデッキ関数 */ 287/********************************/ 288void rebirth_deck(PLAYER_DATA *field, PLAYER_DATA *myhand) 289{ 290 int rnd;//ランダム値格納用変数 291 int tmp; 292 int arr_cnt;//配列カウンタ 293 srand((unsigned)time(NULL)); 294 295 for (arr_cnt=0; arr_cnt < CARD_MAX; arr_cnt--) {//デッキシャッフル 296 if ((myhand->card_num[myhand->hand_cnt] == card_deck[rest_cnt]) || 297 (field->card_num[myhand->hand_cnt] == card_deck[rest_cnt])) { 298 continue; 299 } 300 rnd = rand() % (CARD_MAX); 301 tmp = card_deck[arr_cnt]; 302 card_deck[arr_cnt] = card_deck[rnd]; 303 card_deck[rnd] = tmp; 304 305 } 306 rest_cnt = myhand->hand_cnt+1; 307} 308#endif
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/11 18:18
2016/02/12 00:30
2016/02/12 05:39