カードゲームを・・・

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

カードゲームを・・・

#1

投稿記事 by もんた » 17年前

始めまして、もんたです。
現在C言語の勉強をしていて、練習として自作のカードゲームを作ってみようと思っています。
そこで質問なのですが、構造体を使ってカードの情報を記録し、それを照らし合わせて役を判定する事は可能でしょうか?

例えばトランプには数字と模様の情報があります。
それを、
struct toranpu  card1;

   strcpy(card1.name,"card1")
   card1.number = 8
   card1.moyou = heart
と、
struct toranpu  card2;

   strcpy(card2.name,"card2")
   card2.number = 5
   card2.moyou = daiya
の二つ用意します。

そしてこの二つのカードを揃えて出すと役が完成・・・という様な事は可能でしょうか?
もし可能なら、詳しいやり方を教えて頂けないでしょうか?

また、構造体で作った配列をシャッフルし、手札として割り当てる方法も教えて頂けるとありがたいのですが・・・。
(↑これは面倒なら答えて頂かなくてもかまいません。)

木霊

Re:カードゲームを・・・

#2

投稿記事 by 木霊 » 17年前

はじめまして、もんたさん
え~と、
構造体のメンバ「number」はint型ですよね
「moyou」の方もint型ならいいんですが、char型のポインタ("heart"や"daiya"が文字列ならば)なら
難しくなりそうです

自分はあまりできない方なので、もっとスマートなやり方がありそうですが、
役を全て事前に列挙しておき、if文でしらみつぶしに調べる、というのが確実でしょうか?
数字のペアだけならif ( card1.number == card2.number ) { /*ペア成立*/ } 
みたいにできますが、模様と数字が決まっていて、規則性が無いならば自分ならそうします

ちなみに例だとif ( card1.number == 8 && card1.moyou = heart && card2.number == 5 && card2.moyou == daiya ) { /*ペア成立(ただしmoyouの中身が文字列のつもりでなければ)*/ }
ですね

現段階では、役がカード2枚以上でも成立するのか、それ以外の役は?とか不確定なことが
多いので(構造体の定義も)、そのものずばりな回答は得られにくいですよ
それに、もう少し情報があると、もっとすごい人に診てもらえますw


「name」でカードに名前をつけているということは・・・最終的に「遊戯○」っぽくなる、とかはないかな?

バグ

Re:カードゲームを・・・

#3

投稿記事 by バグ » 17年前

あの書き方から察するに、moyouは列挙型じゃないですか?

kazuoni

Re:カードゲームを・・・

#4

投稿記事 by kazuoni » 17年前

構造体の配列を使用したらもっと管理しやすくなるよな気がするのですが・・・(今回はカードの種類が二種類なんで効率的かどうかわかりませんが・・・。)

バグ

Re:カードゲームを・・・

#5

投稿記事 by バグ » 17年前

主さんが提示したソースを参考にせずに、好き勝手に作ってみました(^_^;)
#include <stdlib.h>
#include <time.h>
#include <memory.h>

#define SHUFFLE		1000		/* デッキをシャッフルする回数 */

/* 構造体の定義 */
struct TRUMP
{
	int mark;		/* カードのマーク、1~4の値が格納される */
	int number;		/* カードの数字、1~13の値が格納される */
};

/* main関数 */
int main(void)
{
	/* 変数の宣言 */
	int cnt, a, b;
	TRUMP trump[52], dummy;

	/* デッキの初期化 */
	for (cnt = 0; cnt < 52; cnt++)
	{
		trump[cnt].mark = cnt / 13 + 1;
		trump[cnt].number = cnt % 13 + 1;
	}

	/* 乱数生成準備 */
	srand((unsigned)time(NULL));

	/* デッキのシャッフル */
	for (cnt = 0; cnt < SHUFFLE; cnt++)
	{
		/* aとbの2つの乱数を用意する */
		a = rand() % 52;
		b = rand() % 52;

		/* aとbの位置にある構造体変数の中身を入れ替える */
		memcpy(&dummy, &trump[a], sizeof(TRUMP));
		memcpy(&trump[a], &trump, sizeof(TRUMP));
		memcpy(&trump, &dummy, sizeof(TRUMP));
	}

	return 0;
}

kazuoni

Re:カードゲームを・・・

#6

投稿記事 by kazuoni » 17年前

>TRUMP trump[52], dummy;

struct TRUMP trump[52];
struct TRUMP dummy;

じゃありませんでしたっけっ^^;間違えてたらすみません・・・。あとついでにmemcpyの三つ目も・・間違えてたらすみません・・・

バグ

Re:カードゲームを・・・

#7

投稿記事 by バグ » 17年前

最初の件は確かにそうですが、主さんのソースを見る限りC/C++コンパイラだと思って問題ないかと考えました。
二つ目のは完全に私のミスですね。引数が逆になってます(苦笑)

フリオ

Re:カードゲームを・・・

#8

投稿記事 by フリオ » 17年前

 
 急ごしらえですが、カードを準備してプレイヤー1に配り、
残ったカードをシャッフルしてプレイヤー2に配るプログラムです。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct card_t{
			int num, suit;
		}CARD;

