C言語で初めてのコーディング!数当てゲームを作成しました

このQ&Aのポイント
  • 高校生男子が独学でC言語を学び、初めてのコードを組みました。
  • 「猫でもわかる C言語プログラミング」という本を参考にしています。
  • 今後はより高度なプログラムやゲームを作りたいと考えています。アドバイスをお願いします。
回答を見る
  • ベストアンサー

高(1)男子 初めてC言語でコードを書きました!!

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

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

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

s0865s
質問者

お礼

アドバイスありがとうございます。 コードを書くのに夢中で 特に変数名などは気にしていませんでした。 確かに、後から見直した時に、 変数名の「i」の所を回答数の「K」や、 「Y」の所をリターンの「R」 「goto」の戻る先をリターンポイントの「RP」 などにすると分かりやすいという事に気付きました!! Tacosan様のご指摘通り本を見直してみたら 「1==Y」ではなく「Y==1」となっていたので今後気をつけたいと思います。 最後に、他の皆様にも、お願いしているのですが、 今後もコードを書いたらアドバイスがもらいたいので、 もし時間があったらよろしくお願いします。

その他の回答 (7)

回答No.8

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

s0865s
質問者

お礼

参考にしていた本に「#define」と言うのは 載っていなかったと思うので、 maru_yoshi_様のおかげでとても便利なものを覚えることが出来ました!! 次書くときは、今回教えていただいた事をいかして マジックナンバーをなくしたいと思います! アドバイスありがとうございました。

  • wormhole
  • ベストアンサー率28% (1619/5654)
回答No.7

>本を見直してみたら >「1==Y」ではなく「Y==1」となっていたので今後気をつけたいと思います。 前者だと「1がYに等しい」、後者だと「Yが1に等しい」どちらが素直に読めますか。って事ですよ。

s0865s
質問者

お礼

「Y=1」のように、Yに1を入れるという風に考えると 「Y==1」や「Y!=1」といったように、Yは、1と等しい、Yは、1と等しくない と言ったようにした方がスッキリ読めますね! それに、コードを書いたときに「左に変数」と統一しておいた方が 分かりやすいし、見やすいと思いました!! wormhole様のおかげで本に書かれていた内容が理解できたような気がします!! アドバイス、ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

いやいや, 「自分で見てわかる」ことを考えちゃダメだって. 「他人が見てわかる」かどうかを考えなきゃ. 例えば, 他の人が見たときに「K は『回答数』なんだ」ってわかってくれると思いますか? 「K」と「kaitousuu」の, どちらがより「回答数」と思ってもらいやすいでしょうか? あるいは, 「リターンの R」と言ってますが, 他の人に「『リターン』ってなんだと思う?」と聞いたらあなたが思っているものと同じものが確実に返ってくると思いますか?

s0865s
質問者

お礼

Tacosan様、二度も分かりやすい説明ありがとうございます。 確かに、「K」と書かれで「回答数」だと分かって貰うには 隣に、コメントでも、書いておかない限り難しいですね。 それに僕は「スタートに戻る」という意味でリターンと言う物を 使おうと思ったのですが、今、見返してみると とても分かりにくかったです。 今後、他の人と共同でプログラムを組んだり、 今回のようにアドバイスをもらう時などのために どんなプログラムか知らない人が見ても、 すぐ分かるような分かりやすいプログラムを 書くことが大切なのですね!

  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.4

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; }

s0865s
質問者

お礼

アドバイスありがとうございます。 jjon-com様のコードでやらせていただきました! ゲームをやっていって最後に答えが出た方がすっきりして プレイヤー側からしてみると親切ですね!! 次、作る時はプレイヤー側から見てどんな工夫があったらうれしいか いろいろ考えて試行錯誤していきたいと思います 他の皆様にも、お願いしているのですが、 今後もコードを書いたらアドバイスがもらいたいので、 もし時間があったらよろしくお願いします。

noname#245243
noname#245243
回答No.3

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%E3%81%92%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB
s0865s
質問者

お礼

アドバイスありがとうございます。 僕の書いた物と比べると字下げしてある物の方が 全然見やすいと思い、改めて見やすい物を書く重要性が分かりました!! 今後も、コードを書いたらアドバイスがもらいたいので、 kmee様たちと同様にもし時間があったらよろしくお願いします。

  • tsunji
  • ベストアンサー率20% (196/958)
回答No.2

