ページ 1 / 1
ゲーム
Posted: 2009年1月22日(木) 18:07
by MOMO
今宿題で3桁の数を当てるというプログラムを作っているのですが最後に正解数を表示させるにはどうすればよいですか?
C言語初心者です。
よろしくお願いします。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)
{
int secret_number[3];
int guess_number[3];
int hit;
int blow;
int count;
int again;
int point;
int i, n, k;
count= again = point = 0;
srand(time(NULL));
while(1){
k = 0;
secret_number[0] = rand () % 9 + 1;
secret_number[1] = rand () % 9 + 1;
secret_number[2] = rand () % 9 + 1;
for(i = 0;i < 3;i++){
for(n = 0;n < 3;n++){
if(i != n){
if(secret_number != secret_number[n]){
k = k + 1;
}
}
}
}
if(k == 6){
break;
}
}
while(1){
hit = blow = again = 0;
printf("Make a guess the number\nChance is %d\n", (10 - count));
count++;
printf("Make the hundredth.");
scanf("%d", &guess_number[0]);
printf("Make the tenth.");
scanf("%d", &guess_number[1]);
printf("Make the oneth");
scanf("%d", &guess_number[2]);
if (guess_number != secret_number){
if (secret_number > guess_number){
printf("You missed.\nThe number is small\n");
}else{
printf("You missed.\nThe number is big.\n");
}
if (count == 10){
printf("You missed.\nThe correct number is %d",secret_number);
break;
}
}
for(i = 0;i < 3;i++){
for(n = 0;n < 3;n++){
if(i == n){
if(guess_number == secret_number[n]){
hit = hit + 1;
}
}
else{
if(guess_number == secret_number[n]){
blow = blow + 1;
}
}
}
}
printf("hit = %d , blow = %d\n",hit, blow);
if (hit == 3 ){
printf("Bingo\n");
point = point + (11 - count);
printf("This point is%d \n" ,(11 - count));
printf("Total point is%d\n", point);
printf("Do you try again(Yes 2, No 6)\n");
scanf("%d", &again);
if (again == 6){
break;
}
if (again == 1){
count = 0;
}
}
else if (count == 10){
printf("You bad.\n");
printf("Do you try again(Yes 2, No 6)\n");
scanf("%d", &again);
if (again == 6){
break;
}
else {
count = 0;
}
}
else if (hit < 3){
printf("You miss.\n");
}
}
}
Re:ゲーム
Posted: 2009年1月22日(木) 18:21
by non
質問ですが、3桁の数字は1桁づつ、配列にいれなければいけないのは、仕様ですか?
また、同じ数字が使われてはいけないのも仕様ですか?
Re:ゲーム
Posted: 2009年1月22日(木) 18:24
by MOM
三桁の数字は一桁づつ、配列に入れなければいけないのは使用ではありません。
しかし三桁の数字がすべて異なっていなければいけません。
よろしくお願いします。
Re:ゲーム
Posted: 2009年1月22日(木) 18:30
by Mist
最後って言うのは1ゲームごとの終わり?
それとも、6を押して終了した時?
あと、規約にしたがってソースの字下げを行ってください。
読みにくいです。
Re:ゲーム
Posted: 2009年1月22日(木) 18:33
by non
次の質問です。
10の位や1の位に0は使ったらいけないのですね。
まだ、プログラムを全部見てないですが、正しく動いてないのは確かですよね。
原因の一つとして、
if (guess_number != secret_number){
これは、配列のアドレスを比較しているので、数字の大きさを比較しているわけではありません。
Re:ゲーム
Posted: 2009年1月22日(木) 18:42
by non
とりあえず、3桁の数字にしたらどうでしょうか?
あとで、正解を出すときにも、役に立ちますし。
sec_num=secret_number[0]*100+secret_number[1]*10+secret_number[2];
Re:ゲーム
Posted: 2009年1月22日(木) 18:43
by Mist
if (guess_number != secret_number){
if (secret_number > guess_number){
printf("You missed.\nThe number is small\n");
}else{
printf("You missed.\nThe number is big.\n");
}
この部分で何をしたいのかは意味不明だけど、Hit & Blowとしては一応ちゃんと動くよ。
Re:ゲーム
Posted: 2009年1月22日(木) 18:43
by MOMO
Mist ..熟練のプログラマーへ
1ゲームごとです。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(void)
{
int secret_number[3];
int guess_number[3];
int hit;
int blow;
int count;
int again;
int point;
int i, n, k;
count= again = point = 0;
srand(time(NULL));
while(1){
k = 0;
secret_number[0] = rand () % 9 + 1;
secret_number[1] = rand () % 9 + 1;
secret_number[2] = rand () % 9 + 1;
for(i = 0;i < 3;i++){
for(n = 0;n < 3;n++){
if(i != n){
if(secret_number != secret_number[n]){
k = k + 1;
}
}
}
}
if(k == 6){
break;
}
}
while(1){
hit = blow = again = 0;
printf("Make a guess the number\nChance is %d\n", (10 - count));
count++;
printf("Make the hundredth.");
scanf("%d", &guess_number[0]);
printf("Make the tenth.");
scanf("%d", &guess_number[1]);
printf("Make the oneth");
scanf("%d", &guess_number[2]);
if (guess_number != secret_number){
if (secret_number > guess_number){
printf("You missed.\nThe number is small\n");
}else{
printf("You missed.\nThe number is big.\n");
}
if (count == 10){
printf("You missed.\nThe correct number is %d",secret_number);
break;
}
}
for(i = 0;i < 3;i++){
for(n = 0;n < 3;n++){
if(i == n){
if(guess_number == secret_number[n]){
hit = hit + 1;
}
}
else{
if(guess_number == secret_number[n]){
blow = blow + 1;
}
}
}
}
printf("hit = %d , blow = %d\n",hit, blow);
if (hit == 3 ){
printf("Bingo\n");
point = point + (11 - count);
printf("This point is%d \n" ,(11 - count));
printf("Total point is%d\n", point);
printf("Do you try again(Yes 2, No 6)\n");
scanf("%d", &again);
if (again == 6){
break;
}
if (again == 1){
count = 0;
}
}
else if (count == 10){
printf("You bad.\n");
printf("Do you try again(Yes 2, No 6)\n");
scanf("%d", &again);
if (again == 6){
break;
}
else {
count = 0;
}
}
else if (hit < 3){
printf("You miss.\n");
}
}
}
Re:ゲーム
Posted: 2009年1月22日(木) 18:45
by Mist
> とりあえず、3桁の数字にしたらどうでしょうか?
Hit & Blowというゲームの性質上、各桁はばらばらのほうが処理しやすいと思うよ。
HitはともかくBlowのチェックがめんどくさいよ。
Bitマスクとか使えばそれほど手間でもないけど、初心者ってことだし。
Re:ゲーム
Posted: 2009年1月22日(木) 18:52
by Mist
とりあえずご質問の回答。
正解数を記憶するための変数をひとつ追加。
最初に0をセットしておく。
printf("Bingo\n"); のところで正解数+1する
正解数を表示する。
それだけ。
Re:ゲーム
Posted: 2009年1月22日(木) 19:23
by Mist
なんとなくネット上で見つけたソースを切り貼りして作りました、って感じだけど他のおかしなところも指摘しておきます。
1.複数回プレイできるようになっているけど正解はみんな同じ
正解を作る部分が最初の一回しか実行されないので何回プレイしても答えの数字は常に同じ。
2.下の部分は入力された各桁の数字が1~9の範囲であるかをチェックするようにすべき。
同じ答えを見たことがあるけど、そのプログラムとあなたのプログラムでは目的がそもそも違うからそのままパクっても意味がない。
if (guess_number != secret_number){
if (secret_number > guess_number){
printf("You missed.\nThe number is small\n");
}else{
printf("You missed.\nThe number is big.\n");
}
各プログラムの意味を理解して修正しないとこのまま出しても多分受け取ってもらえないですよ。
Re:ゲーム
Posted: 2009年1月22日(木) 19:41
by non
> if (guess_number != secret_number){
> if (secret_number > guess_number){
> printf("You missed.\nThe number is small\n");
> }else{
> printf("You missed.\nThe number is big.\n");
> }
>
> この部分で何をしたいのかは意味不明だけど、Hit & Blowとしては一応ちゃんと動くよ。
やりたいことは、入力した3桁の数字が、乱数で出しておいた答えと比較して大きいか
小さいか表示しているつもりだと思いますが・・・
どうして、一応ちゃんと動くの?
配列のアドレスを比較しているのだから、絶対一致することはなく、何度やっても同じ答えに
なるのでは?
MOMOさんがいう正解数とは、10回やっても当たらなかったときに、secret_number を
表示したいのかと私は思いました。
Re:ゲーム
Posted: 2009年1月22日(木) 20:20
by Mist
> どうして、一応ちゃんと動くの?
Hit & Blowというゲーム知りません?
上にも書きましたがここで本来行うべきエラーチェックはguess_number[0]~[2]に一桁の1~9までの数値がきちんと入力されているかどうかです。
で、間違った値が入力されている場合は再入力に戻るようにすることです。
全然出来ていませんけど。
ただ、現状のプログラムでも無駄な文章が毎回出力されるだけでbreakされているわけではないのでその後の処理が動きます。
そのため、”間違った入力がされることがなければ”という条件付でHit & Blowとしては正しく動作していますしゲームとして成立します。
そういう意味での”一応”です。
> まだ、プログラムを全部見てないですが、正しく動いてないのは確かですよね。
エラー処理は多分MOMOさんの意図どおり動いてないとは思いますが、正常系は動きますから動かないと断ずるのはちょっと可哀想かな、と思いました。
どこまでを”正しく”の範疇に含めるかの問題なのかもしれませんが。
> MOMOさんがいう正解数とは、10回やっても当たらなかったときに、secret_number を
> 表示したいのかと私は思いました。
ああ、なるほど。それは思いつきませんでした。
複数回実行できるようになってるから正解までたどり着いた回数かと。
それだったらprintf一個追加するだけですね。
Re:ゲーム
Posted: 2009年1月22日(木) 20:24
by Mist
ごめん。最後取り消し。
> MOMOさんがいう正解数とは、10回やっても当たらなかったときに、secret_number を
> 表示したいのかと私は思いました。
printf("You missed.\nThe correct number is %d",secret_number);
ここ直すだけか。
printf("You missed.\nThe correct number is %d %d %d",secret_number[0],secret_number[1],secret_number[2]);
だね。
Re:ゲーム
Posted: 2009年1月22日(木) 20:24
by non
Mistさんへ
風呂の中で、さきほどMistさんが書かれた、Hit & Blowは動いているという意味に気がつき、
風呂から、上がったら、MistさんからすでにRESが・・・大変失礼しました。
Re:ゲーム
Posted: 2009年1月22日(木) 21:14
by s-rush
横やりすいません。
>>複数回プレイできるようになっているけど正解はみんな同じ
>>正解を作る部分が最初の一回しか実行されないので何回プレイしても答えの数字は常に同じ。
確かにおっしゃる通り、正解を作る部分が1度しか実行されていないので、
何回プレイしても答えは常に同じ数次になります。
ですが、仮にその部分を修正して、ゲームやり直し時に乱数生成部から実行できるようにしても
rand()(だけ)で乱数を生成しているようなので、
何度実行したとしても同じ数値になるのではないでしょうか?
初めの数字を生成するところから少し不十分のような気がします。
Re:ゲーム
Posted: 2009年1月22日(木) 22:42
by Mist
> rand()(だけ)で乱数を生成しているようなので、
> 何度実行したとしても同じ数値になるのではないでしょうか?
どうしてそのように思われましたか?
何が不足していると思いますか?
「だけ」と書かれているのが非常に気になります。
3桁の重複しない数字ですから同じ数字になる確率は小さくないかもしれませんが、必ず同じになることはないと思います。
Re:ゲーム
Posted: 2009年1月22日(木) 23:07
by s-rush
すいません、少し勘違いしてました^^;
srand(time(NULL));
を見落としてました。
Re:ゲーム
Posted: 2009年1月22日(木) 23:37
by Mist
私の書き方が悪かったかもしれませんが、今回の「何度も実行」というのはプログラムを終了させず(正解、不正解の後2キーを押して)ゲームを継続した場合のことなので、乱数シードの初期化(srand)を行っているかどうかは関係ありません。
randが実行されるたびに乱数が返されますので、まず違う答えが出来ると思います。
プログラムを終了させてもう一度実行する場合には時間等を使ったシードの初期化行っておかないと、s-rushさんがおっしゃるとおりに1回目と2回目では同じ答えになります。(同じだったら"乱数"じゃねーな(^^;)
例:srandは行わない、乱数値は適当
プログラム自体の実行(1回目)
rand(1回)=1000
rand(2回)=5
rand(3回)=98
rand(4回)=325
プログラム自体の実行(2回目)
rand(1回)=1000
rand(2回)=5
rand(3回)=98
rand(4回)=325
プログラムの実行単位で見れば同じになりますが、内部単位でみれば同じにはなりませんので違う答えが作れます。
この違いは混同しないでください。
Re:ゲーム
Posted: 2009年1月22日(木) 23:50
by Dixq (管理人)
>>MOMOさん
細かいことですが、
>Mist ..熟練のプログラマーへ
お名前は「Mist」さんです。後、その方と特に深い付き合いをされていない場合は、敬称を付けるようにしてください。
また、プレタグを使うとコードが見やすくなります。
詳しくは規約をご覧下さい。
Re:ゲーム
Posted: 2009年1月23日(金) 00:09
by s-rush
>>プログラムを終了させてもう一度実行する場合には時間等を使ったシードの初期化行っておかないと、s-rushさんがおっしゃるとおりに1回目と2回目では同じ答えになります。
一応こういう意味で、同じになるのではないのかな?
って思いましたので^^;
もっと詳しく書くべきでした。
なので
>>プログラムの実行単位で見れば同じになりますが、内部単位でみれば同じにはなりませんので違う答えが作れます。
>>この違いは混同しないでください。
たぶん大丈夫です。
一応私もゲームで乱数を使いまくっている身なので^^
Re:ゲーム
Posted: 2009年1月23日(金) 12:19
by MOMO
返事が遅くなりすいません。
Mist ..熟練のプログラマーへ
printf("You missed.\nThe correct number is %d %d %d",secret_number[0],secret_number[1],secret_number[2]);の部分を変えたら出てくるようになりました。
ありがとうございます。
しかし異なる数字にするにはrandだと3桁をいつも異ならせることは難しいのですが3桁を常に異ならせるいい方法はありますか?
Re:ゲーム
Posted: 2009年1月23日(金) 12:29
by バグ
0~9の整数を格納した配列を用意して、ランダムに入れ替えて先頭の3つを採用する…とか?
Re:ゲーム
Posted: 2009年1月23日(金) 12:37
by BEMANI
>>MOMOさん
>異なる数字にするにはrandだと3桁をいつも異ならせることは難しいのですが・・・
取得したランダム値と、すでに取得されているランダム値を比較して
同じであればもう一度取得するという方法ではダメでしょうか?
上の記事に管理人さんも書かれていらっしゃいますが
以後、名前を呼ぶ時に「Mist ..熟練のプログラマーへ 」
という書き方は本当にしない方がいいです。(お友達などの関係であれば結構です)
もし違うのであれば、「Mistさん・Mist様」など呼び捨てにしないようにしましょう。
Re:ゲーム
Posted: 2009年1月23日(金) 12:49
by MOMO
すいませんでした。
気をつけます。
取得したランダム値と、すでに取得されているランダム値を比較して
同じであればもう一度取得するという方法とはどのようにやるのですか?
C言語初心者なものでいろいろとすいません。
Re:ゲーム
Posted: 2009年1月23日(金) 13:51
by BEMANI
>>MOMOさん
MOMOさんの場合、
・乱数を三つ取得する
・正解・不正解を表示する
という流れが出来ていると思うので、
・それが同じかどうかを見る
・同じならもう一度取得し、違うのであれば三つの数字はすべて違うといえる
これをC言語という形で書いていきましょう。
secret_number[0]、[1]、[2]が同じでなければいいんですよね?
(間違ってたらごめんなさい;)
// まず、secret_number[0]と[1]と[2]の値を取得します。(これはもう出来ていますね)
secret_number[0] = rand () % 9 + 1;
secret_number[1] = rand () % 9 + 1;
secret_number[2] = rand () % 9 + 1;
// 次に、secret_number[0]と[1]が同じ値でないかを調べ、
// もし同じならもう一度取得します。
// ここで、取得した値がまたかぶってしまう可能性もあるのでwhileを使い
// 同じでなくなるまで取得します。
while(1)
{
if(secret_number[0] == secret_number[1])
secret_number[1] = rand()%9 + 1;
else
break;
}
// 最後に、secret_number[0]と[2]・[1]と[2]が同じ値でないかを調べ、
// もし同じならもう一度取得します。
// この条件が満たされれば、かぶらないと思います
while(1)
{
if( (secret_number[0] == secret_number[2]) || (secret_number[1] == secret_number[2]) )
secret_number[2] = rand()%9 + 1;
else
break;
}
今は三桁みたいですので、こんな方法でよいのなら・・・。
(ただし、この書き方は桁数が増えれば、増えるほど、しんどいやり方になります。
改良できるのであれば改良してみましょう。)
Re:ゲーム
Posted: 2009年1月23日(金) 14:03
by toyo
バグさんの書かれたランダムに入れ替えていく方法なら
int secret_number[/url] = {1,2,3,4,5,6,7,8,9};
int i, j, k, l;
for (i = 0; i < 10; i++) {
j = rand() % 9;
k = rand() % 9;
l = secret_number[ j ];
secret_number[ j ] = secret_number[ k ];
secret_number[ k ] = l;
}
トランプゲームのシャッフルでよく使われるかな
Re:ゲーム
Posted: 2009年1月23日(金) 16:48
by やそ
ちょっと横に逸れますが・・
TOYOさんの例をみても分かるとおり、
secret_number[0] = rand () % 9 + 1;
だと
0から9ではなく
1から9の乱数になりますが・・・
良いです?
Re:ゲーム
Posted: 2009年1月24日(土) 08:42
by Mist
> 0から9
と書いたのはバグさんでMOMOさんじゃないね。
Re:ゲーム
Posted: 2009年1月27日(火) 11:16
by やそ
>Mist さん
> 0から9
>と書いたのはバグさんでMOMOさんじゃないね。
うん、バグさんが0から9と書いているのは流れを読んで分かっていますです^^
ただ、MONOさんが想定している数字の範囲が0からなのか1からなのか、はっきりとした
回答が出ていなかったように見えましたので聞いてみた次第です。
nonさんの質問で
>10の位や1の位に0は使ったらいけないのですね。
というのもありましたし・・・
ランダム数字の決定でしたら、toyoさんの提示されたトランプシャッフルの手法が
分かりやすくて良さそうですね^^