プロが教える店舗&オフィスのセキュリティ対策術

C言語を独学し始めた高校一年男子です。
「猫でもわかる C言語プログラミング」という本で勉強しています。
その本のポインタなどの難しいところを除いて
一通り読んで1~100までの数を当てる数当てゲームを作ってみました!
これまでは、本に書かれていることを写してやっていたので、自分で組むのは初めてです。
これからは、もっと高度なプログラムやゲームを作っていきたいと思っています。
それを踏まえて、今後どのようなことを気をつけて書いていけばいいかなどの
アドバイスをコードを見てしてもらいたいのですが、
だれか、お願いできないでしょうか?
これが、そのコードです↓


//<if,goto,rand関数を使った数当てゲーム>//


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
printf("いまから数当てゲームをします\n");
R:
printf("0~100のうちどれが答えなのか当ててください\n");
int Q,A,Y,i;
srand((unsigned)time(NULL));
Q=rand()%100+1;

for(i=1; i<6; i++)

{printf("あと%d回で当ててください!\n",6-i);

scanf("%d",&A);

if(Q<A){printf("もっと小さい数です\n");
}

else if(Q>A){printf("もっと大きい数です\n");
}

else{printf("正解です!!(^O^)/\nもう一回やりますか??\nはい→1\nいいえ→それ以外の数字\n選択してください\n");
scanf("%d",&Y);
if(1==Y){goto R;}
if(1!=Y){}break;}}
printf("\n「「「終了します」」」\n");

return 0;
}



長くなりましたが、アドバイスお願いします m(._.)m

A 回答 (8件)

他の突っ込みどころも挙げておこう.



・変数名 (や関数名など) に気を付ける: 変数 (など) の名前が「その変数 (など) の意味」を十分あらわしているか, 考えましたか? 例えば, 「Y」という名前にあなたはどのような意味を込めたのですか?
・比較をするときに 1==Y とか 1!=Y とかの順序はやめた方がいい: 「Y==1 なんて書くと Y=1 と間違えちゃうかもしれないので 1==Y と書きましょう」としているものもあるけど, しょせん定数との比較でしか意味をなさないし, はっきり言って不自然. いまどきの処理系ならそのくらい警告で出せるので, 処理系に任せた方がいい.
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
コードを書くのに夢中で
特に変数名などは気にしていませんでした。
確かに、後から見直した時に、
変数名の「i」の所を回答数の「K」や、
「Y」の所をリターンの「R」
「goto」の戻る先をリターンポイントの「RP」
などにすると分かりやすいという事に気付きました!!

Tacosan様のご指摘通り本を見直してみたら
「1==Y」ではなく「Y==1」となっていたので今後気をつけたいと思います。

最後に、他の皆様にも、お願いしているのですが、
今後もコードを書いたらアドバイスがもらいたいので、
もし時間があったらよろしくお願いします。

お礼日時:2012/12/07 23:17

プログラム中に"6"という定数が2回出てきますね。


これは同じ意味を持つ数値、多分最大試行回数なので、
#define MAX_TRIAL_NUMBER (6)
としてプログラムの先頭、またはヘッダファイルに定義しておいて、コード中ではこのマクロで記述しておくのがいいでしょう。
最大試行回数を別の数字にする時、変更する場所が一つになります。
また、これはプログラムの可読性(読みやすさ、理解しやすさ)を上げることになります。
(というより、こっちの方が主目的)
コードの中で6とか100等の数値があると、その数値の意味が分からないでしょ。
だからコード中に直接書いてある数値のことを「マジックナンバー」って言って、よくないことの一つになっています。
コード中に直接数値を書かないように気を付けましょう。
/* でも一回しか使わないプログラムにはいっぱい使っちゃうんだけどね */
    • good
    • 0
この回答へのお礼

参考にしていた本に「#define」と言うのは
載っていなかったと思うので、
maru_yoshi_様のおかげでとても便利なものを覚えることが出来ました!!

