俺々フレームワーク。トランプ。


俺々フレームワークシリーズ。
お題はトランプ。


ポーカーと神経衰弱ぐらいは作ってみたいなーと思って今週初めより設計を練り始めて見たものの
インスタンスの生成=カードデッキ1式とした辺りからどんどん深みにはまってくことに。


・デッキの一番上からカードを引く。引いたカードをデッキの一番下に戻す
・デッキから任意のカードを引いてくる(神経衰弱の出題を生成する場合)


という、現実にある動作だったり、ゲーム的に欲しい動作なんかが
実装の手間を生んでしまったような。
カードがダブらないようにする為のフォローとかも。


あと、カードといえば表と裏の2状態ある訳だが
ゲームによって必要・不要がまちまちだったので実装には含めず(ゲームプログラムの方で対処という形)。
カード情報を int 型だけでやり取り出来るところが狙い。


実装最中から思ってたけど定数を引数として可変可能とすれば
トランプに限らず、花札やUNOなんかにも生かせそう。
…継承を可能とするための更なる実装、という工程が増えるが(汗)。


Trump framework test


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


main.c

/*---------------------------------------------------------------------------------
	
	Trump framework test
	
	version 0.01
	May 14, 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[DECK_NUM + 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("Trump framework\n\nversion 0.01\nMay 14, 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_CreateDeck();
	
	Random random = Random_Create(GENERATOR_LCGS);
	clearValue();
	
	while(1){
		
		swiWaitForVBlank();
		scanKeys();
		
		//GetKeysDownRepeat
		kdr = keysDownRepeat();
		
		
		//GetCardNumber, GetCardUse & drawDeck
		drawDeck(trump);
		
		//GetCard
		if(kdr & KEY_A){
			
			if(card_index < DECK_NUM){
				
				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 < DECK_NUM){
				
				card_num[card_index] = Trump_RequestCard(trump, Random_GetValue(random) % DECK_NUM);
				
				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_ShuffleDeck(trump, 1, SHUFFLE_NUM);
			consoleSelect(&bottom_cons);
			printf("ShuffleDeck %d\n", SHUFFLE_NUM);
			
		}
		
		//ClearDeck
		if(kdr & KEY_START){
			
			Trump_ClearDeck(trump);
			clearValue();
			consoleSelect(&bottom_cons);
			printf("ClearDeck\n");
			
		//DestroyDeck
		}else if(kdr & KEY_SELECT){
			
			trump = Trump_DestroyDeck(trump);
			random = Random_Destroy(random);
			consoleSelect(&bottom_cons);
			printf("DestroyDeck & exit\n");
			return 0;
			
		}
		
		
	}
	
}

//---------------------------------------------------------------------------------
void clearValue(void) {
//---------------------------------------------------------------------------------
	
	int i;
	for(i = 0;i < DECK_NUM + 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 14, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _TRUMP_H_
#define _TRUMP_H_


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

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


typedef struct _Trump *Trump;


#ifdef __cplusplus
extern "C" {
#endif


//トランプデッキを生成・破棄する。
Trump Trump_CreateDeck(void);
Trump Trump_DestroyDeck(Trump trump);

//デッキを初期化する。
void Trump_ClearDeck(Trump trump);
	
//デッキをシャッフルする。
void Trump_ShuffleDeck(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 14, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

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


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

typedef struct _Trump{
	Card card[DECK_NUM];
	int card_remain;
	int deck_index;
	Random random;
}_Trump;


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

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


//---------------------------------------------------------------------------------
Trump Trump_CreateDeck(void) {
//---------------------------------------------------------------------------------
	
	Trump trump;
	
	trump = (Trump)malloc(sizeof(_Trump));
	
	trump->random = Random_Create(GENERATOR_LCGS);
	
	Trump_ClearDeck(trump);
	
	return trump;
	
}

//---------------------------------------------------------------------------------
Trump Trump_DestroyDeck(Trump trump) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return NULL;
	
	trump->random = Random_Destroy(trump->random);
	free(trump);
	
	return NULL;
	
}

//---------------------------------------------------------------------------------
void Trump_ClearDeck(Trump trump) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return;
	
	int i;
	for(i = 0;i < DECK_NUM;i++){
		trump->card[i].number = i;
		trump->card[i].use = false;
	}
	
	trump->card_remain = DECK_NUM;
	trump->deck_index = 0;
	
}

//---------------------------------------------------------------------------------
void Trump_ShuffleDeck(Trump trump, int seed, int shuffle_num) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return;
	
	int i, a, b;
	
	Random_SetSeed(trump->random, seed);
	
	for(i = 0;i < shuffle_num;i++){
		
		a = Random_GetValue(trump->random) % DECK_NUM;
		b = Random_GetValue(trump->random) % DECK_NUM;
		
		trump_SwapCard(&trump->card[a], &trump->card[b]);
		
	}
	
}

//---------------------------------------------------------------------------------
int Trump_GetCardRemain(Trump trump) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return -1;
	
	return trump->card_remain;
	
}

//---------------------------------------------------------------------------------
int Trump_GetCardNumber(Trump trump, int deck_index) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return -1;
	if(deck_index < 0 || deck_index >= DECK_NUM) return -1;
	
	return trump->card[SET_DECK_INDEX(trump->deck_index + deck_index)].number;
	
}

//---------------------------------------------------------------------------------
bool Trump_GetCardUse(Trump trump, int deck_index) {
//---------------------------------------------------------------------------------
	
	if(trump == NULL) return -1;
	if(deck_index < 0 || deck_index >= DECK_NUM) return -1;
	
	return trump->card[SET_DECK_INDEX(trump->deck_index + deck_index)].use;
	
}

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

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


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

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

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