俺々フレームワーク。カードデッキ&トランプ。


先日のトランプフレームワークをカードデッキフレームワークとして独立することで、
基本的なカードデッキの動作を提供。
カードデッキフレームワークをベースにトランプとしてパックすることで
トランプデッキ動作を提供する。
といった作りになってます。


データ構造にトランプならではの項目が増えることもなかったので
継承を実装するまでもなく、パック関数化するだけで済みました。


インスタンス生成が Deck でなく Trump となってて
あたかも独自のデータ構造かと思わせてますが typedef で単純に Deck 構造体ポインタの型名を増やしただけです。
Trump のみの利用者には Trump のみ見せるというのを提供するが為の記述です。

typedef struct _Deck *Trump;


Deck framework, and
Trump framework test


サンプル一式またはライブラリ&フレームワーク一式は以下のサイトよりダウンロードできます。
http://page.freett.com/ntr/


ソース(フレームワーク部、テストプログラム部のみ)。


main.c

/*---------------------------------------------------------------------------------
	
	Deck framework, and
	 Trump framework test
	
	version 0.01
	May 16, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <nds.h>
#include "libmy/Random.h"
#include "fwmy/Trump.h"


#define SHUFFLE_NUM 100


const char suit[] = {
	0x05, //club
	0x04, //diamond
	0x03, //heart
	0x06  //spade
};

const char *rank[] = {"A ", "2 ", "3 ", "4 ", "5 ", "6 ", "7 ", "8 ", "9 ", "10", "J ", "Q ", "K "};


int card_num[TRUMP_MAX + 1], card_index;
PrintConsole top_cons, bottom_cons;


void clearValue(void);
void drawDeck(Trump trump);


//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
	
	//initVideoMode
	videoSetMode(MODE_0_2D);
	videoSetModeSub(MODE_0_2D);
	
	//initVRAMBank
	vramSetBankA(VRAM_A_MAIN_BG);
	vramSetBankC(VRAM_C_SUB_BG);
	
	//initConsole
	top_cons = *consoleInit(0, 0, BgType_Text4bpp, BgSize_T_256x256, 0, 1, true, true);
	bottom_cons = *consoleInit(0, 0, BgType_Text4bpp, BgSize_T_256x256, 0, 1, false, true);
	
	//initKeysDownRepeat
	u32 kdr;
	keysSetRepeat(6, 3);
	
	consoleSelect(&bottom_cons);
	printf("Deck framework, and\n Trump framework test\n\nversion 0.01\nMay 16, 2010\n\nBy REGEKATSU\n\n\n");
	
	consoleSelect(&top_cons);
	printf("\x01b[18;0Husage:\n"
		"KEY_A: GetCard, KEY_B: SetCard\n"
		"KEY_Y: ReqCard, KEY_X: ShfDeck\n"
		"KEY_ST:ClrDeck, KEY_SL:DstDeck\n"
	);
	
	//CreateDeck
	Trump trump = Trump_Create();
	
	Random random = Random_Create(GENERATOR_LCGS);
	clearValue();
	
	while(1){
		
		swiWaitForVBlank();
		scanKeys();
		kdr = keysDownRepeat();
		
		
		//GetCardNumber, GetCardUse & drawDeck
		drawDeck(trump);
		
		//GetCard
		if(kdr & KEY_A){
			
			if(card_index < TRUMP_MAX){
				
				card_num[card_index] = Trump_GetCard(trump);
				consoleSelect(&bottom_cons);
				printf("GetCard %c%s\n", suit[ SET_SUIT(card_num[card_index])], rank[SET_RANK(card_num[card_index])]);
				card_index++;
				
			}
			
		//SetCard
		}else if(kdr & KEY_B){
			
			if(card_index > 0){
				
				card_index--;
				Trump_SetCard(trump, card_num[card_index]);
				consoleSelect(&bottom_cons);
				printf("SetCard %c%s\n", suit[ SET_SUIT(card_num[card_index])], rank[SET_RANK(card_num[card_index])]);
				card_num[card_index] = -1;
				
			}
			
		//RequestCard
		}else if(kdr & KEY_Y){
			
			if(card_index < TRUMP_MAX){
				
				card_num[card_index] = Trump_RequestCard(trump, Random_GetValue(random) % TRUMP_MAX);
				
				if(card_num[card_index] != -1){
					consoleSelect(&bottom_cons);
					printf("RequestCard %c%s\n", suit[ SET_SUIT(card_num[card_index])], rank[SET_RANK(card_num[card_index])]);
					card_index++;
				}
				
			}
			
		//ShuffleDeck
		}else if(kdr & KEY_X){
			
			Trump_Shuffle(trump, Random_GetValue(random), SHUFFLE_NUM);
			consoleSelect(&bottom_cons);
			printf("ShuffleDeck %d\n", SHUFFLE_NUM);
			
		}
		
		//ClearDeck
		if(kdr & KEY_START){
			
			Trump_Clear(trump);
			clearValue();
			consoleSelect(&bottom_cons);
			printf("ClearDeck\n");
			
		//DestroyDeck
		}else if(kdr & KEY_SELECT){
			
			trump = Trump_Destroy(trump);
			random = Random_Destroy(random);
			consoleSelect(&bottom_cons);
			printf("DestroyDeck & exit\n");
			return 0;
			
		}
		
	}
	
}

//---------------------------------------------------------------------------------
void clearValue(void) {
//---------------------------------------------------------------------------------
	
	int i;
	for(i = 0;i < TRUMP_MAX + 1;i++){
		card_num[i] = -1;
	}
	card_index = 0;
	
}

//---------------------------------------------------------------------------------
void drawDeck(Trump trump) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return;
	
	consoleSelect(&top_cons);
	printf("\x01b[0;0HdrawDeck\n");
	
	int i, j;
	int card_num[4], card_use[4];
	
	for(i = 0;i < 13;i++){
		
		for(j = 0;j < 4;j++){
			card_num[j] = Trump_GetCardNumber(trump, i + (j * 13));
			card_use[j]  = (int)Trump_GetCardUse(trump, i + (j * 13));
		}
		
		printf("\x01b[%d;0H %c%s,%01d %c%s,%01d %c%s,%01d %c%s,%01d\n", 2 + i, 
			
			suit[ SET_SUIT(card_num[0]) ], rank[ SET_RANK(card_num[0]) ], card_use[0], 
			suit[ SET_SUIT(card_num[1]) ], rank[ SET_RANK(card_num[1]) ], card_use[1], 
			suit[ SET_SUIT(card_num[2]) ], rank[ SET_RANK(card_num[2]) ], card_use[2], 
			suit[ SET_SUIT(card_num[3]) ], rank[ SET_RANK(card_num[3]) ], card_use[3]
			
		);
		
	}
	
	printf("\nRemain %02d", Trump_GetCardRemain(trump));
	
}

//---------------------------------------------------------------------------------


Trump.h

/*---------------------------------------------------------------------------------
	
	Trump framework header
	
	version 0.01
	May 16, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _TRUMP_H_
#define _TRUMP_H_


#define RANK_NUM 13
#define SUIT_NUM 4
//#define JOKER_NUM 2
#define TRUMP_MAX (RANK_NUM * SUIT_NUM /* + JOKER_NUM */ )