次書くときは、今回教えていただいた事をいかして
マジックナンバーをなくしたいと思います!

アドバイスありがとうございました。

お礼日時:2012/12/12 00:24

>本を見直してみたら


>「1==Y」ではなく「Y==1」となっていたので今後気をつけたいと思います。

前者だと「1がYに等しい」、後者だと「Yが1に等しい」どちらが素直に読めますか。って事ですよ。
    • good
    • 0
この回答へのお礼

「Y=1」のように、Yに1を入れるという風に考えると
「Y==1」や「Y!=1」といったように、Yは、1と等しい、Yは、1と等しくない
と言ったようにした方がスッキリ読めますね!
それに、コードを書いたときに「左に変数」と統一しておいた方が
分かりやすいし、見やすいと思いました!!

wormhole様のおかげで本に書かれていた内容が理解できたような気がします!!
アドバイス、ありがとうございました。

お礼日時:2012/12/09 00:26

いやいや, 「自分で見てわかる」ことを考えちゃダメだって. 「他人が見てわかる」かどうかを考えなきゃ.



例えば, 他の人が見たときに「K は『回答数』なんだ」ってわかってくれると思いますか? 「K」と「kaitousuu」の, どちらがより「回答数」と思ってもらいやすいでしょうか?

あるいは, 「リターンの R」と言ってますが, 他の人に「『リターン』ってなんだと思う?」と聞いたらあなたが思っているものと同じものが確実に返ってくると思いますか?
    • good
    • 0
この回答へのお礼

Tacosan様、二度も分かりやすい説明ありがとうございます。


確かに、「K」と書かれで「回答数」だと分かって貰うには
隣に、コメントでも、書いておかない限り難しいですね。

それに僕は「スタートに戻る」という意味でリターンと言う物を
使おうと思ったのですが、今、見返してみると
とても分かりにくかったです。

今後、他の人と共同でプログラムを組んだり、
今回のようにアドバイスをもらう時などのために
どんなプログラムか知らない人が見ても、
すぐ分かるような分かりやすいプログラムを
書くことが大切なのですね!

お礼日時:2012/12/09 00:20

rand()%100+1; で生成されるのは,0~100ではなく,1~100です。



6回で正解が出なかったときも「もう一回やりますか?」とうながした方が利用者にとって遊びやすいと思います。

ということで私もコードに手を入れてみました,ご参考までに。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int q, a, i, y;
srand((unsigned)time(NULL));
printf("いまから数当てゲームをします\n");
while (1) {
printf("0~100のうちどれが答えなのか当ててください\n");
q =rand() % 101;
a = q - 1;
for (i = 6; i > 0 && q != a; i--) {
printf("あと%d回で当ててください!\n", i);
scanf("%d", &a);
if (q < a) {
printf("もっと小さい数です\n");
}
if (q > a) {
printf("もっと大きい数です\n");
}
}
if (q == a) {
printf("正解です!!(^O^)/\n");
} else {
printf("正解は%dでした\n", q);
}
printf("もう一回やりますか??\n");
printf("はい→1\nいいえ→それ以外の数字\n");
printf("選択してください\n");
scanf("%d", &y);
if (y != 1) {
break;
}
}
printf("\n「「「終了します」」」\n");
return 0;
}
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
jjon-com様のコードでやらせていただきました!
ゲームをやっていって最後に答えが出た方がすっきりして
プレイヤー側からしてみると親切ですね!!

次、作る時はプレイヤー側から見てどんな工夫があったらうれしいか
いろいろ考えて試行錯誤していきたいと思います

他の皆様にも、お願いしているのですが、
今後もコードを書いたらアドバイスがもらいたいので、
もし時間があったらよろしくお願いします。

お礼日時:2012/12/07 23:03

GOTOについてや、動作速度についてはkmeeさん、tsunjiさんが回答して下さっているので、インデントの細かい点についてだけ。