#1さんと同じで、gotoを使わない方が、C言語としてすっきりします。 私のならwhile(1){}かdo..whileでループする方法にしますけどね。 ローカル変数のint Q,A,Y,i;は、関数の入り口にまとめておいた方がいいね。 printf("0~100のうちどれが答えなのか当ててください\n"); は1~100だよね。

s0865s
質問者

お礼

アドバイスありがとうございます。 tsunji様のご指摘通り「goto」は、使わずに「while」にして組み立てて 変数は、関数の入口にしたりなどしてミスを無くし見やすい物を書けるように心がけたいです!! kmee様と同様に、またコードを書いたらアドバイスがもらいたいので、 もし時間があったらよろしくお願いします。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

> 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ではあまり見掛けない流儀です。

s0865s
質問者

お礼

アドバイスありがとうございます。 「srand」の所は、インターネットで調べて入れたもので、 意味がよく分かっていなかったので、分かりやすく解説いただきありがとうございます。 「goto」は、他の方に指摘された通り「while」に変えて一回組み直してみようと思います! > if(1!=Y){}break;}} の所は  > if(1==Y){goto R;} に対応させて付けなくてはいけないと思っていたので kmee様のおがげで必要ないという事が分かりました!ありがとうございます!! あまりソースは見たことがなかったので知りませんでした。 確かに、字下げした方が見やすくていいですね! これからは、見やすい物を書くように心がけたいと思います!! また、コードを書いたらアドバイスがもらいたいので、 もし時間があったらよろしくお願いします。