#define SET_SUIT(n) ((n) / RANK_NUM)
#define SET_RANK(n) ((n) % RANK_NUM)


typedef struct _Deck *Trump;


#ifdef __cplusplus
extern "C" {
#endif


//トランプデッキを生成する。
Trump Trump_Create(void);

//トランプデッキを破棄する。
Trump Trump_Destroy(Trump trump);

//トランプデッキをクリア(初期化)する。
void Trump_Clear(Trump trump);

//トランプデッキをシャッフルする。
void Trump_Shuffle(Trump trump, int seed, int shuffle_num);

//トランプデッキにあるカード残数を返す。
int Trump_GetCardRemain(Trump trump);

//トランプデッキにあるカード情報を返す。デッキインデックスは数字が若ものほど、上にあるカードを示している。
int Trump_GetCardNumber(Trump trump, int deck_index);//カード番号
bool Trump_GetCardUse(Trump trump, int deck_index);//カード使用中の有無

//トランプデッキにある一番上のカードを取得する。デッキに1枚もカードが無い場合 -1 が返る。
int Trump_GetCard(Trump trump);

//トランプデッキにある任意のカードを取得する。カードがある場合そのカードが、使用中の場合 -1 が返る。
int Trump_RequestCard(Trump trump, int card_number);

//トランプデッキの一番下にカードを戻す。
void Trump_SetCard(Trump trump, int card_number);


#ifdef __cplusplus
}
#endif

#endif	// _TRUMP_H_


Trump.c

