質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

232閲覧

C言語で上手く実行してくれないのですが…

Cat_N_Memory

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/10/22 05:45

編集2017/10/22 05:45

###前提・実現したいこと
C言語で自分の腕試しに簡易的なカードゲームを作ろうとしています。

###発生している問題・エラーメッセージ
コンパイルは問題なく出来ましたが、肝心の起動が上手くいきません。
タスクマネージャー上では「起動中」なのですが、1~2分待っても何も反応がありません。

###該当のソースコード

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <time.h> 4 5#define Cardtype 2 6#define Intype 4 7#define CardMax 3 8 9typedef struct status{ 10 int hp; 11 int cards[2][4]; 12 int have[5]; 13} Sta; 14 15/* カードの名前を判定する */ 16void Namejudge(const int id){ 17 switch(id){ 18 case 10 : printf("無の剣"); break; 19 case 11 : printf("緑の剣"); break; 20 case 12 : printf("赤の剣"); break; 21 case 13 : printf("青の剣"); break; 22 case 20 : printf("無の盾"); break; 23 case 21 : printf("緑の盾"); break; 24 case 22 : printf("赤の盾"); break; 25 case 23 : printf("青の盾"); break; 26 } 27} 28 29/* カードの説明文を判定する */ 30void Descjudge(const int id){ 31 char desc[256]; 32 33 switch(id){ 34 case 10 : printf("相手に無属性威力4の攻撃。"); break; 35 case 11 : printf("相手に木属性威力4の攻撃。"); break; 36 case 12 : printf("相手に火属性威力4の攻撃。"); break; 37 case 13 : printf("相手に水属性威力4の攻撃。"); break; 38 case 20 : printf("全属性の攻撃を半減させる。"); break; 39 case 21 : printf("水属性の攻撃を無効化、木属性の攻撃を半減させる。"); break; 40 case 22 : printf("木属性の攻撃を無効化、火属性の攻撃を半減させる。"); break; 41 case 23 : printf("火属性の攻撃を無効化、水属性の攻撃を半減させる。"); break; 42 } 43} 44 45/* 初期化処理 */ 46void Initia(Sta *std){ 47 int r, n, m; 48 int f; 49 50 srand(time(NULL)); 51 52 std->hp = 100; 53 54 for(f = 0; f < 5; f++){ 55 do{ 56 n = rand() % Cardtype + 1; 57 m = rand() % Intype; 58 59 if(std->cards[n - 1][m] == CardMax){ 60 std->have[f] = n * 10 + m; 61 std->cards[n - 1][m] += 1; 62 } 63 } while(std->have[f] < 10); 64 } 65 66} 67 68/* 選択処理 */ 69int choosecard(Sta std, Sta ene){ 70 int f, choice; 71 72 printf("自分残りHP:%d", std.hp); 73 printf("相手残りHP:%d", ene.hp); 74 75 printf("手持ちカード\n"); 76 77 for(f = 0; f < 5; f++){ 78 printf("%d番:", f + 1); 79 Namejudge(std.have[f]); 80 printf(" - "); 81 Descjudge(std.have[f]); 82 } 83 84 printf("カードを選択してください(1~5):"); 85 86 do{ 87 scanf("%d", &choice); 88 if(choice < 1 || choice > 5){ 89 printf("\a1~5で選択してください。:"); 90 } 91 } while(choice < 1 || choice > 5); 92 93 return choice - 1; 94} 95 96/* ダメージ計算、演算処理、文章表示 */ 97void Fight(int p, int e, Sta *pla, Sta *ene){ 98 int pd, ed; 99 int obju; 100 101 if(pla->have[p] / 10 == 1 && ene->have[e] / 10 == 1){ 102 /* どちらも攻撃札の場合、単純にダメージを付与 */ 103 pd = 4; 104 ed = 4; 105 printf("互いの攻撃がぶつかり合った!\n"); 106 }else if(pla->have[p] / 10 == 1 && ene->have[e] / 10 == 2){ 107 /* こちらが攻撃札の場合、ダメージ変動するかの判定 */ 108 /* 無属性盾なら半減 */ 109 if(ene->have[e] % 10 == 0) pd = 2; 110 else{ 111 obju = ((pla->have[p] % 10) - (ene->have[e] % 10) + 3) % 3; 112 /* 1なら貫通、2なら無効、0なら半減 */ 113 switch(obju){ 114 case 0 : pd = 2; printf("こちらの攻撃は相手の盾で弱められてしまった!\n"); break; 115 case 1 : pd = 4; printf("こちらの攻撃は相手の盾を貫通した!\n"); break; 116 case 2 : pd = 0; printf("こちらの攻撃は相手の盾に阻まれてしまった!\n"); break; 117 } 118 } 119 ed = 0; 120 }else if(pla->have[p] / 10 == 2 && ene->have[e] / 10 == 1){ 121 /* 今度は逆、やることもほぼ変わらない */ 122 /* 無属性盾なら半減 */ 123 if(pla->have[p] % 10 == 0) ed = 2; 124 else{ 125 obju = ((pla->have[p] % 10) - (ene->have[e] % 10) + 3) % 3; 126 /* 1なら無効、2なら貫通、0なら半減 */ 127 switch(obju){ 128 case 0 : ed = 2; printf("こちらの盾で相手の攻撃を弱めた!\n"); break; 129 case 1 : ed = 0; printf("こちらの盾は相手の攻撃を阻んだ!\n"); break; 130 case 2 : ed = 4; printf("こちらの盾は相手の攻撃で破れてしまった!\n"); break; 131 } 132 } 133 pd = 0; 134 }else{ 135 /* どちらも防御札なので互いにダメージなし */ 136 pd = 0; 137 ed = 0; 138 printf("互いに守りあっている。\n"); 139 } 140 141 pla->hp -= ed; 142 ene->hp -= pd; 143} 144 145int main(void){ 146 Sta Pla, Ene; 147 int turn, plac, enec; 148 149 srand(time(NULL)); 150 151 Initia(&Pla); 152 Initia(&Ene); 153 154 turn = 0; 155 156 puts("========================"); 157 puts(" Cards Battle "); 158 puts("========================"); 159 160 do{ 161 printf("---%dターン目---\n", ++turn); 162 plac = choosecard(Pla, Ene); 163 enec = rand() % 5; 164 printf("カードオープン!\n"); 165 166 printf("あなたは「"); 167 Namejudge(Pla.have[plac]); 168 printf("」を召喚!\n"); 169 170 printf("あいては「"); 171 Namejudge(Ene.have[enec]); 172 printf("」を召喚!\n"); 173 174 Fight(plac, enec, &Pla, &Ene); 175 176 if(Pla.hp <= 0 || Ene.hp <= 0) break; 177 } while(1); 178 179 return 0; 180}

