ジャンケンフレームワーク。


今日はジャンケンフレームワークを書いてみました。
ジャンケンコードは昨年より、書いては捨ててを幾度か繰り返してたのですが
ようやく部品として取り扱えそうなものが出来ました。


今まで書いてきたものは1対1専用の一人称構造でしたが
今度のは複数人対戦を可能とした三人称構造としました。


・手がバラけた場合をあいこ判定とする
・勝ち負けが各プレイヤーにより異なる


という辺りで汚いコードを書いてしまってるかも知れません。
参考にしたソースも無いので、もっと綺麗な判定方法があるのかもです。


Janken framework test


サンプルコードを含むプロジェクト一式、ライブラリ・フレームワーク一式は
下記サイトからダウンロードできます。


Nitro Developer Style
http://page.freett.com/ntr/


ソース

main.c

/*---------------------------------------------------------------------------------
	
	Janken framework test
	
	version 0.01
	Jun 01, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <nds.h>
#include "fwmy/Janken.h"


#define PLAYER_MAX 3


const char *str_hand[] = {"GOO", "CHOKI", "PAR"};
const char *str_judge[] = {"MAKE", "AIKO", "KACHI"};


void drawJudge(Janken janken, int player_num);


//---------------------------------------------------------------------------------
int main(void){
//---------------------------------------------------------------------------------
	
	consoleDemoInit();
	printf("Janken framework test\n\nversion 0.01\nJun 01, 2010\n\nBy REGEKATSU\n\n\n");
	printf("usage:\nKEY_A: SetHand (random)\nKEY_B: Clear\nKEY_ST:Judge\nKEY_SL:Destroy & exit");
	
	srand(time(NULL));
	
	Janken janken = Janken_Create(PLAYER_MAX);
	drawJudge(janken, PLAYER_MAX);
	
	while(1){
		
		swiWaitForVBlank();
		scanKeys();
		
		if(keysDown() & KEY_A){
			int i;
			for(i = 0;i < PLAYER_MAX;i++){
				Janken_SetHand(janken, i, rand() % HAND_MAX);
			}
		}
		
		if(keysDown() & KEY_B){
			Janken_Clear(janken);
			drawJudge(janken, PLAYER_MAX);
		}
		
		if(keysDown() & KEY_START){
			Janken_Judge(janken);
			drawJudge(janken, PLAYER_MAX);
		}
		
		if(keysDown() & KEY_SELECT){
			Janken_Destroy(janken);
			return 0;
		}
		
	}
	
}

//---------------------------------------------------------------------------------
void drawJudge(Janken janken, int player_num){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return;
	
	int i;
	for(i = 0;i < player_num;i++){
		printf("\x01b[%d;0H\x01b[2Kplayer=%02d,hand=%s,judge=%s", 
			15 + i, i, str_hand[Janken_GetHand(janken, i)], str_judge[Janken_GetJudge(janken, i)]);
	}
	
}

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


Janken.h

/*---------------------------------------------------------------------------------
	
	janken framework header
	
	version 0.01
	Jun 01, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _JANKEN_H_
#define _JANKEN_H_


typedef struct _Janken *Janken;


typedef enum{
	JUDGE_MAKE = 0, 
	JUDGE_AIKO, 
	JUDGE_KACHI
}JUDGE_JANKEN;


typedef enum{
	HAND_GOO = 0, 
	HAND_CHOKI, 
	HAND_PAR, 
	HAND_MAX
}HAND_JANKEN;


#ifdef __cplusplus
extern "C" {
#endif


//ジャンケンの場を生成します。引数には参加プレイヤー数を指定します。
Janken Janken_Create(int player_num);
//ジャンケンの場を破棄します。
Janken Janken_Destroy(Janken janken);

//全プレイヤーの設定情報(ジャンケンの手、勝敗)をクリア(初期化)します。
void Janken_Clear(Janken janken);
//現在設定されてる、プレイヤーのジャンケンの手で勝敗を判定します。
void Janken_Judge(Janken janken);
//プレイヤーの、ジャンケンの手を設定します。
void Janken_SetHand(Janken janken, int player_no, int player_hand);
//プレイヤーの、現在のジャンケンの手を取得します。
int Janken_GetHand(Janken janken, int player_no);
//プレイヤーの、現在の勝敗を取得します。
int Janken_GetJudge(Janken janken, int player_no);


#ifdef __cplusplus
}
#endif

#endif	//_JANKEN_H_


Janken.c

/*---------------------------------------------------------------------------------

	janken framework routine
	
	version 0.01
	Jun 01, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdlib.h>
#include <string.h>
#include "Janken.h"


typedef struct{
	int hand;
	int judge;
}Player;

typedef struct _Janken{
	int player_num;
	Player *player;
}_Janken;


int janken_JudgeHand(int hand1, int hand2);


//---------------------------------------------------------------------------------
Janken Janken_Create(int player_num){
//---------------------------------------------------------------------------------
	
	Janken janken;
	
	janken =(Janken)malloc(sizeof(_Janken));
	
	janken->player_num = (player_num <= 1) ? 2 : player_num;
	janken->player = malloc(sizeof(Player) * janken->player_num);
	
	Janken_Clear(janken);
	
	return janken;
	
}

//---------------------------------------------------------------------------------
Janken Janken_Destroy(Janken janken){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return NULL;
	
	free(janken->player);
	free(janken);
	
	return NULL;
	
}

//---------------------------------------------------------------------------------
void Janken_Clear(Janken janken){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return;
	
	memset(&janken->player, 0, sizeof(Player) * janken->player_num);
	
}

//---------------------------------------------------------------------------------
void Janken_Judge(Janken janken){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return;
	
	
	int i, j, kind_hand[HAND_MAX], kind_sum, ather_hand = 0;
	
	
	memset(kind_hand, 0, sizeof(kind_hand));
	
	//全プレイヤーの出した手の種類を得る。
	for(i = 0;i < janken->player_num;i++){
		kind_hand[janken->player[i].hand] = 1;
	}
	
	//出された手の種類数を得る。
	kind_sum = 0;
	for(i = 0;i < HAND_MAX;i++){
		kind_sum += kind_hand[i];
	}
	
	//出された全ての手が1種のみ、または3種全てあった場合、「あいこ」とする。
	if(kind_sum != 2){
		
		for(i = 0;i < janken->player_num;i++){
			janken->player[i].judge = JUDGE_AIKO;
		}
		
	//2種の場合、強い手を「勝ち」とし、弱い手を「負け」とする。
	}else{
		
		for(i = 0;i < janken->player_num;i++){
			
			for(j = 0;j < HAND_MAX;j++){
				if(kind_hand[j] != 0 && janken->player[i].hand != j){
					ather_hand = j;
				}
			}
			
			janken->player[i].judge = janken_JudgeHand(janken->player[i].hand, ather_hand);
			
		}
		
	}
	
}

//---------------------------------------------------------------------------------
void Janken_SetHand(Janken janken, int player_no, int player_hand){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return;
	
	if(player_no < 0 || player_no >= janken->player_num) return;
	if(player_hand < HAND_GOO || player_hand >= HAND_MAX) return;
	
	janken->player[player_no].hand = player_hand;
	
}

//---------------------------------------------------------------------------------
int Janken_GetHand(Janken janken, int player_no){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return -1;
	
	if(player_no < 0 || player_no >= janken->player_num) return -1;
	
	return janken->player[player_no].hand;
	
}

//---------------------------------------------------------------------------------
int Janken_GetJudge(Janken janken, int player_no){
//---------------------------------------------------------------------------------
	
	if(janken == NULL) return -1;
	
	if(player_no < 0 || player_no >= janken->player_num) return -1;
	
	return janken->player[player_no].judge;
	
}

//---------------------------------------------------------------------------------
int janken_JudgeHand(int hand1, int hand2){
//---------------------------------------------------------------------------------
	
	int judge;
	
	if(hand1 == hand2){
		judge = JUDGE_AIKO;
	}else if((hand1 + 1) % 3 == hand2){
		judge = JUDGE_KACHI;
	}else{
		judge = JUDGE_MAKE;
	}
	
	return judge;
	
}

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