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

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

ただいまの
回答率

90.37%

  • C

    4831questions

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

新・明解c言語中級編の四章”マスターマインド"について

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 642

tkhs314

score 6

 前提・実現したいこと

コンピューターが生成した4桁の数字を当てるマスターマインドというプログラムを作ろうとしています.
例えば答えが2341の時
入力:7890    出力:それらの数字中0個の数字が含まれ、そのうち位置もあっているのは0個です
入力:1234    出力:それらの数字中4個の数字が含まれ、そのうち位置もあっているのは0個です
入力:2341    出力:正解です

というようなプログラムです。

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

しかし、どのような数字を入力しても「それらの数字中0個が含まれ、・・・」というような結果になってしまいます・・・。どこが間違っているのか、どなたか教えてください(´;ω;`)

エラーメッセージ

 該当のソースコード

ソースコード

include<stdio.h>

include<string.h>

include<time.h>

include<string.h>

include<ctype.h>

void make4digits(char x[])    /*相異なる4つの数字の並びを生成して配列xに格納*/
{
int i,j,val;

srand(time(NULL));
for(i=0;i<4;i++){
do{
val=rand()%10;
for(j=0;j<i;j++)
if(val==x[j]-'0')    break;
}while(j<i);    /*重複しない値が出るまで繰り返す*/
x[i]=val+'0';
}
}

int check(const char s[])    /*入力された文字列が四文字、数字のみ、重複なしを満たすかチェック*/
{
int i,j;
int len=strlen(s);
if(len!=4)
return 1;
for(i=0;i<4;i++){
if(!isdigit(s[i]))
return 2;
}
for(i=0;i<4;i++){
for(j=0;j<i;j++)
if(s[i]==s[j]) return 3;
}

return 0;
}

void judge(const char s[],char no[],int *hit,int *blow)    /*ヒットとフローの判定*/
{
int i,j;
*hit=*blow=0;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(s[i]==no[j])    /*数字が一致*/
if(i==j)    *(hit)++;    /*位置も一致*/
else        *(blow)++;   /*位置は不一致*/ 
}
}
}

void print_result(int snum,int spos)    /*判定結果を出力*/
{
if(spos==4)
printf("正解です!\n");
else{
printf("それらの文字中%d個の数字が含まれます\n",spos+snum);
printf("そのうち位置もあっているのは%d個です\n",spos);
}
}

int main(void)
{
int try_no=0,i;
int chk;
int hit,blow,ch;
char no[4];
const char s[10];
clock_t end,start;

printf("マスターマインドをしましょう\n");
printf("4つの数字の並びを当ててください\n");
printf("1234のように連続して数字を入力してください\n");
printf("重複のないようにしてください\n");
printf("五回以内の正解を目指しましょう\n");
printf("スペースキーで開始します\n");
make4digits(no);
printf("%s",no);    /*正しくプログラムが動いてるか検証するために答えを表示*/

while((ch=getchar())!=' ')
;
start=time(NULL);
do{
do{
printf("入力してください:");
scanf("%s",s);
chk=check(s);
switch(chk){    /*正しく入力されるまでループ*/
case 1:
printf("きちんと4文字入力してください\n");
break;
case 2:
printf("数字以外を入力しないでください\n");
break;
case 3:
printf("同じ数字を重複して入力しないでください\n");
break;
}
}while(chk!=0);

try_no++;  
printf("%d回目\n",try_no);
judge(s,no,&hit,&blow);
print_result(blow,hit);

}while(try_no<6 && hit!=4);

end=time(NULL);
if(hit!=4)
printf("残念でした.正解は%sです\n",no);
else
printf("正解です!かかった時間は%f秒です\n",difftime(end,start));

return 0;   
}

 試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • dice142

    2018/09/26 15:24

    コードはコードブロック(```)で囲んでください。わからなければコードをドラッグで選択して「<code>」ボタンでもできます。

    キャンセル

回答 4

+2

judge関数内のヒットのインクリメント部分を以下のように書いていますが、

*(hit)++;

