カードの山配列deck
から何枚か人間の手札に移動しよう。
手札用の構造体 human
を宣言し、そこに5枚の山札を
移動する。
Cards deck, human;
int i;
initialize(&deck);
shuffle(&deck);
/* 人間に5枚配る */
for (human.n=0; human.n<5; human.n++) {
memcpy(&human.card[human.n], &deck.card[--deck.n], sizeof (aCard));
}
--deck.n
とすることにより、山に残っているカードの
カウントが1ずつ減って行く。
ここまでの関数をまとめて、配った5枚のカードを表示する だけのプログラムを作ってみる。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CARDS 52 /* 難しいのでジョーカー抜き */
typedef struct { /* 1枚のカードの構造体 */
char *suit; /* スート */
int number; /* 数字 */
char *name; /* 読み名 */
} aCard;
typedef struct { /* 山、手札などカードの集合体 */
aCard card[CARDS]; /* 単一カードが52枚 */
int n; /* 今何枚あるか */
} Cards;
void initialize(Cards *d) /* Cards構造体のポインタ */
{
static char *suits[] = {
"ハート", "スペード", "ダイヤ", "クラブ", "ジョーカー"
};
static char *numbers[] = {
"JOKER", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"J", "Q", "K"
}; /* ここまでは initcard2 と同じ*/
int s, n, i;
for (i=0; i<CARDS; i++) {
s = i/13; /* 13で割ると切捨て */
n = i%13 + 1; /* 13で割った余り+1 */
/* d->card がaCard構造体の配列メンバになる。
d->cardは配列なのでd->card[x] でアクセスする。 */
d->card[i].suit=suits[s];
d->card[i].number = n;
d->card[i].name = numbers[n];
}
d->n = 52; /* この山が持っている枚数をセット */
}
void shuffle(Cards *d)
{
int i, pair;
aCard work;
int length=d->n;
srandom(time(NULL));
for (i=0; i<length; i++) {
pair = random()%length; /* 交換相手の決定 */
memcpy(&work, &d->card[i], sizeof work);
memcpy(&d->card[i], &d->card[pair], sizeof work);
memcpy(&d->card[pair], &work, sizeof work);
}
}
void dispcard(aCard c)
{
printf("%sの%s\n", c.suit, c.name);
}
int main(int argc, char *argv[])
{
Cards deck, human;
int i;
initialize(&deck);
shuffle(&deck);
/* 人間に5枚配る */
for (human.n=0; human.n<5; human.n++) {
memcpy(&human.card[human.n], &deck.card[--deck.n], sizeof (aCard));
}
puts("あなたの手は");
for (i=0; i<human.n; i++) {
dispcard(human.card[i]);
}
}
配られた5枚のカードを役判定する。ポーカーの役は以下の通り。
役なし
1組だけ数の同じカードが2枚ある
2組数の同じカードが2枚ずつある
1組数の同じカードが3枚ある
スートが揃ってない状態の連続した5つの数になっている(K の次は A につながる)
5枚とも同じスート
スリーカードとワンペアが同時にある組み合わせ
同じ数のカードが4枚ある
フラッシュとストレートが同時にある組み合わせ
10, J, Q, K, A でできたストレートフラッシュ
役を構成している数やスートも強さの基準となることがあるが、最初は 気にしないことにする。
5枚の手札の組み合わせから役を判定するには、それぞれの役を判定する
関数を作成し、役に一致する場合には1、そうでない場合には0を返すようにする。
各判定関数を is_役名()
という名前の関数にし、
int is_royalStraightFlush(Cards *c) { .... }
int is_straightFlush(Cards *c) { .... }
int is_fourCards(Cards *c) { .... }
int is_fullHouse(Cards *c) { .... }
int is_flush(Cards *c) { .... }
int is_straight(Cards *c) { .... }
int is_threeCards(Cards *c) { .... }
int is_twoPairs(Cards *c) { .... }
int is_onePair(Cards *c) { .... }
とそれぞれ作っておく。それを利用して役判定をする部分を作る。
int check(Cards *c)
....
if (is_royalStraightFlush(c)) {
printf("ロイヤルストレートフラッシュです\n");
} else if (is_straightFlush(c)) {
printf("ストレートフラッシュです\n");
} else if (is_fourCards(c)) {
printf("フォーカードです\n");
} else if (is_fullHouse(c)) {
printf("フルハウスです\n");
} else if (is_flush(c)) {
printf("フラッシュです\n");
} else if (is_straight(c)) {
printf("ストレートです\n");
} else if (is_threeCards(c)) {
printf("スリーカードです\n");
} else if (is_twoPairs(c)) {
printf("ツーペアです\n");
} else if (is_onePair(c)) {
printf("ワンペアです\n");
} else {
printf("ハイカードです\n");
}
if
の条件部分では、0以外の値を取るものが「真」になるので、
役判定関数のうち初めて0以外を返した役の名前が表示される。
ワンペアを判定する関数を作ってみよう。カードの「数」の部分だけを 調べて、その「数」の登場回数を数えるようにする。登場回数が1以上のものが 4種類あればワンペアである。
int is_onePair(Cards *c)
{
int box[14]; /* 該当番号が何個あるかの配列 */
int i, j;
int sum=0; /* 1枚以上のカードが何種類? */
for (i=1; i<=13; i++) {/* 全て0に初期化 box[0] は使わない */
box[i] = 0;
}
for (j=0; j<c->n; j++) { /* Count each number */
/* c->card[j] が手持の5枚目のカードの構造体 */
/* c->card[j].number は、その数字 */
box[c->card[j].number]++;
}
for (i=1; i<=13; i++) { /* A〜Kまでのboxを調べる */
if (box[i]>0) /* 1以上のものがあれば sum を1増やす */
sum++;
}
if (sum == 4)
return 1;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CARDS 52 /* 難しいのでジョーカー抜き */
typedef struct { /* 1枚のカードの構造体 */
char *suit; /* スート */
int number; /* 数字 */
char *name; /* 読み名 */
} aCard;
typedef struct { /* 山、手札などカードの集合体 */
aCard card[CARDS]; /* 単一カードが52枚 */
int n; /* 今何枚あるか */
} Cards;
char *hand[] = { /* 役の名前の配列 */
"ハイカード",
"ワンペア",
"ツーペア",
"スリーカード",
"ストレート",
"フラッシュ",
"フルハウス",
"フォーカード",
"ストレートフラッシュ",
"ロイヤルストレートフラッシュ",
};
void initialize(Cards *d) /* Cards構造体のポインタ */
{
static char *suits[] = {
"ハート", "スペード", "ダイヤ", "クラブ", "ジョーカー"
};
static char *numbers[] = {
"JOKER", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"J", "Q", "K"
}; /* ここまでは initcard2 と同じ*/
int s, n, i;
for (i=0; i<CARDS; i++) {
s = i/13; /* 13で割ると切捨て */
n = i%13 + 1; /* 13で割った余り+1 */
/* d->card がaCard構造体の配列メンバになる。
d->cardは配列なのでd->card[x] でアクセスする。 */
d->card[i].suit=suits[s];
d->card[i].number = n;
d->card[i].name = numbers[n];
}
d->n = 52; /* この山が持っている枚数をセット */
}
void shuffle(Cards *d)
{
int i, pair;
int length=d->n;
aCard work;
srandom(time(NULL));
for (i=0; i<length; i++) {
pair = random()%length; /* 交換相手の決定 */
memcpy(&work, &d->card[i], sizeof work);
memcpy(&d->card[i], &d->card[pair], sizeof work);
memcpy(&d->card[pair], &work, sizeof work);
}
}
void dispcard(aCard c)
{
printf("%sの%s\n", c.suit, c.name);
}
int is_royalStraightFlush(Cards *c) { return 0; }
int is_straightFlush(Cards *c) { return 0; }
int is_fourCards(Cards *c) { return 0; }
int is_fullHouse(Cards *c) { return 0; }
int is_flush(Cards *c) { return 0; }
int is_straight(Cards *c) { return 0; }
int is_threeCards(Cards *c) { return 0; }
int is_twoPairs(Cards *c) { return 0; }
int is_onePair(Cards *c)
{
int box[14]; /* 該当番号が何個あるかの配列 */
int i, j;
int sum=0; /* 1枚以上のカードが何種類? */
for (i=1; i<=13; i++) {/* 全て0に初期化 box[0] は使わない */
box[i] = 0;
}
for (j=0; j<c->n; j++) { /* Count each number */
/* c->card[j] が手持の5枚目のカードの構造体 */
/* c->card[j].number は、その数字 */
box[c->card[j].number]++;
}
for (i=1; i<=13; i++) {
if (box[i]>0)
sum++;
}
printf("sum=%d\n", sum);
if (sum == 4)
return 1;
return 0;
}
int judge(Cards *c)
{
if (is_royalStraightFlush(c)) {
printf("ロイヤルストレートフラッシュです\n");
} else if (is_straightFlush(c)) {
printf("ストレートフラッシュです\n");
} else if (is_fourCards(c)) {
printf("フォーカードです\n");
} else if (is_fullHouse(c)) {
printf("フルハウスです\n");
} else if (is_flush(c)) {
printf("フラッシュです\n");
} else if (is_straight(c)) {
printf("ストレートです\n");
} else if (is_threeCards(c)) {
printf("スリーカードです\n");
} else if (is_twoPairs(c)) {
printf("ツーペアです\n");
} else if (is_onePair(c)) {
printf("ワンペアです\n");
} else {
printf("ハイカードです\n");
}
}
int main(int argc, char *argv[])
{
Cards deck, human, com;
int i;
initialize(&deck);
shuffle(&deck);
/* 人間に5枚配る */
for (human.n=0; human.n<5; human.n++) {
memcpy(&human.card[human.n], &deck.card[--deck.n], sizeof (aCard));
}
puts("あなたの手は");
for (i=0; i<human.n; i++) {
dispcard(human.card[i]);
}
judge(&human);
}