ゲーム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
MOMO

ゲーム

#1

投稿記事 by MOMO » 16年前

今宿題で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");
}
}
}

non

Re:ゲーム

#2

投稿記事 by non » 16年前

質問ですが、3桁の数字は1桁づつ、配列にいれなければいけないのは、仕様ですか?
また、同じ数字が使われてはいけないのも仕様ですか?

MOM

Re:ゲーム

#3

投稿記事 by MOM » 16年前

三桁の数字は一桁づつ、配列に入れなければいけないのは使用ではありません。
しかし三桁の数字がすべて異なっていなければいけません。
よろしくお願いします。

Mist

Re:ゲーム

#4

投稿記事 by Mist » 16年前

最後って言うのは1ゲームごとの終わり?
それとも、6を押して終了した時?

あと、規約にしたがってソースの字下げを行ってください。
読みにくいです。

non

Re:ゲーム

#5

投稿記事 by non » 16年前

次の質問です。
10の位や1の位に0は使ったらいけないのですね。

まだ、プログラムを全部見てないですが、正しく動いてないのは確かですよね。
原因の一つとして、
if (guess_number != secret_number){
これは、配列のアドレスを比較しているので、数字の大きさを比較しているわけではありません。

non

Re:ゲーム

#6

投稿記事 by non » 16年前

とりあえず、3桁の数字にしたらどうでしょうか?
あとで、正解を出すときにも、役に立ちますし。

sec_num=secret_number[0]*100+secret_number[1]*10+secret_number[2];

Mist

Re:ゲーム

#7

投稿記事 by Mist » 16年前

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としては一応ちゃんと動くよ。

MOMO

Re:ゲーム

#8

投稿記事 by MOMO » 16年前

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");

}

}

}

Mist

Re:ゲーム

#9

投稿記事 by Mist » 16年前

> とりあえず、3桁の数字にしたらどうでしょうか?

Hit & Blowというゲームの性質上、各桁はばらばらのほうが処理しやすいと思うよ。
HitはともかくBlowのチェックがめんどくさいよ。
Bitマスクとか使えばそれほど手間でもないけど、初心者ってことだし。

Mist

Re:ゲーム

#10

投稿記事 by Mist » 16年前

とりあえずご質問の回答。

正解数を記憶するための変数をひとつ追加。
最初に0をセットしておく。
printf("Bingo\n"); のところで正解数+1する
正解数を表示する。

それだけ。

Mist

Re:ゲーム

#11

投稿記事 by Mist » 16年前

なんとなくネット上で見つけたソースを切り貼りして作りました、って感じだけど他のおかしなところも指摘しておきます。

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");

}

各プログラムの意味を理解して修正しないとこのまま出しても多分受け取ってもらえないですよ。

non

Re:ゲーム

#12

投稿記事 by non » 16年前

> 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 を
表示したいのかと私は思いました。

Mist

Re:ゲーム

#13

投稿記事 by Mist » 16年前

> どうして、一応ちゃんと動くの?
Hit & Blowというゲーム知りません?
上にも書きましたがここで本来行うべきエラーチェックはguess_number[0]~[2]に一桁の1~9までの数値がきちんと入力されているかどうかです。
で、間違った値が入力されている場合は再入力に戻るようにすることです。
全然出来ていませんけど。

ただ、現状のプログラムでも無駄な文章が毎回出力されるだけでbreakされているわけではないのでその後の処理が動きます。
そのため、”間違った入力がされることがなければ”という条件付でHit & Blowとしては正しく動作していますしゲームとして成立します。
そういう意味での”一応”です。

> まだ、プログラムを全部見てないですが、正しく動いてないのは確かですよね。
エラー処理は多分MOMOさんの意図どおり動いてないとは思いますが、正常系は動きますから動かないと断ずるのはちょっと可哀想かな、と思いました。
どこまでを”正しく”の範疇に含めるかの問題なのかもしれませんが。

> MOMOさんがいう正解数とは、10回やっても当たらなかったときに、secret_number を
> 表示したいのかと私は思いました。
ああ、なるほど。それは思いつきませんでした。
複数回実行できるようになってるから正解までたどり着いた回数かと。
それだったらprintf一個追加するだけですね。

Mist

Re:ゲーム

#14

投稿記事 by Mist » 16年前

ごめん。最後取り消し。

> 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]);

だね。

non

Re:ゲーム

#15

投稿記事 by non » 16年前

Mistさんへ
風呂の中で、さきほどMistさんが書かれた、Hit & Blowは動いているという意味に気がつき、
風呂から、上がったら、MistさんからすでにRESが・・・大変失礼しました。

s-rush

Re:ゲーム

#16

投稿記事 by s-rush » 16年前

横やりすいません。
>>複数回プレイできるようになっているけど正解はみんな同じ
>>正解を作る部分が最初の一回しか実行されないので何回プレイしても答えの数字は常に同じ。
確かにおっしゃる通り、正解を作る部分が1度しか実行されていないので、
何回プレイしても答えは常に同じ数次になります。
ですが、仮にその部分を修正して、ゲームやり直し時に乱数生成部から実行できるようにしても
rand()(だけ)で乱数を生成しているようなので、
何度実行したとしても同じ数値になるのではないでしょうか?

初めの数字を生成するところから少し不十分のような気がします。

