プロが教えるわが家の防犯対策術!

Cプログラムについて質問です。
列挙体と関数を用いてじゃんけんゲームを作成しています。
コンパイラは上手くいったのですが、何回か実行してみてコンピュータ側はグーしか出してくれません。
そして3つ警告が出てしまいます。
C26812 列挙型 'janken' は対象範囲外です。'enum' (Enum.3) より 'enum class' を優先します。
C6001 初期化されていないメモリ 'shoubukekka' を使用しています。 Project2
C6031 戻り値が無視されました: 'scanf' Project2
やはりこの警告のせいでグーしか出してくれないのでしょうか?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef enum janken { Gu = 0, Choki = 2, Pa = 5 } JPON;
int saikoro(void) {
int sai;
srand((unsigned)time(NULL));
sai =rand()%6+1;
return(0);
}
JPON sysjan(int sai)
{
int pon;

switch (sai) {
case 1: pon = Gu; break;
case 2: pon = Gu; break;
case 3: pon = Choki; break;
case 4: pon = Choki; break;
case 5: pon = Pa; break;
case 6: pon = Pa; break;
}

return ((JPON)0);
}
int shoubu(JPON kenin, JPON kenout)
{
int shoubukekka;

switch (kenin) {
case Gu:
if (kenout == Gu) shoubukekka = 0;
else if (kenout == Choki) shoubukekka = 1;
else shoubukekka = -1;
break;
case Choki:
if (kenout == Gu) shoubukekka = -1;
else if (kenout == Choki) shoubukekka = 0;
else shoubukekka = 1;
break;
case Pa:
if (kenout == Gu) shoubukekka = 1;
else if (kenout == Choki) shoubukekka = -1;
else shoubukekka = 0;
break;
}

return (shoubukekka);
}
void watashinoken(JPON ken)
{
switch (ken) {
case Gu: printf("わたしはグーを出しました。\n"); break;
case Choki: printf("わたしはチョキを出しました。\n"); break;
case Pa: printf("わたしはパーを出しました。\n"); break;
}
}
void anatanoken(JPON ken)
{
switch (ken) {
case Gu: printf("あなたはグーを出しました。\n"); break;
case Choki: printf("あなたはチョキを出しました。\n"); break;
case Pa: printf("あなたはパーを出しました。\n"); break;
}
}
void kekka(int r)
{
switch (r) {
case -1: printf("あなたの負けです\n"); break;
case 1: printf("あなたの勝ちです\n"); break;
case 0: printf("あいこです\n"); break;
}
}
int main(void) {
JPON choken;
JPON sysken;
int ken_buf;
int sai;
int shoubukekka;
do {
printf("\nジャンケンをしましょう。\n");
printf("\nグーは0 チョキは2 パーは5を入れます。\n");
printf("\nじゃんけんぽん!はいどうぞ:\a");
scanf("%d", &ken_buf);
choken = (JPON)ken_buf;
if ((choken != Gu) && (choken != Choki) && (choken != Pa))
printf("\n@@@@正しく入れてください!@@@@\n");
} while (!(choken == Gu || choken == Choki || choken == Pa));
sai = saikoro();
sysken = sysjan(sai);
shoubukekka = shoubu(choken, sysken);
printf("\a");
anatanoken(choken);
watashinoken(sysken);
kekka(shoubukekka);
printf("\n終わります。おつかれさまでした。\n\n");
return(0);
}

A 回答 (5件)

> 少し修正を加えて上手いこといきました。



そりゃ良かったです。

> グーを3回連続で出してくることはありますが、ちゃんと他の手も出すようになりました。

一応、グーの3回連続出現、ってのは4%くらいの確率で起こりうるんで、25回に1回くらいの確率で出るんで、まぁ気にせんでもエエんちゃうかな。
    • good
    • 0

> 何回か実行してみてコンピュータ側はグーしか出してくれません。



まず、「そりゃそうだ」と言う話。
前回

https://oshiete.goo.ne.jp/qa/12336707.html

参照すると、コンピュータの手は、

> 1.3 1~6のサイの目を引数で受け取り、目が1,2ならグーを、3,4ならチョキを、5,6ならパーを発生させる関数sysjanを作成せよ。(sysjanはコンピュータが出す拳)

で定義されてる

> JPON sysjan(int sai)

がコントロールしてるんだけど、まず今回、ここの定義が間違ってます。

> return ((JPON)0);

って定義したでしょ?
って事は毎回0しか返さなく、って事は、列挙体JPONの定義により毎回グーしか出してません。そしてその上のswitch文での判定が全く役に立ってない無駄な処理になっている。
まず、そのreturn ((JPON)0);を消す。
そして、

switch (sai) {
 case 1: pon = Gu; break;
 case 2: pon = Gu; break;
 case 3: pon = Choki; break;
 case 4: pon = Choki; break;
 case 5: pon = Pa; break;
 case 6: pon = Pa; break;
}

