ページ 11

数当てゲームをつくってます

Posted: 2012年8月15日(水) 00:41
by c言語ちゃれんじゃー
初心者です!

やりたいプログラムの流れとしては、
乱数生成(答え1~5000

数字を入力

入力された文字が10進数かどうか1~5000の範囲内かどうか判定

答えの数字と入力された数字比較してどちらが大きいか判断して表示

あっていた場合正解ですと表示

コード:

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

int main(void)
{
int ans,exp,a,count = 1;
srand((unsigned int)time(NULL));
ans = rand()%5000+1;
//printf("%d\n",ans);//テスト用
while(count <= 20)
{   
	printf("数字を入力してください:");
	scanf("%d\n",&exp);	
	if(exp <= 0)
	{
	printf("1~5000の間の数字を入力してください\n");
	}
	if(exp >= 5001)
	{
	printf("1~5000の間の数字を入力してください\n");
	}
	if(exp == ans)
	{
	printf("正解です\n");
	break;
	}
	else if(exp < ans)
	{
	
	printf("答えは%dより大きいです\n",exp);
	count++;
	}
	else
	{
	(exp > ans);
	printf("答えは%dより小さいです\n",exp);
	count++;
	}
}
printf("また挑戦してください");
return(0);
}
実行すると、

数字を入力してください:1111
1111
答えは1111より大きいです
数字を入力してください:2222
答えは1111より大きいです
数字を入力してください:2222
答えは2222より大きいです
数字を入力してください:


と入力が1つ遅れて反応する(?)
な感じです。改善法+入力された文字が数字かどうか判定する関数について教えてください><

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 00:57
by h2so5
入力が遅れて反応する現象は確認できないのですが、何かの勘違いでは?

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 07:44
by box
本題とは関係ないかもしれませんが、
c言語ちゃれんじゃー さんが書きました:

コード:

	(exp > ans);
このコードの意味は何ですか?

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 08:39
by non

コード:

scanf("%d\n",&exp);
\nを入れちゃ駄目。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 09:12
by box
適当に作り替えてください。

コード:

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

#define NG (0)
#define OK (!(NG))
#define MIN (1)
#define MAX (5000)
#define CHALLENGE (10)      // 20回だと必ず当たるので、おもしろくない
#define KETA (4)

int isNum(char *p)
{
    int i;

    for (i = 0; p[i]; i++) {
        if (!isdigit(p[i])){
            return NG;
        }
    }
    return OK;
}

int main(void)
{
    char p[KETA+2];     // +2は、'\n'と'\0'の分
    int ans, num, count = 0;

    srand((unsigned) time(NULL));
    ans = rand() % (MAX - MIN + 1) + MIN;
    // printf("%d\n", ans);

    printf("%dから%dまでの数を当てるゲーム\n", MIN, MAX);
    printf("%d回以内に当ててね\n", CHALLENGE);
    while (++count <= CHALLENGE) {
        printf("%d回目の挑戦\n", count);
        printf("%dから%dまでの数を入力:", MIN, MAX);
        fgets(p, sizeof(p), stdin), rewind(stdin);
        p[strlen(p)-1] = '\0';      // 末尾の'\n'を取り除く
        if (!isNum(p)) {
            printf("数字以外を入力しちゃダメ!\n");
        }
        else {
            num = atoi(p);
            if (!((MIN <= num) && (num <= MAX))) {
                printf("%dから%dまでの数を入力してよ!\n", MIN, MAX);
            }
            if (num == ans) {
                printf("おめでとう!正解です!\n");
                break;
            }
            printf("答えは%dよりも%sです\n", num, (ans < num) ? "小さい" : "大きい");
        }
    }
    if (count > CHALLENGE) {
        printf("答えは%dでした\n", ans);
    }
    printf("また挑戦してね\n");
    return 0;
}

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 14:38
by olivia
実行すると基本的な動作はうまくいくようになりました。
アドバイスをくれた方々ありがとうございます!
僕が今導入したいのが、入力された文字が数字であるかどうかを判定する
ことを導入したいのですが、調べたのですがいまいちわかりません。
何がわからないかというと、
1 どの関数を使えばいいかわからない(getcharとかいろいろ)
2 それぞれのどれが適しているか、またその関数の使用方法

おしえてくださいお願いします><

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 14:44
by softya(ソフト屋)
別トピックの内容が引き継がれていないようなので引用しておきます。
olivia さんが書きました:

コード:

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

int main(void)
{
int ans,exp,a,count = 1;
srand((unsigned int)time(NULL));
ans = rand()%5000+1;
//printf("%d\n",ans);//テスト用
while(count <= 20)
{   
	printf("数字を入力してください:");
	scanf("%d",&exp);	
	if(exp <= 0)
	{
	printf("1~5000の間の数字を入力してください\n");
	}
	if(exp >= 5001)
	{
	printf("1~5000の間の数字を入力してください\n");
	}
	if(exp == ans)
	{
	printf("正解です\n");
	break;
	}
	else if(exp < ans)
	{
	
	printf("答えは%dより大きいです\n",exp);
	count++;
	}
	else
	{
	(exp > ans);
	printf("答えは%dより小さいです\n",exp);
	count++;
	}
}
printf("また挑戦してください");
return(0);
}
 
実行すると基本的な動作はうまくいくようになりました。
アドバイスをくれた方々ありがとうございます!
僕が今導入したいのが、入力された文字が数字であるかどうかを判定する
ことを導入したいのですが、調べたのですがいまいちわかりません。
何がわからないかというと、
1 どの関数を使えばいいかわからない(getcharとかいろいろ)
2 それぞれのどれが適しているか、またその関数の使用方法

おしえてくださいお願いします><

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 14:55
by softya(ソフト屋)
いろいろ方法があるのでどれが正解というのは無いのですが文字・文字列として取得して数値チェックすれば数値以外が入力された時にエラーに出来ます。
getchar()で1文字づつ取得しても良いですし、gets()で文字列として取得してもよいでしょう。
数値の文字か判定するには、isdigitを使ってください。
http://www.bohyoh.com/CandCPP/C/Library/isdigit.html

インデントを意識されていないと思いますのでバグを出さないためにもインデントを意識されたほうが良いと思います。
「mixcpp/投稿前チェックリスト - PukiWiki」
http://uchan.net/w/index.php?mixcpp%2F% ... 5%B9%A5%C8

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 18:02
by olivia
回答ありがとうございます!
実際にisdigitつかって書いてみました!

コード:

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

int main(void)
{
	int ans,exp,success,count = 1;
	srand((unsigned int)time(NULL));
	ans = rand()%5000+1;
	//printf("%d\n",ans);//テスト用
while(count <= 20)
{   
	printf("数字を入力してください:");
	success = scanf("%d",&exp);	
	isdigit(success) !=0;
	if(success == 0)
	{
		printf("文字はうてません\n");
		count++;
	}
	if ( (exp <= 0) || (5001 <= exp) )
	{
		printf("1~5000の間の数字を入力してください\n");
	}
	if( exp==ans)
	{
		printf("正解です");
		break;
	}
	else if(exp<ans)
	{
		printf("答えは%dより大きいです\n",exp);
	} 
	else if(exp>ans)
	{
		printf("答えは%dより小さいです\n",exp);
	}
}
printf("また挑戦してください");
return(0);
}
実行すると、

数字を入力してください:a
文字はうてません
1~5000の間の数字を入力してください
答えは-858993460より大きいです
数字を入力してください:文字はうてません
1~5000の間の数字を入力してください
答えは-858993460より大きいです
数字を入力してください:文字はうてません

と20回ループして終了となります。
どうすればこの後に数字の入力をやり直すようにできますか?

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 18:12
by box
olivia さんが書きました:

コード:

	isdigit(success) !=0;
	if(success == 0)
私 box と申す者が先ほど投稿したコードが何か参考になるかもしれませんし、
あるいは全く参考になどならないかもしれません。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 20:49
by olivia

コード:

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

int main(void)
{
	int ans,exp,success,count = 1;
	srand((unsigned int)time(NULL));
	ans = rand()%5000+1;
	//printf("%d\n",ans);//テスト用
	printf("1~5000までの数字をあてる数当てゲームです。\n");
	printf("1~5000までの");
while(count <= 20)
{   
	printf("数字を入力してください:");
	success = scanf("%d",&exp);	
	isdigit(success) !=0;
	if(success == 0)
	{
		printf("文字はうてません\n");
		count++;
		continue;
	}
	if ( (exp <= 0) || (5001 <= exp) )
	{
		printf("1~5000の間の数字を入力してください\n");
	}
	if( exp==ans)
	{
		printf("正解です");
		break;
	}
	else if(exp<ans)
	{
		printf("答えは%dより大きいです\n",exp);
	} 
	else if(exp>ans)
	{
		printf("答えは%dより小さいです\n",exp);
	}
}
if (count >= 20)
	{
		printf("答えは%dでした。",ans);
	}
printf("また挑戦してください\n");
return(0);
}
修正後こうなりましたが、問題なのはaと入力して実行すると

1~5000までの数字をあてる数当てゲームです。
1~5000までの数字を入力してください:a
文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
数字を入力してください:文字はうてません
答えは4864でした。また挑戦してください
続行するには何かキーを押してください . . .

原因が全く分かりません・・・・

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 20:58
by box
olivia さんが書きました:

コード:

	success = scanf("%d",&exp);	
	isdigit(success) !=0;
	if(success == 0)
この3行では何をしようとしているか、日本語で説明してみてください。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 21:41
by olivia
その三行では、入力された文字が数字かどうかを判定し、数字でない場合はifの中身を実行します。

そしてその中身は文字は打てませんと表示して、scanfからやり直すようにしたかったのです

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 21:52
by box
変数 success には、どういう値が入ることを想定されていますか?

それから、先ほど抜粋した3行のうち、2行目の isdigit の行の意味が全く不明です。
何回もお手数をおかけいたしますが、その3行で何をしようとしているか、
1行ずつ説明していただけないでしょうか。

1行目:○○をしようとしている
2行目:□□をしようとしている
3行目:△△をしようとしている

のように書いてくださるとありがたいです。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 22:20
by olivia
box さんが書きました:変数 success には、どういう値が入ることを想定されていますか?

それから、先ほど抜粋した3行のうち、2行目の isdigit の行の意味が全く不明です。
何回もお手数をおかけいたしますが、その3行で何をしようとしているか、
1行ずつ説明していただけないでしょうか。

1行目:○○をしようとしている
2行目:□□をしようとしている
3行目:△△をしようとしている

のように書いてくださるとありがたいです。

コード:

   
 success = scanf("%d",&exp); //入力された文字をsuccessと置く
 isdigit(success) !=0;//数字でない場合0を返す
 if(success == 0)//0が帰った場合{}内を実行する

それで1行目では数字だった場合は%dはexpで答えの予想として普通につかわれます。
文字だと2行めで下まで行かないように入力するところからやりなおし←これを三行目以下の実行分でやりたいんです

説明下手ですいません><

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 22:30
by Loki
isdigit関数の定義を良く見てみるといいと思います。
http://www9.plala.or.jp/sgwr-t/c/sec07.html#s7-2
http://www.c-tipsref.com/reference/ctype/isdigit.html

scanf関数の定義も見て下さい。
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-3
http://www.c-tipsref.com/reference/stdio/scanf.html

引数はただのint型です。
>isdigit(success) !=0;//数字でない場合0を返す
>if(success == 0)//0が帰った場合{}内を実行する
successにisdigit(success)の戻り値は入りません。
isdigit(success) !=0の結果も入りません。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 22:37
by box
olivia さんが書きました:

コード:

 success = scanf("%d",&exp); //入力された文字をsuccessと置く
scanf関数の仕様を確認してください。「入力した文字」が戻り値になるという記述はどこにもないはずです。
私の想定では、successには0か1が入ると思います。'0'や'1'ではないですよ。念のため。
olivia さんが書きました:

コード:

 isdigit(success) !=0;//数字でない場合0を返す
このコードのどこにも、「0を返す」という意味はありません。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 22:47
by box
私が上の方で提示したコードでは、標準入力から入力した内容(数字が来ているかその他の文字が来ているかは不明)を
いったん文字列として受け取り、isNum関数を用いて、その文字列の1桁ごとに、
isdigit を使って'0'~'9'の数字であるかどうかを判断しています。
このあたりは理解できているでしょうか。

Re: 数当てゲームをつくってます

Posted: 2012年8月15日(水) 23:00
by olivia
box さんが書きました:私が上の方で提示したコードでは、標準入力から入力した内容(数字が来ているかその他の文字が来ているかは不明)を
いったん文字列として受け取り、isNum関数を用いて、その文字列の1桁ごとに、
isdigit を使って'0'~'9'の数字であるかどうかを判断しています。
このあたりは理解できているでしょうか。
そのへんは理解しました

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 05:19
by box
では、あらためておたずねします。
くだんの3行では、変数 success を使って何をしようとされているのでしょうか。

scanf() や isdigit() の仕様、if文の正しい書き方などを再確認の上、
ご説明いただけるとありがたいです。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 09:45
by olivia
box さんが書きました:では、あらためておたずねします。
くだんの3行では、変数 success を使って何をしようとされているのでしょうか。

scanf() や isdigit() の仕様、if文の正しい書き方などを再確認の上、
ご説明いただけるとありがたいです。
その三行では、
入力された文字がすうじでないばあいsuccessの値を0にし数字の場合はそれ以外の値にする
0だった場合実行分の中身(入力からやり直し)という風にしたいんです。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 09:59
by non

コード:

success = scanf("%d",&exp); //入力された文字をsuccessと置く
入力された変数はどこに格納されますか?

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 10:36
by olivia
non さんが書きました:

コード:

success = scanf("%d",&exp); //入力された文字をsuccessと置く
入力された変数はどこに格納されますか?
格納とはどういうことなのかそこらへんはあまり理解できてないです><

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 11:25
by non
標準入力(キーボード)から入力された文字は、どこの変数に入るのかと尋ねました。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 12:28
by olivia
non さんが書きました:標準入力(キーボード)から入力された文字は、どこの変数に入るのかと尋ねました。
exp(答えの予想となる)です。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 12:52
by softya(ソフト屋)
なんか苦労されているようなので、
(1) success = scanf("%d",&exp);
(2) isdigit(success) !=0;
(3) if(success == 0)

の3行で、出てくる変数に入っている内容と入る内容の説明、および動作を書いてもらったほうがよさそうです。
(1) scanfでsuccess にxxxxがはいり、expにxxxxが入る。expの型はxxxxである。
(2) successにxxxxが入っているのでisdigit関数で調べると戻り値がxxxxなので0と比較するとxxxxであるからxxxxが起こる。
(3) もしsuccessが0ならxxxxと言う意味であるから、
のxxxxを埋めてください。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 13:39
by box
scanf() の戻り値を isdigit() の引数にすること自体が意味不明かと…。

Re: 数当てゲームをつくってます

Posted: 2012年8月16日(木) 23:15
by へにっくす
c言語ちゃれんじゃーさん(=oliviaさん?)がisdigit使って書いたコードは、意味がありませんね。
scanfは入力した変数の数を返すのであって、その戻り値をisdigitに渡しても意味がありません。
だってisdigitは文字が数字かどうかを判定するのですから。
それならよっぽどこう書いた方がよいです。

コード:

while(count <= 20)
{
	success = scanf("%d", &exp);
	if ( success != 1 )
	{
		printf("数字以外はだめです");
		count++;
		fflush(stdio); // この関数を呼び出し、数字以外の入力をクリアする
		continue; // whileの次の行へいく
	}
	// ・・・略
}
scanfは想定しない文字は読み込まないのです。
読み込まないでたまったまま。
だからループの最初に戻ってscanfに行っても再度同じ入力を読もうとして
同じ結果になり、無限ループに陥るわけですね。
だから上記のように、fflush関数なり使ってクリアする必要があります。

それにしてもboxさんは意地悪だなあと思うのは私だけかしら?

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 00:17
by olivia
へにっくす さんが書きました:c言語ちゃれんじゃーさん(=oliviaさん?)がisdigit使って書いたコードは、意味がありませんね。
scanfは入力した変数の数を返すのであって、その戻り値をisdigitに渡しても意味がありません。
だってisdigitは文字が数字かどうかを判定するのですから。
それならよっぽどこう書いた方がよいです。

コード:

while(count <= 20)
{
	success = scanf("%d", &exp);
	if ( success != 1 )
	{
		printf("数字以外はだめです");
		count++;
		fflush(stdio); // この関数を呼び出し、数字以外の入力をクリアする
		continue; // whileの次の行へいく
	}
	// ・・・略
}
scanfは想定しない文字は読み込まないのです。
読み込まないでたまったまま。
だからループの最初に戻ってscanfに行っても再度同じ入力を読もうとして
同じ結果になり、無限ループに陥るわけですね。
だから上記のように、fflush関数なり使ってクリアする必要があります。

それにしてもboxさんは意地悪だなあと思うのは私だけかしら?
なるほど!ありがとうございます!

指摘通りfflush使ってみました!

直したコードがこれです↓↓

コード:

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

int main(void)
{
	int ans,exp,success,count = 1;
	srand((unsigned int)time(NULL));
	ans = rand()%5000+1;
	//printf("%d\n",ans);//テスト用
	printf("1~5000までの数字をあてる数当てゲームです。20回まで挑戦できます。\n");
	printf("1~5000までの");
while(count <= 20)
{   
	printf("数字を入力してください:");
	fflush(stdin);
	success = scanf("%d",&exp);	
	if(success != 1)
	{
		printf("文字はうてません\n");
		count++;
		continue;
	}
	if ( (exp <= 0) || (5001 <= exp) )
	{
		printf("1~5000の間の数字を入力してください\n");
	}
	if( exp==ans)
	{
		printf("%正解です!%d回で正解しました!",count);
		break;
	}
	else if(exp<ans)
	{
		printf("答えは%dより大きいです\n",exp);
		printf("残り%d回挑戦できます\n",20 - count);
		count++;
	} 
	else if(exp>ans)
	{
		printf("答えは%dより小さいです\n",exp);
		printf("残り%d回挑戦できます\n",20 - count);
		count++;
	}
}
if (count >= 20)
	{
		printf("答えは%dでした。",ans);
	}
printf("また挑戦してください。\n");
return(0);
}
一応思い通りにうごくようになりいろいろ手を加えてみました!
今まで回答してくださった皆さんありがとうございます!
ほかに無意味な点とか省略できる点とかはありますか?

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 05:06
by box
へにっくす さんが書きました:

コード:

		fflush(stdio); // この関数を呼び出し、数字以外の入力をクリアする
fflush() は、出力ストリームに関する関数のはずですので、
標準入力を fflush() するのは、ひじょうにまずいと思います。
標準出力を fflush() するのは、まだ意味があると思います。

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 05:42
by box
olivia さんが書きました: 指摘通りfflush使ってみました!

コード:

	fflush(stdin);
	success = scanf("%d",&exp);	
stdin に対して fflush() することの是非はひとまずおいておくとして…。
fflush() すればいいよ、というアドバイスをくださった方のコードは、こういう順番になっていましたか?
何のためにそうしているか、意味を正しく理解してからコードを書く方がいいと思います。

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 05:54
by へにっくす
box さんが書きました:fflush() は、出力ストリームに関する関数のはずですので、
標準入力を fflush() するのは、ひじょうにまずいと思います。
標準出力を fflush() するのは、まだ意味があると思います。
おお!そうですか
指摘ありがとうございます m(__;)m
いやータチ悪いですね私。
oliviaさんごめんなさい。

[迷信] fflush で入力バッファをクリア

とりあえず入力バッファをクリアするにはこうするしかないかも

コード:

int ignore;
do {
	ignore = getchar();
} while ( ignore != '\n' );

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 10:01
by beatle
softyaさんの No.26 の投稿は非常に勉強になると思いますので、是非解いてみることをおすすめします

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 13:13
by olivia
box さんが書きました:
へにっくす さんが書きました:

コード:

		fflush(stdio); // この関数を呼び出し、数字以外の入力をクリアする
fflush() は、出力ストリームに関する関数のはずですので、
標準入力を fflush() するのは、ひじょうにまずいと思います。
標準出力を fflush() するのは、まだ意味があると思います。
まだ意味があるとはどういう事ですか?

Re: 数当てゲームをつくってます

Posted: 2012年8月17日(金) 13:54
by box
プログラムの仕様によっては、出力ストリームを吐き出さねばならないことがあって、
そういう場合には fflush() を使うことが有効かもしれません、くらいの意味です。

今回のプログラムで fflush() を使うことが有効かどうかは、存じません。