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

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

ただいまの
回答率

87.36%

if文が実行されない

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 986

score 7

前提・実現したいこと

人狼を作成しています。
その際の二日目の夜について挙動が予測とは違うものになってしまいました。
ゲーム的には2日目の朝の処刑の時点で終了していますが、そこはあまり気にしないでください。

発生している問題・エラーメッセージ

205285行目のif文が実行されないので直したいです。
その前のほとんど同じ分を使ったif文は作動しました。
また、if文が終了した後にはprintf("人狼陣営の勝利です!")という文章は出力され、プログラムは終了しました。

該当のソースコード

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void Jinrou4();
void shuffle();

int main()
{
    srand((unsigned) time(NULL));                  /*時間によって同じ値が出ないようにする */
    int n;
    int role;
    Jinrou4();
}

void Jinrou4(int argc, char **argv)
{
    int utagai,uranai;
    int player;
    int player1=0,player2=0,player3=0,player4=0;
    int kill=0;
    printf("役職を決めます。");
    int values[] = { 1, 2, 3, 4 };
    int size = sizeof(values) / sizeof(int);
    shuffle(values, size);

    for ( int player = 0; player <= 3; player++)
    {

        printf("あなたはplayer%dです。\n",player+1);
        printf("Enterを押してください。");
        while (getchar()!='\n')
        {
            printf(" ");
        }

        if (values[player]==1)
        {
            printf("あなたは人狼です\n");
            printf("特徴:夜に一人指定してコ〇すことができます。");

        }else if(values[player]==2)
        {
            printf("あなたは市民です\n");
            printf("特徴:なし");

        }else if(values[player]==3)
        {
            printf("あなたは市民です\n");
            printf("特徴:なし");

        }else if(values[player]==4)
        {
            printf("あなたは占い師です\n");
            printf("特徴:夜に一人指名して人狼か否かを確認できます。");

        }
        printf("確認したらENTERを押してください");
        if(getchar()=='\n'){
            printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
        }

    }

    for (int count = 0; count<20; count++)
    {
        printf("\n\n");
    }
    printf("それではゲームを開始します\n初夜の殺害はできません\n");
    printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 一日目 夜 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");

    printf("それではplayer1から操作を行います。\n");
    for ( player = 0; player <= 3; player++)
    {
        printf("player%dに渡してください。",player+1);
        printf("あなたがplayer%dならENTERを押してください。\n",player+1);
        while (getchar()!='\n')
        {
            printf(" ");
        }
        if (values[player]==1)
        {
            printf("あなたは人狼です\n");
            printf("怪しいと思うplayerの番号を入力してください\n");
            scanf("%d-1",&utagai);
            if (utagai==0)
            {
                player1++;
            }else if (utagai==1)
            {
                player2++;
            }else if (utagai==2)
            {
                player3++;
            }else if (utagai==3)
            {
                player4++;
            }
            }else if(values[player]==2)
            {
            printf("あなたは市民です\n");
            printf("怪しいと思うplayerの番号を入力してください\n");
            scanf("%d",&utagai);
            if (utagai==1)
            {
                player1++;
            }else if (utagai==2)
            {
                player2++;
            }else if (utagai==3)
            {
                player3++;
            }else if (utagai==4)
            {
                player4++;
            }
            }else if(values[player]==3)
            {
            printf("あなたは市民です\n");
            printf("怪しいと思うplayerの番号を入力してください");
            scanf("%d",&utagai);
            if (utagai==1)
            {
                player1++;
            }else if (utagai==2)
            {
                player2++;
            }else if (utagai==3)
            {
                player3++;
            }else if (utagai==4)
            {
                player4++;
            }
            }else if(values[player]==4)
            {
                printf("あなたは占い師です\n");
                printf("占うplayerの番号を入力してください。\n");
                scanf("%d",&uranai);
            if (values[uranai-1]==1)
            {
                printf("player%dは人狼です\n",uranai);
                printf("特徴:夜に一人指定してコ〇すことができます。\n");

            }else if(values[uranai-1]==2)
            {   
                printf("player%dは市民です\n",uranai);
                printf("特徴:なし\n");

            }else if(values[uranai-1]==3)
            {
                printf("player%dは市民です\n",uranai);
                printf("特徴:なし\n");

            }if(getchar()=='\n'){
                printf(" ");
            }
            }
            printf("確認したらENTERを押してください\n");
            if(getchar()=='\n'){
                printf(" \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
            }

    }

    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 二日目 朝 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
    printf("夜が明け朝になりました\n");
    if (player1<2&&player2<2&&player3<2&&player4<2)
    {
        printf("怪しまれている人物はいません。\n");
    }else if (player1>=2)
    {
        printf("怪しまれているのはplayer1です。\n");
    }else if (player2>=2)
    {
        printf("怪しまれているのはplayer2です。\n");
    }else if (player3>=2)
    {
        printf("怪しまれているのはplayer3です。\n");
    }
    printf("それでは話しあって本日処刑する人を決めてください\n話し合いが終わったらENTERを押してください\n");
    while (getchar()!='\n')
    {
        printf(" ");
    }
    printf("処刑するplayerの番号を入力してください。\n");
    scanf("%d",&player);
    if (values[player-1]==1)
    {
        printf("市民陣営の勝利です!\nおめでとうございます!\n");
        return ;
    }else
    {
        printf("player%dが処刑されました…\n",player);
        values[player-1]=0;
    }

    printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 二日目 夜 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
    printf("恐ろしい夜がやってきました\n");
    printf("夜の行動を行います\n");

    printf("それではplayer1から操作を行います。\n");
    for ( player = 0; player <= 3; player++)
    {
        printf("player%dに渡してください。",player+1);
        printf("あなたがplayer%dならENTERを押してください。\n",player+1);
        while (getchar()!='\n')
        {
            printf(" ");
        }

        if (values[player]==0)                       /*ここから下のif文が実行されません*/
        {
            printf("役職:1->人狼 2,3->市民 4->占い師\n\nplayer1の役職は%d\nplayer2の役職は%d\nplayer3の役職は%d\nplayer4の役職は%d\nでした。\n",values[0],values[1],values[2],values[3]);
        }else if (values[player]==1)
        {
            printf("あなたは人狼です\n");
            printf("殺害するplayerの番号を入力してください\n");
            scanf("%d",&kill);
            printf("殺害するのはplayer%dです。\nENTERを押してください。",kill);
            if(getchar()=='\n'){
                printf(" ");
            }
        }else if(values[player]==2)
        {
            printf("あなたは市民です\n");
            printf("怪しいと思うplayerの番号を入力してください\n");
            scanf("%d",&utagai);
            if (utagai==1)
            {
                player1++;
            }else if (utagai==2)
            {
                player2++;
            }else if (utagai==3)
            {
                player3++;
            }else if (utagai==4)
            {
                player4++;
            }
        }else if(values[player]==3)
        {
            printf("あなたは市民です\n");
            printf("怪しいと思うplayerの番号を入力してください");
            scanf("%d",&utagai);
            if (utagai==1)
            {
                player1++;
            }else if (utagai==2)
            {
                player2++;
            }else if (utagai==3)
            {
                player3++;
            }else if (utagai==4)
            {
                player4++;
            }
        }else if(values[player]==4)
        {
                printf("あなたは占い師です\n");
                printf("占うplayerの番号を入力してください。\n");
                scanf("%d",&uranai);
            if (values[uranai-1]==1)
            {
                printf("player%dは人狼です\n",uranai);
                printf("特徴:夜に一人指定してコ〇すことができます。\n");

            }else if(values[uranai-1]==2)
            {   
                printf("player%dは市民です\n",uranai);
                printf("特徴:なし\n");

            }else if(values[uranai-1]==3)
            {
                printf("player%dは市民です\n",uranai);
                printf("特徴:なし\n");

            }else if(getchar()=='\n'){
                printf(" ");
            }                                                       /*ここまでのif文です*/
        }
            printf("確認したらENTERを押してください\n");
            if(getchar()=='\n'){
                printf(" \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
            }

    }

     printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 三日目 朝 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
        printf("昨晩の犠牲者はplayer%dです。\n",kill);
        printf("人狼陣営の勝利です!\nおめでとうございます!\n");
        return ;
}

void shuffle(int array[], int size)
{   
    int i = size;
    while (i > 1) {
        int j = rand() % i;
        i--;
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

試したこと

似た内容の初夜の行動で使ったif文が実行されたのでそれをコピペしてみましたが、実行されませんでした。

補足情報(FW/ツールのバージョンなど)

vscodeで書き、コマンドプロンプトで実行しています。
当方知識がないので他におかしな点があったら指摘していただいて構いません。
2回目の質問ですので至らない点はご容赦ください。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mather

    2019/07/29 21:51

    加えてインデントがごちゃごちゃに混ざっているのでミスリーティングが多いです。
    コードフォーマッターなどを使って修正したほうがミスに気づきやすいですよ。

    キャンセル

  • shimi43

    2019/07/29 21:53

    了解しました。

    キャンセル

  • jimbe

    2019/07/31 02:21

    いまさらですが, ご提示のコードはコンパイル出来ませんので「if文が実行されない」の原因はコードを見る限りでは見つかりません.
    if文が実行されなかった時のコードに修正して頂けますか.

    キャンセル

回答 3

+1

やばいところを示しておきます

void Jinrou4();
void shuffle();

実際の関数のプロトタイプ宣言とはなってません。
引数の型を明示してください。
また、Jinrou4の実行の際に引数を無視してるのもやばいです。
修正しましょう

そのうえで、動作がおかしい所があればまた言ってきましょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

以下のように else を付けてデバッグしてみてはいかがでしょうか。

} else {
  printf("DEBUG: player = %d\n", player);
  printf("DEBUG: values[player] = %d\n", values[player]);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

205~285行目のif文が実行されないので直したい

matherさんの回答の通り、いわゆる printf()デバッグを、質問者自身がやってみるべきだと思います。

            }else if(getchar()=='\n'){
                printf(" ");
            }                /*ここまでのif文です*/


ここにelse節が無いので、matherさんのようにしてみるのが先決でしょう。
printf()デバッグは

  • プログラムがどこを通るのか
  • その時の変数値はいくつか

を確認するものです。デバッガを使うまでもなく、工夫次第で簡単に動作状況を調べられます。

他におかしな点があったら指摘していただいて構いません

・player1〜player4という4つの変数を、配列にしたほうがよい

これらは疑いをかけられた回数、各人の疑惑値を表すようです。
何番目の登場人物かを表す player という単純変数もあり、名前がかぶらないように、変数名を変えて、例えばこうしたらどうでしょうか。

    int suspicion[4] = { 0, 0, 0, 0 };   // 各人の疑惑値

配列にすることで、次のような箇所は、

            printf("あなたは人狼です\n");
            printf("怪しいと思うplayerの番号を入力してください\n");
            scanf("%d-1",&utagai);
            if (utagai==0)
            {
                player1++;
            }else if (utagai==1)
            {
                player2++;
                ....


if 〜 else if 〜が不要になり、わずか一行で済みます。

            printf("あなたは人狼です\n");
            printf("怪しいと思うplayerの番号を入力してください\n");
            scanf("%d", &utagai);
            suspicion[utagai]++;   // 疑われた人の疑惑値を +1 する


名前がかぶらないようにするのは、エディタ等で、特定の変数を探す・変数名を一括変換する、といった作業をがしやすくするためです。

変数名や関数名は、何のためにあるのか、何をするものか、という意味が伝わりやすい名前にするよう、心がけてください(私にとっても難しいですけどね)。
ここで配列にした場合、その値が何を意味するか(例:疑惑値)、配列の添え字(インデックス)は何を意味するか(例:プレーヤーを特定する)を整理してください。配列の添え字は、Cでは0から始まります。ユーザに0〜3を入力させるか、1〜4を入力させるか、も大事です。
データ設計が大事なことを忘れないように。

・values[player]の値は2でも3でも市民です。

        }else if(values[player]==2)
        {
            printf("あなたは市民です\n");
            printf("特徴:なし");
        }else if(values[player]==3)
        {
            printf("あなたは市民です\n");
            printf("特徴:なし");


まずこうしましょう。

        } else if (values[player] == 2 || values[player] == 3) {
            printf("あなたは市民です\n");
            printf("特徴:なし");
        } else ....


ここに限らず if 〜 else if 〜 else を switch 〜 case に置き換えられる箇所がたくさんあります。こんな風に

        switch (values[player]) {
        case 1:
            printf("あなたは人狼です\n");
            printf("特徴:夜に一人指定してコ〇すことができます。");
            break;
        case 2:
        case 3:
            printf("あなたは市民です\n");
            printf("特徴:なし");
            break;
        case 4:
            printf("あなたは占い師です\n");
            printf("特徴:夜に一人指名して人狼か否かを確認できます。");
            break;
        }


中カッコ { } の数がぐっと減ってすっきりしますし、if 文の条件に何度も出てくる  values[player] == ?  がひとつだけになり、分岐の意図が明確になります。

・これら case ラベルの 1, 2, 3, 4 は、人狼、市民、占い師を意味する値です。単なる整数値ではないので、マジックナンバーのままにするのではなく、例えば

#define EXECUTED 0   // 処刑された
#define JINROU   1   // 人狼
#define CITIZEN1 2   // 市民1
#define CITIZEN2 3   // 市民2
#define DIVINER  4   // 占い師
  または
enum { EXECUTED, JINROU, CITIZEN1, CITIZEN2, DIVINER };


のようにした方が良くて、上の case ラベルはこんな風に書けます。

        case JINROU:
        case CITIZEN1:
        case CITIZEN2:
        case DIVINER:

・ここで、CITIZEN1 と CITIZEN2 の区別が要るのかどうか。同じ値でも良いのでは?それは私には判断できませんが、区別が要らない可能性があります。その場合、配列名 values(値)は他にも使いたくなりそうなので roles(役)に変えた上で、こんな風にするでしょう。

    enum { EXECUTED, JINROU, CITIZEN, DIVINER };
    int roles[4] = { JINROU, CITIZEN, CITIZEN, DIVINER };

・player変数を用いた2種類の for 文には違いがあります。

    int player;                                  // (A)

    for ( player = 0; player <= 3; player++)     // (B)
    for ( int player = 0; player <= 3; player++) // (C)


(B) の for 文は (A)で定義した player 変数を使いますが、
(C) の player 変数は (A) の player 変数ではありません。お分かりですか?
「if 文が実行されない」問題には関係ないと思いますが、不注意にこういうことをすると、思わぬバグに遭う危険性があります。

・player4 >= 2 の場合、何も表示しませんが、良いのでしょうか?

    if (player1<2&&player2<2&&player3<2&&player4<2)
    {
        printf("怪しまれている人物はいません。\n");
    }else if (player1>=2)
    {
        printf("怪しまれているのはplayer1です。\n");
    }else if (player2>=2)
    {
        printf("怪しまれているのはplayer2です。\n");
    }else if (player3>=2)
    {
        printf("怪しまれているのはplayer3です。\n");
    }

・jinrou4() 関数は空行を含めて 280 行もあります。このあと、3日め、4日目と、ただダラダラと書き足しますか?
普通、関数は数十行程度に収めたほうが良いと言われます。まとまった処理を関数化して、見通しを良くすることは今後絶対に必要です。少しずつ関数化することをお勧めします。例えば

  • 初期化、初日、2日目…と場面が変わる毎に、それぞれを関数化・一般化するとか
  • 画面を更新する処理を関数化するとか
  • エンターキーを入力する処理を関数化するとか
  • 疑われている人の情報を表示する部分を関数化するとか etc.

・エンターキー入力に関して、

        while (getchar()!='\n')    // (A)タイプ
        {
            printf(" ");
        }

        if(getchar()=='\n'){       // (B)タイプ
            printf("\n\n...");
        }


(A)タイプと(B)タイプがコード中に混在しています。心配なのは、(B) だとエンターキーでなくても処理が先に進んでしまうことです。関数化する際はついでに、こういう箇所でどうすべきか整理すると良いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る