typedef struct stock_t{
			CARD card[52];
			int remain;
		}STOCK;

void SetStock(STOCK *stock)
{
	const char *suitch = "SCHD";
	int i;
	
	for(i = 0; i < 52; i ++){
		stock->card.num = i % 13 + 1;
		stock->card.suit = suitch[i / 13];
	}
	stock->remain = 52;
}

void Swap(CARD *a, CARD *b)
{
	CARD c = *a;
	*a = *b;
	*b = c;
}

void Shuffle(STOCK *stock)
{
	int rnd, n = stock->remain;
	
	while(n --){
		rnd = (int)((n + 1) * (rand() / (RAND_MAX + 1.0)));
		Swap(&stock->card[n], &stock->card[rnd]);
	}
}

int Deal(STOCK *stock, CARD *player, int n)
{
	int i;
	
	if(n > stock->remain) return 0;
	for(i = 0; i < n; i ++) player = stock->card[-- stock->remain];
	return 1;
}

void PrintCard(CARD *card, int n)
{
	int i;
	
	for(i = 0; i < n; i ++){
		if(card.suit) printf("[%c%2d]", card.suit, card.num);
		if(i % 13 == 12) putchar('\n');
	}
	if(i % 13) putchar('\n');
}

void Print(STOCK *stock, CARD *player1, CARD *player2)
{
	printf("\nstock %d\n", stock->remain);
	PrintCard(stock->card, stock->remain);
	printf("player1 : ");
	PrintCard(player1, 5);
	printf("player2 : ");
	PrintCard(player2, 5);
}

int main(void)
{
	STOCK stock;
	CARD player1[5] = {0}, player2[5] = {0};
	
	srand((unsigned)time(NULL));
	SetStock(&stock);
	Print(&stock, player1, player2);
	Deal(&stock, player1, 5);
	Print(&stock, player1, player2);
	Shuffle(&stock);
	Deal(&stock, player2, 5);
	Print(&stock, player1, player2);
	return 0;
}

 

もんた

Re:カードゲームを・・・

#9

投稿記事 by もんた » 17年前

おお、こんなに返信が・・・・・・皆さんありがとうございます。
特にシャッフルは細かく書いてくださって、大感謝です。
シャッフルの方はこれを応用して何とかしてみようと思います。

役についてですが、もう少し詳しい情報を・・・とあったので、もう少しカードの情報を書いておこうと思います。

①ゲームはUNOの様に、デッキからカードを引いて出すタイプ
②カードには、出すと相手を一回休みにしたりする様なものと、役を作るものの二つに分かれる
③役のカードは揃えてから出すのではなく、1ターンに最大一枚ずつ順番に出していく
④役は三枚の物を三種類作る

そして役を作るカードですが、色と数字の要素があります。
色は三種類あり、役を別の色と組み合わせる事はできません。
数字も三種類ありますが、これは出す事の出来る順番を示します。
例えば、1なら最初におくことが出来、3なら役の最後に置く事ができます。
つまり、1の赤、2の赤、3の赤、と順番に出す事になります。
ちなみに同じカードが2枚あります。


やたら長文になって申し訳ありません・・・。
色々と書いていますが、まずは3種類の役を作るプログラムを作ろうと思っています。
役に使うカード以外の事は後々考えようと思います。

やはり木霊さんの仰る通り、事前に役を列挙しておくやり方が良いのでしょうか?

木霊

Re:カードゲームを・・・

#10

投稿記事 by 木霊 » 17年前

(役に使えるカードの)色が3種類で数字も1~3だけなら一枚出されるごとに色と数字をチェックすれば
いけそうです
・・・
// ----
if ( 今出したカードが役に使えるか == false ) { goto 次の処理;}
if ( カウント != 0 ) {
    if ( ( 今出したカードの色 == 今まで出されてきたカードの色 ) &&
            ( 今出したカードの数字 > 前回出したカードの数字 ) ) {
        カウント ++;
        前回出したカードの数字 = 今出したカードの数字;
    } else {
        カウント = 0;
        今まで出されてきたカードの色 = 今出したカードの色;
        前回出したカードの数字 = 今出したカードの数字;
    }
} else {
    カウント = 1;
    今まで出されてきたカードの色 = 今出したカードの色;
    前回出したカードの数字 = 今出したカードの数字;
}
if ( カウント == 3 ) { /*役成立の処理へ*/ }
// ----
次の処理:// goto文のラベル
・・・
こんな感じで考えてみました、数字の上限が3以上に変更になった時も一応対応できます
(日本語部分は自分のプログラムに合わせて置き換えて見てください)
if文の入れ子が多くなるのであえてgotoを使ってますが関数化(//----の範囲)する時にはreturn文に
置き換えて下さい


> バグさん

#defineかenumとは思ったんですが、昔の自分が一度やってしまった間違いだったので・・・

もんた

Re:カードゲームを・・・

#11

投稿記事 by もんた » 17年前

おお・・・ありがとうございます。
これで何とか基本部分は作れそうです。
答えてくださった皆様、本当にありがとうございました。

閉鎖

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