Mist

Re:ゲーム

#17

投稿記事 by Mist » 16年前

> rand()(だけ)で乱数を生成しているようなので、
> 何度実行したとしても同じ数値になるのではないでしょうか?

どうしてそのように思われましたか?
何が不足していると思いますか?
「だけ」と書かれているのが非常に気になります。

3桁の重複しない数字ですから同じ数字になる確率は小さくないかもしれませんが、必ず同じになることはないと思います。

s-rush

Re:ゲーム

#18

投稿記事 by s-rush » 16年前

すいません、少し勘違いしてました^^;

srand(time(NULL));
を見落としてました。

Mist

Re:ゲーム

#19

投稿記事 by Mist » 16年前

私の書き方が悪かったかもしれませんが、今回の「何度も実行」というのはプログラムを終了させず(正解、不正解の後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

プログラムの実行単位で見れば同じになりますが、内部単位でみれば同じにはなりませんので違う答えが作れます。
この違いは混同しないでください。

Dixq (管理人)

Re:ゲーム

#20

投稿記事 by Dixq (管理人) » 16年前

>>MOMOさん

細かいことですが、

>Mist ..熟練のプログラマーへ

お名前は「Mist」さんです。後、その方と特に深い付き合いをされていない場合は、敬称を付けるようにしてください。

また、プレタグを使うとコードが見やすくなります。
詳しくは規約をご覧下さい。

s-rush

Re:ゲーム

#21

投稿記事 by s-rush » 16年前

>>プログラムを終了させてもう一度実行する場合には時間等を使ったシードの初期化行っておかないと、s-rushさんがおっしゃるとおりに1回目と2回目では同じ答えになります。
一応こういう意味で、同じになるのではないのかな?
って思いましたので^^;
もっと詳しく書くべきでした。
なので

>>プログラムの実行単位で見れば同じになりますが、内部単位でみれば同じにはなりませんので違う答えが作れます。
>>この違いは混同しないでください。

たぶん大丈夫です。
一応私もゲームで乱数を使いまくっている身なので^^

MOMO

Re:ゲーム

#22

投稿記事 by MOMO » 16年前

返事が遅くなりすいません。
Mist ..熟練のプログラマーへ
printf("You missed.\nThe correct number is %d %d %d",secret_number[0],secret_number[1],secret_number[2]);の部分を変えたら出てくるようになりました。
ありがとうございます。
しかし異なる数字にするにはrandだと3桁をいつも異ならせることは難しいのですが3桁を常に異ならせるいい方法はありますか?

バグ

Re:ゲーム

#23

投稿記事 by バグ » 16年前

0~9の整数を格納した配列を用意して、ランダムに入れ替えて先頭の3つを採用する…とか?

BEMANI

Re:ゲーム

#24

投稿記事 by BEMANI » 16年前

>>MOMOさん
>異なる数字にするにはrandだと3桁をいつも異ならせることは難しいのですが・・・
取得したランダム値と、すでに取得されているランダム値を比較して
同じであればもう一度取得するという方法ではダメでしょうか?


上の記事に管理人さんも書かれていらっしゃいますが
以後、名前を呼ぶ時に「Mist ..熟練のプログラマーへ 」
という書き方は本当にしない方がいいです。(お友達などの関係であれば結構です)
もし違うのであれば、「Mistさん・Mist様」など呼び捨てにしないようにしましょう。

MOMO

Re:ゲーム

#25

投稿記事 by MOMO » 16年前

すいませんでした。
気をつけます。
取得したランダム値と、すでに取得されているランダム値を比較して
同じであればもう一度取得するという方法とはどのようにやるのですか?
C言語初心者なものでいろいろとすいません。

BEMANI

Re:ゲーム

#26

投稿記事 by BEMANI » 16年前

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


今は三桁みたいですので、こんな方法でよいのなら・・・。
(ただし、この書き方は桁数が増えれば、増えるほど、しんどいやり方になります。
改良できるのであれば改良してみましょう。)

toyo

Re:ゲーム

#27

投稿記事 by toyo » 16年前

バグさんの書かれたランダムに入れ替えていく方法なら
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:ゲーム

#28

投稿記事 by やそ » 16年前

ちょっと横に逸れますが・・

TOYOさんの例をみても分かるとおり、

secret_number[0] = rand () % 9 + 1;
だと
0から9ではなく
1から9の乱数になりますが・・・
良いです?

Mist

Re:ゲーム

#29

投稿記事 by Mist » 16年前

> 0から9

と書いたのはバグさんでMOMOさんじゃないね。

やそ

Re:ゲーム

#30

投稿記事 by やそ » 16年前

>Mist さん
 > 0から9
 >と書いたのはバグさんでMOMOさんじゃないね。

うん、バグさんが0から9と書いているのは流れを読んで分かっていますです^^
ただ、MONOさんが想定している数字の範囲が0からなのか1からなのか、はっきりとした
回答が出ていなかったように見えましたので聞いてみた次第です。

nonさんの質問で
>10の位や1の位に0は使ったらいけないのですね。
というのもありましたし・・・

ランダム数字の決定でしたら、toyoさんの提示されたトランプシャッフルの手法が
分かりやすくて良さそうですね^^

閉鎖

“C言語何でも質問掲示板” へ戻る