###試したこと
どこかエラーにひっからないレベルで間違えているのかと思いましたが、まだ初めて間もないためよくわからず戸惑っています。

###補足情報(言語/FW/ツール等のバージョンなど)
コンパイラはMinGWを使っています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Initia関数内のこの部分が非常に怪しいです。

C

1do{ 2 n = rand() % Cardtype + 1; 3 m = rand() % Intype;
if(std->cards[n - 1][m] == CardMax){ std->have[f] = n * 10 + m; std->cards[n - 1][m] += 1; }

} while(std->have[f] < 10);

std->cardsの値が初期化される前に参照されています。

ですので、if文内部が実行される保証はありません。
また、ループ内が実行されなければ、終了条件を満たす保証もありません。

ループに突入する前に適切に構造体変数を初期化する必要があるでしょう。


私ならカード周りをこういう風に実装するかな、とちょっと書いてみました。

card.h

C

1#ifndef INCLUDED_CARD 2#define INCLUDED_CARD 3 4typedef struct { 5 int id_; 6 char name_[10]; 7 char caption_[128]; 8} Card; 9 10int get_type_num_of_cards(void); 11Card *get_random_card(Card *); 12 13int get_card_id(const Card *); 14const char *get_card_name(const Card *); 15const char *get_card_caption(const Card *); 16 17int print_card_info(const Card *); 18 19#endif

card.c

C

1#include "card.h" 2#include <stdio.h> 3#include <stdlib.h> 4 5static Card cards[] = { 6 {10, "無の剣", "相手に無属性威力4の攻撃。"}, 7 {11, "緑の剣", "相手に木属性威力4の攻撃。"}, 8 {12, "赤の剣", "相手に火属性威力4の攻撃。"}, 9 {13, "青の剣", "相手に水属性威力4の攻撃。"}, 10 {20, "無の盾", "全属性の攻撃を半減させる。"}, 11 {21, "緑の盾", "水属性の攻撃を無効化、木属性の攻撃を半減させる。"}, 12 {22, "赤の盾", "木属性の攻撃を無効化、火属性の攻撃を半減させる。"}, 13 {23, "青の盾", "火属性の攻撃を無効化、水属性の攻撃を半減させる。"} 14}; 15 16int get_type_num_of_cards(void) { 17 return sizeof(cards) / sizeof(cards[0]); 18} 19Card *get_random_card(Card *card) { 20 *card = cards[ 21 rand() % get_type_num_of_cards() 22 ]; 23 return card; 24} 25 26int get_card_id(const Card *card) { 27 return card->id_; 28} 29const char *get_card_name(const Card *card) { 30 return card->name_; 31} 32const char *get_card_caption(const Card *card) { 33 return card->caption_; 34} 35 36int print_card_info(const Card *card) { 37 return printf( 38 "id: %d, %s\n%s\n", 39 get_card_id(card), 40 get_card_name(card), 41 get_card_caption(card) 42 ); 43}

割と手抜きです。実際には外部ファイルにカードの情報を置いた方がよいでしょう。
あんまり参考にならないかもしれませんが、こういう書き方もあるよ、と言うことで。

投稿2017/10/22 06:03

編集2017/10/22 13:12
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Cat_N_Memory

2017/10/22 06:19

回答ありがとうございます! 僕は本来そこのループで「選択されたカードが既に使用回数の上限に達しているか」という判断をしたかったのですが、確かにこれを見る限り「上限に達しないと処理しない」という風になっていました… 気付いていただきありがとうございました!
takuan_no_hito

2017/10/22 06:26 編集

解決されたようで、お疲れ様です。 こちらも素人なのですが、気になったので、いくつか。 その部分は初期化処理ですので、 for (f = 0; f < 5; f++) { n = rand() % Cardtype + 1; m = rand() % Intype; std->have[f] = n * 10 + m; } だけでも十分な気がします。 また、カードの種類毎に使用回数を決めているならば、cards[2][4]で間違いないと思いますが、自身が持っている5種類のカードに対して使用回数制限があるならば、used[5]でも十分な気がします。 (追記)同じカードを2つ持ってても意味ない場合は、既にそのカードが取得されていないか確かめる必要がありそうですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問