基本的に{の数と、}の数は一致させましょう。
また言語や規約にも寄りますが、C言語の一般的なインデントの書き方としては
if(hoge)
{
[TAB] // ToDo
}
else
{
[TAB] //ToDo
}
のように{や}の前後は改行を行い独立させ、また{}内の処理はタブで字下げする方法が一般的だと思います。
※異なる記述方法もあります。
また、if文やfor文の中に記述する操作が1行の場合は{}で囲まなくても処理が行われます。
しかし、{}で囲まない記述方法は分かりづらく、バグが混入する原因となりやすいので一般的には避けられます。

上記の記述法に沿って元ソースを改変しましたので参考にどうぞ。
(OKWave上だとタブの字下げが反映されないので、下記のサイトで確認して下さい。)
http://codepad.org/eJzf0ZUj

参考URL:http://ja.wikipedia.org/wiki/%E5%AD%97%E4%B8%8B% …
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。

僕の書いた物と比べると字下げしてある物の方が
全然見やすいと思い、改めて見やすい物を書く重要性が分かりました!!

今後も、コードを書いたらアドバイスがもらいたいので、
kmee様たちと同様にもし時間があったらよろしくお願いします。

お礼日時:2012/12/07 22:52

#1さんと同じで、gotoを使わない方が、C言語としてすっきりします。


私のならwhile(1){}かdo..whileでループする方法にしますけどね。

ローカル変数のint Q,A,Y,i;は、関数の入り口にまとめておいた方がいいね。

printf("0~100のうちどれが答えなのか当ててください\n"); は1~100だよね。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。

tsunji様のご指摘通り「goto」は、使わずに「while」にして組み立てて
変数は、関数の入口にしたりなどしてミスを無くし見やすい物を書けるように心がけたいです!!

kmee様と同様に、またコードを書いたらアドバイスがもらいたいので、
もし時間があったらよろしくお願いします。

お礼日時:2012/12/07 22:47

> srand((unsigned)time(NULL))



srandが毎回呼ばれます。
「乱数」は実際には計算で乱数っぽい数値を出す「疑似乱数」を使っていて、srandで設定する種が同じなら、そのあとにつづくrandはまったく同じ順番で出てきます。
種にtimeを使っているので、一度正解なら、最大1秒は同じ数値が正解です。


> if(1==Y){goto R;}

便利なgotoですが、基本は「gotoは使わない」というのが、昨今のプログラミングの原則です。

> if(1!=Y){}break;}}

これは
if(1!=Y){
} // if(1!=Y) に対応する
break;
} // else {printf("正解 ... に対応する
} // for(i=1; i<6; i++) に対応する

となります。
if(1!=Y) が成立しても、何もしません。そのため、なにも書いてないのと等価です。
break;は ifに関係なく実行されます。 直前で if ( 1 == Y)があるので、実質 1 != Y のときだけbreakが実行されますが。

間違いではありませんが、実際のプログラミングでは、{と}の対応がわかるように字下げしましょう。
} を1行で複数並べるのは、Cではあまり見掛けない流儀です。
    • good
    • 0
この回答へのお礼

アドバイスありがとうございます。
「srand」の所は、インターネットで調べて入れたもので、
意味がよく分かっていなかったので、分かりやすく解説いただきありがとうございます。

「goto」は、他の方に指摘された通り「while」に変えて一回組み直してみようと思います!

> if(1!=Y){}break;}} の所は 
> if(1==Y){goto R;} に対応させて付けなくてはいけないと思っていたので
kmee様のおがげで必要ないという事が分かりました!ありがとうございます!!

あまりソースは見たことがなかったので知りませんでした。
確かに、字下げした方が見やすくていいですね!
これからは、見やすい物を書くように心がけたいと思います!!

また、コードを書いたらアドバイスがもらいたいので、
もし時間があったらよろしくお願いします。

お礼日時:2012/12/07 22:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!