関連するQ&A

  • C言語で数当てゲーム

    私は最近5月からCのプログラミングを学び始めた中3なんですが じゃんけんゲームと丁半ゲームを今までに作りました で今回数当てゲームを作ってみたのですが何回作り直しても エラーが出ます(コンパイラのエラーではなくWindows?のエラーのようなもの) じゃんけんゲームなどと同じように作ったつもりなのですが・・・・ どうなっているのでしょうか? ソースは↓です #include <stdio.h> #include <time.h> #include <stdlib.h> #include <conio.h> int main() { int kazu,i,x; printf("数当てゲーム!!\n"); srand(time(NULL)); x=0; i=0; do { kazu=rand()%9+1; printf("数を入力してください(1~9)\n"); scanf("%d",i); if(i<10){ if(i==kazu) { printf("当たり!!\n続けるなら0やめるなら0以外を入力"); scanf("%d",x); } else {printf("残念・・・はずれ\n続けるなら0やめるなら0以外を入力"); scanf("%d",x);} } else {printf("入力ミスです\n続けるなら0やめるなら0以外を入力"); getch();} }while(x==0); return 0; } 一応コンパイラのエラーは出ていないのですが・・・ 初心者なのでわかりません。 どこが原因なのか詳しくおしえてください

  • C言語【おみくじプログラム】

    お正月前にならったばかりのC言語を用いて おみくじプログラムを作りました。 最近それをまた改良して 強制的にくじを引かせるものにしようと考えました。 しかしどうしてもwhileのループから抜け出せないので ここで質問させていただきます。 どうか間違っている部分を教えてください。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 7 int main(){ int k,y,n; printf("ようこそ。\n"); printf("ここではおみくじを販売して折ります。\n"); printf("よろしければ運試しをしていって下さい。\n\n"); printf("おみくじを引きますか?\n"); printf("※引く場合はy,引かない場合はnを入力してください\n"); scanf("%s,&k"); if(k!=y){ while(k=y){ printf("そんなこと言わずに引いてみてくださいよ。\n\n"); printf("おみくじを引きますか?\n"); printf("※引く場合はy,引かない場合はnを入力してください\n"); scanf("%s,&k"); } } char *kuji[N] = {"大吉", "中吉", "小吉","末吉", "吉", "凶","大凶"}; srand((unsigned)time(NULL)); printf("おみくじ: %s\n\n\n", kuji[rand() % N]); printf("結果はどうでしたか?\n"); printf("またのお越しをお待ちしております。\n"); return 0; }

  • 文字と数字の判定について

    c言語を学び始めたばかりの者です。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <ctype.h> main(){ printf("数当てゲームを開始します。\n"); int a,count,n,b; srand((unsigned)time(NULL)); printf("1~10の中から1つ数字を選びます。\n"); a = (rand()%10)+1; printf("選びました\n"); for(count=0;;count++){ printf("その数字はズバリ:"); scanf("%d",&n); //もし数字でなければという文にしたい!! if (?){ printf("数字を入力してください。\n"); continue; } else{ if(n<a){ printf("もっと大きな値です。\n"); printf("%d回間違えました。\n",count+1); continue; } if(n==a){ printf("正解です!!\n"); b=0; exit(0); } if(n>a){ printf("もっと小さな値です。\n"); printf("%d回間違えました。\n",count+1); continue; } } } } というプログラムなのですが数字の判定の仕方が分からなくて最初のifの条件に何をいれればいいのか分からないので分かるかたいましたら教えてもらえないでしょうか?

  • C言語の問題がわからないです。

    C言語のプログラムで、列数を自分で決めて、 (例)3列         ●(この行を最後として)   □● ●□● 上記のプログラムを作りたいのですが、 上手くいきません。途中まで作ったのですが、なかなか思うようにいかないです。どうすれば上記のようになりますでしょうか? #include <stdio.h> void disp(int x, int y); main() { int i,n; printf("表示する列:"); scanf("%d",&n); disp(3,3); for(i=1;i<=n;i++){ if(i%2==0){ disp(n-i,4); disp(i,2); } else{ disp(n-i,4); disp(i,1); } disp(1,3); } } void disp(int x, int y) { int i; for(i=0;i<x;i++){ if(y==1){ printf("●"); } else if(y==2){ printf("□"); } else if(y==3){ printf("\n"); } else{ printf("\0"); } } }

  • C言語について

    次のような問題です。 問 自然数nを入力し、nを3で割って割り切れるかどうかを判定し結果を表示する。「割り切れる」、「1余る」、「「2余る」のいずれかが入るものとする。 このようなものをつくりました。 #include<stdio.h> int main(void) { int n; printf("自然数:"); scanf("%d",&n); if(n==0){ printf("割り切れる\n"); }else if(n==1){ printf("1余る\n"); }else{ printf("2余る"); } return(0); } これで合っているかよろしくお願いします。

  • C言語のソースコードについて教えてください。

    以下のソースコードを学習用C言語開発環境で行ったのですが、 『ファイル「C:/Users/ユーザー名/AppData/Local/EasyIDEC/project/タイトル/main.c」の 「41行目」で記述エラーを発見しました。 「,」を付け忘れています。』 という、コンパイルエラーが表示されました。 何度も見直したのですが、よくわかりません。 #include <stdio.h> int main(int argc, char *argv[]) { char answer ; answer = 'n' ; while(answer =='n') { int input ; input = 0 ; int add ; add = 1 ; int sum ; sum = 0 ; printf("数値を入力して下さい。:") ; scanf("%d", &input ) ; int i ; i = 0 ; while(i < input) { sum =sum + add ; printf("\n%d",sum) ; i++ ; add++ ; } printf("\n1から%dまでの総和は、%dです。" , input , sum) ; while(1) { printf("\n終了しますか? y/n:") ; scanf(" %c , &answer) ; if( (answer != 'y') && (answer != 'n') ) { printf( "y or nを入れてください。") ; } else { break ; } } } return 0 ; }

  • c言語について。

    #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<time.h> int goukei=0; //goukei関数の定義 int detame; //detame関数の定義 void gusu(){printf("偶数%dが出ました。ゲームオーバーです。\n",detame); getchar(); exit(1);} int kisu(){ goukei=goukei+detame; printf("奇数%dがでました。合計%d点です。\n",detame,goukei); } main(){ char answer[20]; //文字型変数answerの宣言 int amari; //amari関数の宣言 //ゲームの説明・開始 printf("さいころの目が奇数なら、出た目だけ得点が加算され、\n"); printf("偶数が出たら、その場でゲームオーバーです。\n"); printf("さいころを振ってください。\n"); getchar(); srand((unsigned)time(NULL));//rand関数の初期化 detame=rand()%6+1;//1から6までの乱数の発生 amari=detame%2; if(amari==0){gusu();}else{kisu();} while(1) { printf("ゲームを続けますか?yesかnoで答えてください。\n"); scanf("%s",&answer); if(strcmp(answer,"no")==0){ break;} printf("ゲームを続けます。\n"); printf("さいころを振ってください。\n"); getchar(); detame=rand()%6+1; amari=detame%2; if(amari==0){gusu();}else{kisu();} } //合計得点とゲームの終了 printf("合計で%d点でした。ゲームを終了します。\n",goukei); } このプログラミングはさいころを振って、奇数なら出た目が加算され奇数ならゲームオーバーというものなんですが、さいころを二つにするときはどういうプログラムになるのか教えてください。お願いします。

  • C言語でのじゃんけん

    こんちには。 C言語の乱数を用いてじゃんけんプログラムを作ろうと思っているのですが、 エラーメッセージが出てしまいうまくいきません。 どこがおかしいのでしょうか? #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int i,j,k; printf("じゃんけんをしましょう(ぐー:1、ちょき:2、ぱー:3)¥n"); for(k=k; k<=10; k++) { srand(time(NULL)); j=rand()%3+1; scanf("%d",&i); if(i==1&&j==1) printf("私はグーなので、あいこです¥n"); else if(i==1&&j==2) printf("私はチョキなので、あなたの勝ちです¥n"); else if(i==1&&j==3) printf("私はパーなので、あなたの負けです¥n"); else if(i==2&&j==1) printf("私はグーなので、あなたの負けです¥n"); else if(i=2&&j==2) printf("私はチョキなので、あいこです¥n"); else if(i==2&&j==3) printf("私はパーなので、あなたの勝ちです¥n"); else if(i==3&&j==1) printf("私はグーなので、あなたの勝ちです¥n"); else if(i==3&&j==2) printf("私はチョキなので、あなたの負けです¥n"); else if(i==3&&j==3) printf("私はパーなので、あいこです¥n"); else printf("1か2か3を入力してください¥n"); } } OS mountain lionで利用中ですが、 「じゃんけんをしましょう(ぐー:1、ちょき:2、ぱー:3)」 と表示されたまま、うまく動作しません。 教えてください。

    • ベストアンサー
    • Mac
  • C++言語について。構文エラー

    ジャンケンゲームを作ってたんですが サイトを参考にしながらやってたんですが、どこかでミスったみたいで。 コピーしてやるのはイヤなので、自分で打ちたいんです。   どうか間違いを指摘してもらえないでしょうか?            #include <stdio.h> #include <stdlib.h> int main() { int n; int p;//player int c;//computer srand(0);//乱数の初期化 do { //プレイヤーの手 printf("あなたの手を入力してください\n(グー:1、チョキ:2、パー:3\n"); scanf("%d", &p); //コンピュータの手 c = rand() % 3 + 1; //勝ち負け判定 if(p == c){ printf("draw\n"); }else if(p == 1 && c == 2){ printf("WIN!!\n"); }else if(p == 2 && c == 3){ printf("WIN!!\n"); }else if(p == 3 && c == 2){ printf("WIN!!\n"); }else{ printf("lose...\n"); } //続けるかどうかの判定 printf("try agin?\nNO(0を入力)---"); scanf("%d", &n); //nが0以外だったら続ける }while(n != 0); return 0; }        で、エラーが構文エラー : ';' が 'return' の前にありません。 というものでした。   よろしくおねがいします。

  • C言語の問題です!!

    すみません。 詳細表示をする際に、未ソート部の先頭要素の上に記号文字「*」を表示し、未ソート部の最小要素の上に記号文字「+」を表示したいと思い、以下のソースプログラムを作成したのですが、結果が何か違う気がします…。どこが違うのか、教えていただけませんか? また、プログラムを修正していただけませんか? #include<stdio.h> #include<stdlib.h> #include<time.h> #define swap(type,x,y) do{type t=x;x=y;y=t;}while(0) /*--- 単純選択ソート ---*/ void selection(int a[], int n) { int i, j,k,flg; char *disp[]={" ","[* ]","[ +]","[*+]"}; for (i = 0; i < n - 1; i++) { int min = i; for (j = i + 1; j < n; j++) { if (a[min] > a[j]) { min = j; } } for (k = 0; k < n; k++) { flg=0; if(k==i) flg|=1; if(k==min) flg|=2; printf("%s",disp[flg]); } printf("\n"); for (k = 0; k < n; k++) printf("[%2d]", a[k]); printf("\n"); swap(int, a[i], a[min]); } } int main(void) { int i, nx; int *x; printf("要素数 : "); scanf("%d", &nx); x = calloc(nx, sizeof(int)); srand(time(NULL)); for (i = 0; i < nx; i++) { x[i] = rand() % 100; printf("x[%d] = %d\n", i, x[i]); } selection(x, nx); for (i = 0; i < nx; i++) printf("x[%d] = %d\n", i, x[i]); free(x); return 0; }

専門家に質問してみよう