ポーカーの最後の章です。
8.カードを変更する
関数名 ChangeCard 戻り値 なし 引 数 デッキ、手札 機 能 手札のフラグが立っているカードのみ デッキの5枚目から必要枚数分配る |
void ChangeCard(const Card deck[CARD_NUM], Card hand[HAND_NUM]) { int i; int dealCount; dealCount = HAND_NUM; for (i = 0; i < HAND_NUM; i++) { if (hand[i].selectFlag == 1) { hand[i] = deck[dealCount]; dealCount++; } } } |
選択フラグが立っているカードのみ変更します。
カードの変更後、ソートして表示しますので、そこまで作りましょう。
<sample program 145-01>
int main(void)
{
Card deck[CARD_NUM];
Card hand[HAND_NUM];
srand((unsigned int)time(NULL));
/* デッキの初期化 */
InitializeDeck(deck);
/* デッキのシャッフル */
ShuffleDeck(deck);
/* 手札を配る */
DealCard(deck, hand);
/* 手札をソートする */
SortHand(hand);
/* 手札を表示する */
ShowHand(hand);
/* 変更するカードを選択する */
SelectCard(hand);
/* カードを変更する */
ChangeCard(deck, hand);
/* 手札をソートする */
SortHand(hand);
/* 手札を表示する */
ShowHand(hand);
return 0;
}
|
<実行結果>
ダ イ ヤ: 4 スペード: 5 ハ ー ト:10 ク ラ ブ:12 ク ラ ブ:13 0 ダ イ ヤ: 4 * スペード: 5 ハ ー ト:10 ク ラ ブ:12 ク ラ ブ:13 1 ダ イ ヤ: 4 * スペード: 5 * ハ ー ト:10 ク ラ ブ:12 ク ラ ブ:13 5 ハ ー ト: 3 スペード:10 ハ ー ト:10 ク ラ ブ:12 ク ラ ブ:13 続行するには何かキーを押してください・・・
11.手役を判定して表示する
関数名 Result 戻り値 なし 引 数 手札 機 能 手役を判定し表示する |
void Result(const Card hand[HAND_NUM]) { int i; int flushFlag; int straightFlag; if (hand[0].number == hand[1].number && hand[1].number == hand[2].number && hand[2].number == hand[3].number) { printf("フォーカード\n"); return; } if (hand[1].number == hand[2].number && hand[2].number == hand[3].number && hand[3].number == hand[4].number) { printf("フォーカード\n"); return; } if (hand[0].number == hand[1].number && hand[1].number == hand[2].number) { if (hand[3].number == hand[4].number) { printf("フルハウス\n"); } else { printf("スリーカード\n"); } return; } if (hand[1].number == hand[2].number && hand[2].number == hand[3].number) { printf("スリーカード\n"); return; } if (hand[2].number == hand[3].number && hand[3].number == hand[4].number) { if (hand[0].number == hand[1].number) { printf("フルハウス\n"); } else { printf("スリーカード\n"); } return; } if (hand[0].number == hand[1].number && hand[2].number == hand[3].number) { printf("ツーペア\n"); return; } if (hand[0].number == hand[1].number && hand[3].number == hand[4].number) { printf("ツーペア\n"); return; } if (hand[1].number == hand[2].number && hand[3].number == hand[4].number) { printf("ツーペア\n"); return; } if (hand[0].number == hand[1].number || hand[1].number == hand[2].number || hand[2].number == hand[3].number || hand[3].number == hand[4].number) { printf("ワンペア\n"); return; } flushFlag = 1; for (i = 0; i < HAND_NUM - 1; i++) { if (hand[i].suit != hand[i + 1].suit) { flushFlag = 0; break; } } straightFlag = 1; for (i = 0; i < HAND_NUM - 1; i++) { if (hand[i + 1].number - hand[i].number != 1) { straightFlag = 0; break; } } if (flushFlag == 1 && straightFlag == 1) { printf("ストレートフラッシュ\n"); return; } if (flushFlag == 1) { printf("フラッシュ\n"); return; } if (straightFlag == 1) { printf("ストレート\n"); return; } printf("ノーペア\n"); } |
以前作った際には、役の判定後に次の役の判定を行わないようにするため、無限ループを作りbreakさせる方法で作りました。
今回は関数に分割したため、別の方法を取っています。
戻り値が無い(void)ように設定されていますが、return文を使うことにより、関数の途中で元のプログラムへ戻ることが可能です。
return文が実行されることにより、その時点で関数は終了します。
これで完成ですので、全てのプログラムを書いておきます。
<sample program 145-02>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUMBER 13
#define MARK 4
#define CARD_NUM (NUMBER * MARK)
#define SHUFFLE_TIME 2000
#define HAND_NUM 5
/* カード構造体 */
typedef struct
{
int number;
int suit;
int selectFlag;
} Card;
void InitializeDeck(Card deck[CARD_NUM]);
void ShuffleDeck(Card deck[CARD_NUM]);
void DealCard(const Card deck[CARD_NUM], Card hand[HAND_NUM]);
void SortHand(Card hand[HAND_NUM]);
void ShowHand(const Card hand[HAND_NUM]);
void SelectCard(Card hand[HAND_NUM]);
void ChangeCard(const Card deck[CARD_NUM], Card hand[HAND_NUM]);
void Result(const Card hand[HAND_NUM]);
int main(void)
{
Card deck[CARD_NUM];
Card hand[HAND_NUM];
srand((unsigned int)time(NULL));
/* デッキの初期化 */
InitializeDeck(deck);
/* デッキのシャッフル */
ShuffleDeck(deck);
/* 手札を配る */
DealCard(deck, hand);
/* 手札をソートする */
SortHand(hand);
/* 手札を表示する */
ShowHand(hand);
/* 変更するカードを選択する */
SelectCard(hand);
/* カードを変更する */
ChangeCard(deck, hand);
/* 手札をソートする */
SortHand(hand);
/* 手札を表示する */
ShowHand(hand);
/* 手役を判定して表示する */
Result(hand);
return 0;
}
void InitializeDeck(Card deck[CARD_NUM])
{
int i;
for (i = 0; i < CARD_NUM; i++) {
deck[i].suit = i / NUMBER;
deck[i].number = i % NUMBER + 1;
deck[i].selectFlag = 0;
}
}
void ShuffleDeck(Card deck[CARD_NUM])
{
int i;
int index1, index2;
Card work;
for (i = 0; i < SHUFFLE_TIME; i++) {
index1 = rand() % CARD_NUM;
index2 = rand() % CARD_NUM;
work = deck[index1];
deck[index1] = deck[index2];
deck[index2] = work;
}
}
void DealCard(const Card deck[CARD_NUM], Card hand[HAND_NUM])
{
int i;
for (i = 0; i < HAND_NUM; i++) {
hand[i] = deck[i];
}
}
void SortHand(Card hand[HAND_NUM])
{
int i;
int j;
Card work;
for (i = 0; i < HAND_NUM - 1; i++) {
for (j = 0; j < HAND_NUM - 1; j++) {
if (hand[j].number > hand[j + 1].number) {
work = hand[j];
hand[j] = hand[j + 1];
hand[j + 1] = work;
}
}
}
}
void ShowHand(const Card hand[HAND_NUM])
{
int i;
for (i = 0; i < HAND_NUM; i++) {
switch (hand[i].suit) {
case 0:
printf("スペード:");
break;
case 1:
printf("ハ ー ト:");
break;
case 2:
printf("ダ イ ヤ:");
break;
case 3:
printf("ク ラ ブ:");
break;
}
printf("%2d", hand[i].number);
if (hand[i].selectFlag == 1) {
printf(" *\n");
}
else {
printf("\n");
}
}
}
void SelectCard(Card hand[HAND_NUM])
{
int select;
for (;;) {
do {
scanf("%d", &select);
} while (select < 0 || select > HAND_NUM);
if (select == HAND_NUM) {
break;
}
if (hand[select].selectFlag == 0) {
hand[select].selectFlag = 1;
}
else {
hand[select].selectFlag = 0;
}
/* 手札を表示する */
ShowHand(hand);
}
}
void ChangeCard(const Card deck[CARD_NUM], Card hand[HAND_NUM])
{
int i;
int dealCount;
dealCount = HAND_NUM;
for (i = 0; i < HAND_NUM; i++) {
if (hand[i].selectFlag == 1) {
hand[i] = deck[dealCount];
dealCount++;
}
}
}
void Result(const Card hand[HAND_NUM])
{
int i;
int flushFlag;
int straightFlag;
if (hand[0].number == hand[1].number &&
hand[1].number == hand[2].number &&
hand[2].number == hand[3].number) {
printf("フォーカード\n");
return;
}
if (hand[1].number == hand[2].number &&
hand[2].number == hand[3].number &&
hand[3].number == hand[4].number) {
printf("フォーカード\n");
return;
}
if (hand[0].number == hand[1].number &&
hand[1].number == hand[2].number) {
if (hand[3].number == hand[4].number) {
printf("フルハウス\n");
}
else {
printf("スリーカード\n");
}
return;
}
if (hand[1].number == hand[2].number &&
hand[2].number == hand[3].number) {
printf("スリーカード\n");
return;
}
if (hand[2].number == hand[3].number &&
hand[3].number == hand[4].number) {
if (hand[0].number == hand[1].number) {
printf("フルハウス\n");
}
else {
printf("スリーカード\n");
}
return;
}
if (hand[0].number == hand[1].number &&
hand[2].number == hand[3].number) {
printf("ツーペア\n");
return;
}
if (hand[0].number == hand[1].number &&
hand[3].number == hand[4].number) {
printf("ツーペア\n");
return;
}
if (hand[1].number == hand[2].number &&
hand[3].number == hand[4].number) {
printf("ツーペア\n");
return;
}
if (hand[0].number == hand[1].number ||
hand[1].number == hand[2].number ||
hand[2].number == hand[3].number ||
hand[3].number == hand[4].number) {
printf("ワンペア\n");
return;
}
flushFlag = 1;
for (i = 0; i < HAND_NUM - 1; i++) {
if (hand[i].suit != hand[i + 1].suit) {
flushFlag = 0;
break;
}
}
straightFlag = 1;
for (i = 0; i < HAND_NUM - 1; i++) {
if (hand[i + 1].number - hand[i].number != 1) {
straightFlag = 0;
break;
}
}
if (flushFlag == 1 && straightFlag == 1) {
printf("ストレートフラッシュ\n");
return;
}
if (flushFlag == 1) {
printf("フラッシュ\n");
return;
}
if (straightFlag == 1) {
printf("ストレート\n");
return;
}
printf("ノーペア\n");
}
|
<実行結果>
ク ラ ブ: 2 ダ イ ヤ: 3 スペード: 7 ハ ー ト: 8 ハ ー ト: 9 0 ク ラ ブ: 2 * ダ イ ヤ: 3 スペード: 7 ハ ー ト: 8 ハ ー ト: 9 1 ク ラ ブ: 2 * ダ イ ヤ: 3 * スペード: 7 ハ ー ト: 8 ハ ー ト: 9 2 ク ラ ブ: 2 * ダ イ ヤ: 3 * スペード: 7 * ハ ー ト: 8 ハ ー ト: 9 5 ダ イ ヤ: 7 ハ ー ト: 8 スペード: 9 ダ イ ヤ: 9 ハ ー ト: 9 スリーカード 続行するには何かキーを押してください・・・
完成しました。
関数にすることで、ソートや表示など、何度も実行しなければならないプログラムを1つにまとめることが出来ました。
main関数を見ると、きちんとプログラムの流れが分かります。
今は1つのcppファイルにプログラムを打ち込んでいますが、複数のメンバーで開発を行う場合には、別々のファイルに関数を作成し、後でつなげるということをやります。
まだファイル分割の説明は先になりますが、自分でプログラムを作る時には関数に分割することを意識して作るようにしてください。