知り合いがポーカー作ると勉強になるよ、教えてくれたのでポーカーのプログラムを作っています。
とりあえずジョーカーなし、交換なしでカードが出て、役を判定させるプログラムを作ったのですがうまく動作しません。(役を判定させるif文の中に入りません)
以下そのプログラムですが、プログラムを記載する前に注意点としていくつか述べておくと
①現状すべてmain関数の中に書いています。
(あとあと全体像ができてきたら、役を判定させる関数などは外部関数にする予定です。いまはとりあえず頭から書いています)
②長いプログラムを全部ここに乗せるのもあれなので、ワンペアの部分だけ取り出しています。
③カード5種類をp[j]=rand()%52としていますが、これだとカードがかぶるおそれがあるので、もしかぶった場合はやり直し、というプログラムを組んでいます。ただ、無限にやり直しをしてしまうと、プログラムが先に進まないので、2000回繰り返した場合(2000回連続で5種類のカードのうちいずれかが被った場合)自動的にプログラムが終了するようにしています。5種類取り出した場合、1回の試行で約0.18くらいの確率で数字がかぶってしまうので、2000回連続で数字がかぶる確率は(0.0324)^1000となりはほぼ0になるので、とりあえずはこれで放置しています。(計算は概算です。有効数字とか考えてないので、実際は結構異なると思います)以下プログラムです。
④役の判定は、カードを小さい順にソートをして、隣り合う数字をもとに判定しています。
---------------------
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef struct Poker{
int card[52];
char mark[52];
}Poker;
int main(void){
Poker num;
int i=0; //for文用
int j=0; //for文用
int k=0; //for文用
int l=0; //for文用
int m=0; //for文用
int n=0; //for文用
int tmp; //配列ソート用
int p[5]; //カード選択用
int max=1; //error防止用
int yaku=0; //カードの役ループ用
srand((unsigned)time(NULL));
for(i=0;i<13;i++){
num.card=i+1;
num.card[i+13]=i+1;
num.card[i+26]=i+1;
num.card[i+39]=i+1;
num.mark='s';
num.mark[i+13]='d';
num.mark[i+26]='h';
num.mark[i+39]='c';
}
for(j=0;j<5;j++){
p[j]=rand()%52;
max++; //for文無限回繰り返しを防ぐ
if(j==4){
if(p[0]==p[1]||p[0]==p[2]||p[0]==p[3]||p[0]==p[4]||p[1]==p[2]||p[1]==p[3]||p[1]==p[4]||p[2]==p[3]||p[2]==p[4]||p[3]==p[4]){
j=-1;//同じカードかあれば、j=0となりやりなおし(j=-1なのはループの最後にj++があるから)
}
}
if(max==10000)
break;
}
if(max!=10000){
for(k=0;k<5;k++){
printf("%c-%d\n",num.mark[p[k]],num.card[p[k]]);
}
for(l=0;l<4;l++){ //カードのソート
for(m=l;m<5;m++){
if((p[m]%13)<=(p[[/url]%13)){
tmp=p[m];
p[m]=p[[/url];
p[[/url]=tmp;
}
}
}//カードのソートを終了
if((yaku=0)&&(((p[0]%13)==(p[1]%13))||((p[1]%13)==(p[2]%13))||((p[2]%13)==(p[3]%13))||((p[3]%13)==(p[4]%13)))){
yaku=1;
printf("ワンペア\n");
}//ワンペア
} //if(max!=10000の終了)
return 0;
}
------------------------
質問としては
①なぜif文の中に入らないのか?
(あるいは入ってはいるが条件式などに誤りがある)
②はじめにカードを5種類だす際に、もっとうまいプログラムはないのか?(上のプログラムは無限ループを防止するための苦肉の策なので)
③5種類のカードがの中に同じものが含まれることが、そもそもずっと続くなどありえない(確率的にはありえるが、0に収束するので)無限ループを防止するプログラムなど書く必要がない?
他のプログラム等は全く見ないで挑戦していて、かなりへたくそなプログラムだとは思いますが、いろいろと教えてもらえるとうれしいです。
よろしくお願いいたします。
ポーカーで質問です。
Re:ポーカーで質問です。
if ((yaku=0)&& ... ){ yaku=1; printf("ワンペア\n"); }//ワンペア丁寧に見てないですが、これでは永久に無理でしょう。
もしかしてyaku == 0ではないですか?
初心者がこれに自分で気付くには、「デバッグ」という事をすると良いかもしれません。
Re:ポーカーで質問です。
安価ミスですね、もっと注意深くコードを見ることと
もう少し見やすいコードを意識するといいですよ
とりあえず間違いの指摘をば
if((yaku=0)&&...
となっていますが、
yaku=0
だと”yaku”に”0”を代入する結果になりますね。
if((yaku==0)&&...
にすればif文は動き出すと思います、他に問題がなければのお話ですけどね。
もう少し見やすいコードを意識するといいですよ
とりあえず間違いの指摘をば
if((yaku=0)&&...
となっていますが、
yaku=0
だと”yaku”に”0”を代入する結果になりますね。
if((yaku==0)&&...
にすればif文は動き出すと思います、他に問題がなければのお話ですけどね。
Re:ポーカーで質問です。
そうですね。直すとうまく動作しました。
こんなことで質問するのは情けない……
回答をしてくださったお二方、ありがとうございました。
5種類のカードを最初に出すところも、もっとうまいプログラミング法があればご教授よろしくお願いいたします。
こんなことで質問するのは情けない……
回答をしてくださったお二方、ありがとうございました。
5種類のカードを最初に出すところも、もっとうまいプログラミング法があればご教授よろしくお願いいたします。
Re:ポーカーで質問です。
カードのシャッフルは文字通りシャッフルアルゴリズムを使えばいいですよ
0-51まで連続した配列を用意して乱数で2つの数値を取得
その2つの数値をインデックスとする配列の中身を入れ替える
以上の操作を何回か繰り返す
何回繰り返すのが適当かがわからないのですが100回もやればいいでしょう
配列の最初の5個を取り出して終わり
0-51まで連続した配列を用意して乱数で2つの数値を取得
その2つの数値をインデックスとする配列の中身を入れ替える
以上の操作を何回か繰り返す
何回繰り返すのが適当かがわからないのですが100回もやればいいでしょう
配列の最初の5個を取り出して終わり