/*---------------------------------------------------------------------------------
	
	Trump framework routine
	
	version 0.01
	May 16, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <nds/ndstypes.h>//bool 型使用のためにインクルード。
#include "Deck.h"
#include "Trump.h"


//---------------------------------------------------------------------------------
Trump Trump_Create(void) {
//---------------------------------------------------------------------------------
	
	return Deck_Create(TRUMP_MAX);
	
}

//---------------------------------------------------------------------------------
Trump Trump_Destroy(Trump trump) {
//---------------------------------------------------------------------------------
	
	return Deck_Destroy(trump);
	
}

//---------------------------------------------------------------------------------
void Trump_Clear(Trump trump) {
//---------------------------------------------------------------------------------
	
	Deck_Clear(trump);
	
}

//---------------------------------------------------------------------------------
void Trump_Shuffle(Trump trump, int seed, int shuffle_num) {
//---------------------------------------------------------------------------------
	
	Deck_Shuffle(trump, seed, shuffle_num);
	
}

//---------------------------------------------------------------------------------
int Trump_GetCardRemain(Trump trump) {
//---------------------------------------------------------------------------------
	
	return Deck_GetCardRemain(trump);
	
}

//---------------------------------------------------------------------------------
int Trump_GetCardNumber(Trump trump, int deck_index) {
//---------------------------------------------------------------------------------
	
	return Deck_GetCardNumber(trump, deck_index);
	
}

//---------------------------------------------------------------------------------
bool Trump_GetCardUse(Trump trump, int deck_index) {
//---------------------------------------------------------------------------------
	
	return Deck_GetCardUse(trump, deck_index);
	
}

//---------------------------------------------------------------------------------
int Trump_GetCard(Trump trump) {
//---------------------------------------------------------------------------------
	
	return Deck_GetCard(trump);
	
}

//---------------------------------------------------------------------------------
int Trump_RequestCard(Trump trump, int card_number) {
//---------------------------------------------------------------------------------
	
	return Deck_RequestCard(trump, card_number);
	
}

//---------------------------------------------------------------------------------
void Trump_SetCard(Trump trump, int card_number) {
//---------------------------------------------------------------------------------
	
	Deck_SetCard(trump, card_number);
	
}

//---------------------------------------------------------------------------------


Deck.h

/*---------------------------------------------------------------------------------
	
	Deck framework header
	
	version 0.01
	May 16, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _DECK_H_
#define _DECK_H_


typedef struct _Deck *Deck;


#ifdef __cplusplus
extern "C" {
#endif


//カードデッキを生成する。引数にはデッキで使用するカード枚数を指定する。
Deck Deck_Create(int card_max);

//カードデッキを破棄する。
Deck Deck_Destroy(Deck deck);

//カードデッキをクリア(初期化)する。
void Deck_Clear(Deck deck);
	
//カードデッキをシャッフルする。
void Deck_Shuffle(Deck deck, int seed, int shuffle_num);

//カードデッキにあるカード残数を返す。
int Deck_GetCardRemain(Deck deck);

//カードデッキにあるカード情報を返す。デッキインデックスは数字が若ものほど、上にあるカードを示している。
int Deck_GetCardNumber(Deck deck, int deck_index);//カード番号
bool Deck_GetCardUse(Deck deck, int deck_index);//カード使用中の有無

//カードデッキにある一番上のカードを取得する。デッキに1枚もカードが無い場合 -1 が返る。
int Deck_GetCard(Deck deck);

//カードデッキにある任意のカードを取得する。カードがある場合そのカードが、使用中の場合 -1 が返る。
int Deck_RequestCard(Deck deck, int card_number);

//カードデッキの一番下にカードを戻す。
void Deck_SetCard(Deck deck, int card_number);


#ifdef __cplusplus
}
#endif

#endif	// _DECK_H_


Deck.c

/*---------------------------------------------------------------------------------
	
	Deck framework routine
	
	version 0.01
	May 16, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdlib.h>
#include <nds/ndstypes.h>//bool 型使用のためにインクルード。
#include "../libmy/Random.h"
#include "Deck.h"


typedef struct{
	int number;
	bool use;
}Card;

typedef struct _Deck{
	
	Card *card;
	
	int deck_index;
	int card_max;
	int card_remain;
	
	Random random;
	
}_Deck;


#define SET_DECK_INDEX(idx) (((idx) >= deck->card_max) ? idx - deck->card_max:idx)
#define PREV_DECK_INDEX(idx) (((idx) <= 0) ? deck->card_max - 1:idx - 1)
#define NEXT_DECK_INDEX(idx) (((idx) >= deck->card_max - 1) ? 0:idx + 1)

void deck_SwapCard(Card *a, Card *b);


//---------------------------------------------------------------------------------
Deck Deck_Create(int card_max) {
//---------------------------------------------------------------------------------
	
	Deck deck;
	
	deck = (Deck)malloc(sizeof(_Deck));
	deck->card_max = (card_max <= 0) ? 1 : card_max;
	deck->card = malloc(sizeof(Card) * deck->card_max);
	
	deck->random = Random_Create(GENERATOR_LCGS);
	
	Deck_Clear(deck);
	
	return deck;
	
}

//---------------------------------------------------------------------------------
Deck Deck_Destroy(Deck deck) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return NULL;
	
	deck->random = Random_Destroy(deck->random);
	free(deck->card);
	free(deck);
	
	return NULL;
	
}

//---------------------------------------------------------------------------------
void Deck_Clear(Deck deck) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return;
	
	int i;
	for(i = 0;i < deck->card_max;i++){
		deck->card[i].number = i;
		deck->card[i].use = false;
	}
	
	deck->card_remain = deck->card_max;
	deck->deck_index = 0;
	
}

//---------------------------------------------------------------------------------
void Deck_Shuffle(Deck deck, int seed, int shuffle_num) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return;
	
	int i, a, b;
	
	Random_SetSeed(deck->random, seed);
	
	for(i = 0;i < shuffle_num;i++){
		
		a = Random_GetValue(deck->random) % deck->card_max;
		b = Random_GetValue(deck->random) % deck->card_max;
		
		deck_SwapCard(&deck->card[a], &deck->card[b]);
		
	}
	
}

//---------------------------------------------------------------------------------
int Deck_GetCardRemain(Deck deck) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return -1;
	
	return deck->card_remain;
	
}

//---------------------------------------------------------------------------------
int Deck_GetCardNumber(Deck deck, int deck_index) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return -1;
	if(deck_index < 0 || deck_index >= deck->card_max) return -1;
	
	return deck->card[SET_DECK_INDEX(deck->deck_index + deck_index)].number;
	
}

//---------------------------------------------------------------------------------
bool Deck_GetCardUse(Deck deck, int deck_index) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return -1;
	if(deck_index < 0 || deck_index >= deck->card_max) return -1;
	
	return deck->card[SET_DECK_INDEX(deck->deck_index + deck_index)].use;
	
}

//---------------------------------------------------------------------------------
int Deck_GetCard(Deck deck) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return -1;
	if(deck->card_remain == 0) return -1;
	
	int ret;
	
	while(deck->card[deck->deck_index].use == true){
		deck->deck_index = NEXT_DECK_INDEX(deck->deck_index);
	}
	
	deck->card[deck->deck_index].use = true;
	deck->card_remain--;
	
	ret = deck->card[deck->deck_index].number;
	deck->deck_index = NEXT_DECK_INDEX(deck->deck_index);
	
	return ret;
	
	
}

//---------------------------------------------------------------------------------
int Deck_RequestCard(Deck deck, int card_number) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return -1;
	if(card_number < 0 || card_number >= deck->card_max) return -1;
	if(deck->card_remain == 0) return -1;
	
	int i;
	for(i = 0;i < deck->card_max;i++){
		if(deck->card[i].number == card_number && deck->card[i].use == false){
			deck->card[i].use = true;
			deck->card_remain--;
			return deck->card[i].number;
		}
	}
	
	return -1;
	
}


//---------------------------------------------------------------------------------
void Deck_SetCard(Deck deck, int card_number) {
//---------------------------------------------------------------------------------
	
	if(deck == NULL) return;
	if(card_number < 0 || card_number >= deck->card_max) return;
	if(deck->card_remain == deck->card_max) return;
	
	int i;
	Card temp ={0, false};
	
	
	//1,戻すカードの元ある位置にあるカード情報を一時退避する。
	//但し、使用中でないカードを戻す要求だった場合、処理を中断して関数を終了する。
	
	for(i = 0;i < deck->card_max;i++){
		if(deck->card[i].number == card_number){
			
			if(deck->card[i].use == false) return;
			
			deck->card[i].use = false;
			deck->card_remain++;
			temp = deck->card[i];
			break;
			
		}
	}
	
	
	//2,戻すカードの元あった位置を始点として現在のデッキ終点までの値を全て一つ前にずらす。
	
	while(i != PREV_DECK_INDEX(deck->deck_index)){
		deck_SwapCard(&deck->card[i], &deck->card[NEXT_DECK_INDEX(i)]);
		i = NEXT_DECK_INDEX(i);
	}
	
	
	//3,一時退避してた戻すカードの情報をデッキ終点へ書き込み関数を終了する。
	
	deck->card[ PREV_DECK_INDEX(deck->deck_index) ] = temp;
	
	
}

//---------------------------------------------------------------------------------
void deck_SwapCard(Card *a, Card *b) {
//---------------------------------------------------------------------------------
	
	Card temp;
	
	temp = *a;
	*a = *b;
	*b = temp;
	
}

//---------------------------------------------------------------------------------