これは以下のようにhitの指すアドレスをインクリメントしているのと同義です。

*hit;
hit++;

hitの指すをインクリメントしたいのであれば

(*hit)++


とする必要があります。

※blowも同様。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/27 15:47

    ありがとうございます!!
    ポインタ勉強不足でした...頑張ります!

    キャンセル

checkベストアンサー

+1

んでもうひとつ。

void judge(const char s[],char no[],int *hit,int *blow)    /*ヒットとフローの判定*/
{
int i,j;
*hit=*blow=0;

なんで *hit と *blow に0を代入してるんでしょうか。

ああ、これはこれでいいのか。結果を返してるのね


これだけではなんなんで

make4digits 関数

srand(time(NULL));

は、乱数生成ごとに呼ぶんじゃなくて、main関数の最初にだけ呼ぶほうがよろしい

for(j=0;j<i;j++)
if(val==x[j]-'0')    break;

最初にこれが実行されるとき、x には何が入ってるのか考えてみよう。

で、そもそもこのxを文字列として扱うなら、その後尾に'\0'文字を入れないとダメです
そうすると、このバッファは5文字分の領域が必要です
ってことで、
main関数内

char no[4];

これではダメというはなしに。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/27 15:46

    すごくわかりやすく説明して下さりありがとうございます...!!
    charとintの配列では全然違うんですね...

    キャンセル

  • 2018/09/29 18:12

    char とint の違いじゃなく、文字列として扱う場合の決まりごと、ですね
    > printf("%s",no);
    これできちんとnoの内容を出そうと思ったら、noの後尾に'\0'が必要、というはなしです

    文字列として扱わない、というのであれば、それは不要となります

    キャンセル

+1

所謂Numer0n数当てゲームですね。
自分なりに作ってみました。参考になれば幸いです。

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

#define BUFSIZE 256

int check(int*, int*);

int main(void)
{
    char buf[BUFSIZE];
    int c1[4],c2[4];
    int val;
    int i,j;
    int n,loop;
    int flag;
    srand((unsigned int)time(NULL));

    c1[0] = (char)(rand() % 10);
    i = 0;
    while(i < 4){
        flag = 1;
        val = rand() % 10;
        for(j = 0; j < i; j++){
            if(val == c1[j]){
                flag = 0;
                break;
            }
        }
        if(flag == 1){
            c1[i] = val;
            i++;
        }
    }
    printf("4桁の数字が決定しました。\n");

    flag = 0;
    loop = 0;
    while(flag == 0){
        fgets(buf,sizeof(buf),stdin);
        n = strtol(buf,NULL,10);
        for(i = 0; i < 4; i++){
            c2[3 - i] = n % 10;
            n /= 10;
        }
        flag = check(c1,c2);
        loop++;
    }
    printf("%d回で正解できました。\n",loop);
    return 0;
}

int check(int* c1, int* c2)
{
    int i,j;
    int hit = 0;
    int blow = 0;
    int flag = 0;
    for(i = 0; i < 4; i++){
        if(c1[i] == c2[i]){
            hit++;
        }
        else{
            for(j = 0; j < 4; j++){
                if(c1[i] == c2[j]){
                    blow++;
                }
            }
        }
    }
    printf("hit = %d, blow = %d\n",hit,blow);
    if(hit == 4){
        flag = 1;
    }
    return flag;
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/27 15:43

    すごいありがとうございます!!
    char型のランダムな数字の列作る時は乱数をchar型に変換してからの方が確実ですね、、、
    int型とchar型の配列の違いをイマイチ押さえられてませんでした😥

    キャンセル

0

int main(void)
{
int try_no=0,i;
int chk;
int hit,blow,ch;
char no[4];
const char s[10];

ここにも問題があります。
sがconst char[10]で定義されています。

これでは、judge関数に渡す際に
const char[]で定義されてるんだから定義時と値は変わらないはずだ。」とコンパイラが認識してしまう可能性があります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/27 15:44

    ありがとうございます!!

    キャンセル

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

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

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

  • C

    4831questions

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