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

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

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

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

Q&A

解決済

4回答

4914閲覧

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

tkhs314

総合スコア18

C

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

0グッド

1クリップ

投稿2018/09/26 06:22

編集2018/09/26 06:23

前提・実現したいこと

コンピューターが生成した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/ツールのバージョンなど)

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

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

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

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

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

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

dice142

2018/09/26 06:24

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

回答4

0

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

C

1*(hit)++;

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

C

1*hit; 2hit++;

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

C

1(*hit)++

とする必要があります。

※blowも同様。

投稿2018/09/26 06:35

dice142

総合スコア5158

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

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

tkhs314

2018/09/27 06:47

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

0

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

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <time.h> 4 5#define BUFSIZE 256 6 7int check(int*, int*); 8 9int main(void) 10{ 11 char buf[BUFSIZE]; 12 int c1[4],c2[4]; 13 int val; 14 int i,j; 15 int n,loop; 16 int flag; 17 srand((unsigned int)time(NULL)); 18 19 c1[0] = (char)(rand() % 10); 20 i = 0; 21 while(i < 4){ 22 flag = 1; 23 val = rand() % 10; 24 for(j = 0; j < i; j++){ 25 if(val == c1[j]){ 26 flag = 0; 27 break; 28 } 29 } 30 if(flag == 1){ 31 c1[i] = val; 32 i++; 33 } 34 } 35 printf("4桁の数字が決定しました。\n"); 36 37 flag = 0; 38 loop = 0; 39 while(flag == 0){ 40 fgets(buf,sizeof(buf),stdin); 41 n = strtol(buf,NULL,10); 42 for(i = 0; i < 4; i++){ 43 c2[3 - i] = n % 10; 44 n /= 10; 45 } 46 flag = check(c1,c2); 47 loop++; 48 } 49 printf("%d回で正解できました。\n",loop); 50 return 0; 51} 52 53int check(int* c1, int* c2) 54{ 55 int i,j; 56 int hit = 0; 57 int blow = 0; 58 int flag = 0; 59 for(i = 0; i < 4; i++){ 60 if(c1[i] == c2[i]){ 61 hit++; 62 } 63 else{ 64 for(j = 0; j < 4; j++){ 65 if(c1[i] == c2[j]){ 66 blow++; 67 } 68 } 69 } 70 } 71 printf("hit = %d, blow = %d\n",hit,blow); 72 if(hit == 4){ 73 flag = 1; 74 } 75 return flag; 76} 77

投稿2018/09/26 09:13

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tkhs314

2018/09/27 06:43

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

0

ベストアンサー

んでもうひとつ。

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/26 06:42

編集2018/09/26 07:00
y_waiwai

総合スコア87747

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

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

tkhs314

2018/09/27 06:46

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

2018/09/29 09:12

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

0

c

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

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

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

投稿2018/09/26 06:47

asm

総合スコア15147

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

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

tkhs314

2018/09/27 06:44

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問