って書いてるけど、多分switch文とbreak文の関係がまだキチンと分かってないんじゃないかしらん。
ぶっちゃけ、ここで直接returnしちまって構わない。breakはswitch文から脱出するんだけど、returnは大枠の関数自体から脱出するんで、ここでreturnを使っても良いです。っつーか、手を返すのがこの関数の目的なので。
従って、

switch(sai) {
 case 1: case 2: return Gu;
 case 3: case 4: return Choki;
 default: return Pa;
}

って書いちゃって構わない。ここでreturnしておけば関数がJPONで定義された値を返して、関数sysjan「自体から」脱出してくれます。
そして変数ponなんざ用意しないで良いです。従って代入も要りません。

もう一つ。ここで定義されてる仮引数saiな何なのか、と言う事。ここに手の基となる「数値」が入る、ってのが

> ~6のサイの目を引数で受け取り、目が1,2ならグーを、3,4ならチョキを、5,6ならパーを発生させる関数sysjanを作成せよ。

の要求なんだけど、関数saikoroの定義がおかしい。
ここも最後に

> return(0);

となってるけど、「関数が全部return(0)で終わる」ワケではない。これやっちゃうとどんな計算しようとも「0を返す」ので計算が無駄になっちゃう。main関数でのreturn(0)と意味が違うので、returnの通常での使い方を知ってください。
ここは、

return rand()%6+1;

が正しい。計算結果をそのまま返してください。じゃないと他の関数(この場合はsysjan)で結果を受け取れない。そして、ここでも変数saiは全く必要ないです。

C言語だと・・・結構な確率で「何でもかんでも変数用意して代入する」と言うような形式薦める本とか、まぁ、そういう「書法」を推薦する場合が多いと思うんですが、必要ない場合はやらんで良いです。main関数内でも

> int sai;

して

> sai = saikoro();

とかしてるけど、ぶっちゃけ、

sysken = sysjan(saikoro());

しちゃって大丈夫です。これならsaikoroの返り値がsysjanの引数になって、そしてsysjanの返り値がsyskenに代入されてる、って一発で分かります。
変数は「使い回しをする」前提で必要になるもので、一回こっきりしか使わない(この場合、変数saiが登場するのはここだけ、です)場合はわざわざ変数を用意する必要はないです。むしろ関数に関数の結果をそのまま手渡した方がコード上は明解だと思います・・・・まぁ、人によってはそう感じないかもしれませんがね。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
少し修正を加えて上手いこといきました。
グーを3回連続で出してくることはありますが、ちゃんと他の手も出すようになりました。

お礼日時:2021/05/02 19:33

int saikoro(void) {


int sai;
srand((unsigned)time(NULL));
sai =rand()%6+1;
return(0);
}

の、returnしている 0 は、一体何を意味しているのか、考えましょう。
あなたが書いたのですよね?何のつもりで書いたかを思い出しましょう。
そもそもsaikoroという関数の機能はどういうつもりだったのでしょうか?思い出しましょう。

関数sysjanも同様。

全く別のレベルの話として、
srand((unsigned)time(NULL));
は、プログラムの最初で一度だけ実行します。mainの先頭に移動しましょう。
    • good
    • 0

> int saikoro(void) {


> int sai;
> srand((unsigned)time(NULL));
> sai =rand()%6+1;
> return(0);
> }

最後にreturn(0);で、必ず0を返すようになっている。
return(sai);
とすべき。

> JPON sysjan(int sai)
> {
> int pon;
>
> switch (sai) {
> case 1: pon = Gu; break;
> case 2: pon = Gu; break;
> case 3: pon = Choki; break;
> case 4: pon = Choki; break;
> case 5: pon = Pa; break;
> case 6: pon = Pa; break;
> }
>
> return ((JPON)0);
> }

ここも最後にreturn ((JPON)0);で、必ず0を返すようになっている。
    • good
    • 0

> C26812 列挙型 'janken' は対象範囲外です。

'enum' (Enum.3) より 'enum class' を優先します。
> C6001 初期化されていないメモリ 'shoubukekka' を使用しています。 Project2
> C6031 戻り値が無視されました: 'scanf' Project2

原因を追究し警告が出ないよう処置しましょう。


> やはりこの警告のせいでグーしか出してくれないのでしょうか?

わかりません。
まず、グー、チョキ、パーを決める処理アルゴリズムは現状どうなっていて、それが適切な方法であるかどうかの判断があるでしょう。
次に、それが適切な方法である場合、アルゴリズム通りのソースコートになっておるかどうかの解析があるでしょう。

で。
それを設計・製造をされたご自身で行ってみられてのご質問なのかどうか・・・があります。

参考まで。
    • good
    • 0

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